@@ -19,6 +19,10 @@ use rustc_span::Span;
1919
2020use std:: cell:: Cell ;
2121use std:: iter;
22+ #[ cfg( debug_assertions) ]
23+ use std:: ops:: BitXor ;
24+ #[ cfg( debug_assertions) ]
25+ use std:: sync:: atomic:: { AtomicU32 , Ordering } ;
2226
2327pub struct MarkedAttrs ( GrowableBitSet < AttrId > ) ;
2428
@@ -350,17 +354,36 @@ pub fn mk_nested_word_item(ident: Ident) -> NestedMetaItem {
350354
351355pub struct AttrIdGenerator ( WorkerLocal < Cell < u32 > > ) ;
352356
357+ #[ cfg( debug_assertions) ]
358+ static MAX_ATTR_ID : AtomicU32 = AtomicU32 :: new ( u32:: MAX ) ;
359+
353360impl AttrIdGenerator {
354361 pub fn new ( ) -> Self {
355362 // We use `(index as u32).reverse_bits()` to initialize the
356363 // starting value of AttrId in each worker thread.
357364 // The `index` is the index of the worker thread.
358365 // This ensures that the AttrId generated in each thread is unique.
359- AttrIdGenerator ( WorkerLocal :: new ( |index| Cell :: new ( ( index as u32 ) . reverse_bits ( ) ) ) )
366+ AttrIdGenerator ( WorkerLocal :: new ( |index| {
367+ let index: u32 = index. try_into ( ) . unwrap ( ) ;
368+
369+ #[ cfg( debug_assertions) ]
370+ {
371+ let max_id = ( ( index + 1 ) . next_power_of_two ( ) - 1 ) . bitxor ( u32:: MAX ) . reverse_bits ( ) ;
372+ MAX_ATTR_ID . fetch_min ( max_id, Ordering :: Release ) ;
373+ }
374+
375+ Cell :: new ( index. reverse_bits ( ) )
376+ } ) )
360377 }
361378
362379 pub fn mk_attr_id ( & self ) -> AttrId {
363380 let id = self . 0 . get ( ) ;
381+
382+ // Ensure the assigned attr_id does not overlap the bits
383+ // representing the number of threads.
384+ #[ cfg( debug_assertions) ]
385+ assert ! ( id <= MAX_ATTR_ID . load( Ordering :: Acquire ) ) ;
386+
364387 self . 0 . set ( id + 1 ) ;
365388 AttrId :: from_u32 ( id)
366389 }
0 commit comments