The SymbolId space is split between three allocators by convention, with no cross-check
Limitation
SymbolId is a u32 newtype whose range is partitioned by comment
(symbols.rs): builtins occupy 1-99, 1000 + is the name resolver's, and
0x4000_0000 + is the overload allocator's. A third allocator, in
type_engine, hands block-local struct/enum ids from the top of the u32
space counting down (fresh_local_type_id, saturating_sub). The three are
independent, and only a unit test asserts one boundary (second.0 < OVERLOAD_SYM_START). At runtime:
SymbolTable::internadvances withnext_id += 1on au32: it panics on overflow in a debug build and wraps in a release build;- the overload counter's
fetch_addwraps silently; - nothing checks that the resolver's range stays below
OVERLOAD_SYM_STARTor that the two ascending allocators stay clear of the descending one; SymbolTable.mapis apubfield, so code outside the type can insert an id that bypassesinternand the counter entirely.
Impact
Purely theoretical at realistic sizes: the resolver range would have to reach
about 1.07 billion declarations before it met the overload range. The risk is
structural, not practical: identity uniqueness rests on three allocators
respecting comment-level ranges, so a future change that adds a fourth
allocator, widens a range or inserts into map directly has no safety net.
There is no observable symptom, so no reproducing fixture.
Affects
arch.name-resolution.requirement-1metel-frontend/src/identity/symbols.rs(SymbolTable,USER_SYM_START,OVERLOAD_SYM_START)metel-frontend/src/pipeline/type_checking/type_engine/mod.rs(fresh_local_type_id)
Resolution
None yet. Typed allocators (one owner for the whole space, with range checks
and a private map) would turn the convention into an invariant.