@@ -11,11 +11,13 @@ use crate::tokenstream::{DelimSpan, Spacing, TokenTree};
11
11
use crate :: tokenstream:: { LazyAttrTokenStream , TokenStream } ;
12
12
use crate :: util:: comments;
13
13
14
+ use rustc_data_structures:: sync:: WorkerLocal ;
14
15
use rustc_index:: bit_set:: GrowableBitSet ;
15
16
use rustc_span:: source_map:: BytePos ;
16
17
use rustc_span:: symbol:: { sym, Ident , Symbol } ;
17
18
use rustc_span:: Span ;
18
19
20
+ use std:: cell:: Cell ;
19
21
use std:: iter;
20
22
21
23
pub struct MarkedAttrs ( GrowableBitSet < AttrId > ) ;
@@ -346,52 +348,67 @@ pub fn mk_nested_word_item(ident: Ident) -> NestedMetaItem {
346
348
NestedMetaItem :: MetaItem ( mk_word_item ( ident) )
347
349
}
348
350
349
- pub ( crate ) fn mk_attr_id ( ) -> AttrId {
350
- use std:: sync:: atomic:: AtomicU32 ;
351
- use std:: sync:: atomic:: Ordering ;
351
+ pub struct AttrIdGenerator ( WorkerLocal < Cell < u32 > > ) ;
352
352
353
- static NEXT_ATTR_ID : AtomicU32 = AtomicU32 :: new ( 0 ) ;
353
+ impl AttrIdGenerator {
354
+ pub fn new ( ) -> Self {
355
+ // We use `(index as u32).reverse_bits()` to initialize the
356
+ // starting value of AttrId in each worker thread.
357
+ // The `index` is the index of the worker thread.
358
+ // This ensures that the AttrId generated in each thread is unique.
359
+ AttrIdGenerator ( WorkerLocal :: new ( |index| Cell :: new ( ( index as u32 ) . reverse_bits ( ) ) ) )
360
+ }
354
361
355
- let id = NEXT_ATTR_ID . fetch_add ( 1 , Ordering :: SeqCst ) ;
356
- assert ! ( id != u32 :: MAX ) ;
357
- AttrId :: from_u32 ( id)
362
+ pub fn mk_attr_id ( & self ) -> AttrId {
363
+ let id = self . 0 . get ( ) ;
364
+ self . 0 . set ( id + 1 ) ;
365
+ AttrId :: from_u32 ( id)
366
+ }
358
367
}
359
368
360
- pub fn mk_attr ( style : AttrStyle , path : Path , args : MacArgs , span : Span ) -> Attribute {
361
- mk_attr_from_item ( AttrItem { path, args, tokens : None } , None , style, span)
369
+ pub fn mk_attr (
370
+ g : & AttrIdGenerator ,
371
+ style : AttrStyle ,
372
+ path : Path ,
373
+ args : MacArgs ,
374
+ span : Span ,
375
+ ) -> Attribute {
376
+ mk_attr_from_item ( g, AttrItem { path, args, tokens : None } , None , style, span)
362
377
}
363
378
364
379
pub fn mk_attr_from_item (
380
+ g : & AttrIdGenerator ,
365
381
item : AttrItem ,
366
382
tokens : Option < LazyAttrTokenStream > ,
367
383
style : AttrStyle ,
368
384
span : Span ,
369
385
) -> Attribute {
370
386
Attribute {
371
387
kind : AttrKind :: Normal ( P ( ast:: NormalAttr { item, tokens } ) ) ,
372
- id : mk_attr_id ( ) ,
388
+ id : g . mk_attr_id ( ) ,
373
389
style,
374
390
span,
375
391
}
376
392
}
377
393
378
394
/// Returns an inner attribute with the given value and span.
379
- pub fn mk_attr_inner ( item : MetaItem ) -> Attribute {
380
- mk_attr ( AttrStyle :: Inner , item. path , item. kind . mac_args ( item. span ) , item. span )
395
+ pub fn mk_attr_inner ( g : & AttrIdGenerator , item : MetaItem ) -> Attribute {
396
+ mk_attr ( g , AttrStyle :: Inner , item. path , item. kind . mac_args ( item. span ) , item. span )
381
397
}
382
398
383
399
/// Returns an outer attribute with the given value and span.
384
- pub fn mk_attr_outer ( item : MetaItem ) -> Attribute {
385
- mk_attr ( AttrStyle :: Outer , item. path , item. kind . mac_args ( item. span ) , item. span )
400
+ pub fn mk_attr_outer ( g : & AttrIdGenerator , item : MetaItem ) -> Attribute {
401
+ mk_attr ( g , AttrStyle :: Outer , item. path , item. kind . mac_args ( item. span ) , item. span )
386
402
}
387
403
388
404
pub fn mk_doc_comment (
405
+ g : & AttrIdGenerator ,
389
406
comment_kind : CommentKind ,
390
407
style : AttrStyle ,
391
408
data : Symbol ,
392
409
span : Span ,
393
410
) -> Attribute {
394
- Attribute { kind : AttrKind :: DocComment ( comment_kind, data) , id : mk_attr_id ( ) , style, span }
411
+ Attribute { kind : AttrKind :: DocComment ( comment_kind, data) , id : g . mk_attr_id ( ) , style, span }
395
412
}
396
413
397
414
pub fn list_contains_name ( items : & [ NestedMetaItem ] , name : Symbol ) -> bool {
0 commit comments