mutableなRange(0..)をIteratorとして使う小技があるけど
オーバーフローは意識したことないな

fn new_id() -> Option<usize> {
use std::cell::RefCell;
use std::ops::RangeInclusive;

thread_local! {
static ID: RefCell<RangeInclusive<usize>> = RefCell::new(0..=usize::MAX);
}

ID.with_borrow_mut(|ids| ids.next())
}