That's fair! If looked at from that angle though, I think that https://doc.rust-lang.org/reference/items.html kind of answers this. For items declared within functions or other scopes, "The meaning of these scoped items is the same as if the item was declared outside the scope."
That statement could still be interpreted multiple ways, but I think the way I'd read it confirms what you've discovered: per
static declaration in your code, there's exactly one static item, and thus exactly one memory location representing that static.
Or in other words, the
static declaration is not at all modified (including by duplication) by being inside a generic block.
I think we can still solve this, though it needs more complexity. Rust won't create N static memory locations, but we can disambiguate a single one.
I think one common-ish pattern is to use
Any::type_id for this. If you store a
HashMap<TypeId, u32>, you can use a single static to support all counters.
For a full solution, I'd recommend also replacing
static mut with a
<Mutex<...>>@17cupsofcoffee said, though,
static mut itself is really hard to get right in Rust. Using a safe abstraction like
OnceCell for initialization and
Mutex for synchronization will avoid that.