@@ -54,11 +54,21 @@ pub struct SyntaxContext(u32);
54
54
impl !Ord for SyntaxContext { }
55
55
impl !PartialOrd for SyntaxContext { }
56
56
57
- #[ derive( Debug , Encodable , Decodable , Clone ) ]
58
- pub struct SyntaxContextData {
57
+ #[ derive( Debug , Encodable , Decodable , Clone , Copy , Hash , PartialEq , Eq ) ]
58
+ pub struct SyntaxContextKey {
59
59
outer_expn : ExpnId ,
60
60
outer_transparency : Transparency ,
61
61
parent : SyntaxContext ,
62
+ }
63
+
64
+ impl SyntaxContextKey {
65
+ fn new ( outer_expn : ExpnId , outer_transparency : Transparency , parent : SyntaxContext ) -> Self {
66
+ SyntaxContextKey { outer_expn, outer_transparency, parent }
67
+ }
68
+ }
69
+
70
+ #[ derive( Debug , Encodable , Decodable , Clone , Copy ) ]
71
+ pub struct SyntaxContextData {
62
72
/// This context, but with all transparent and semi-transparent expansions filtered away.
63
73
opaque : SyntaxContext ,
64
74
/// This context, but with all transparent expansions filtered away.
@@ -332,8 +342,9 @@ pub(crate) struct HygieneData {
332
342
foreign_expn_data : FxHashMap < ExpnId , ExpnData > ,
333
343
foreign_expn_hashes : FxHashMap < ExpnId , ExpnHash > ,
334
344
expn_hash_to_expn_id : UnhashMap < ExpnHash , ExpnId > ,
335
- syntax_context_data : Vec < SyntaxContextData > ,
336
- syntax_context_map : FxHashMap < ( SyntaxContext , ExpnId , Transparency ) , SyntaxContext > ,
345
+ syntax_context_data : Vec < ( SyntaxContextKey , SyntaxContextData ) > ,
346
+ syntax_context_data_map : FxHashMap < SyntaxContextKey , SyntaxContextData > ,
347
+ syntax_context_map : FxHashMap < SyntaxContextKey , SyntaxContext > ,
337
348
/// Maps the `local_hash` of an `ExpnData` to the next disambiguator value.
338
349
/// This is used by `update_disambiguator` to keep track of which `ExpnData`s
339
350
/// would have collisions without a disambiguator.
@@ -359,14 +370,19 @@ impl HygieneData {
359
370
foreign_expn_hashes : FxHashMap :: default ( ) ,
360
371
expn_hash_to_expn_id : std:: iter:: once ( ( ExpnHash ( Fingerprint :: ZERO ) , ExpnId :: root ( ) ) )
361
372
. collect ( ) ,
362
- syntax_context_data : vec ! [ SyntaxContextData {
363
- outer_expn: ExpnId :: root( ) ,
364
- outer_transparency: Transparency :: Opaque ,
365
- parent: SyntaxContext ( 0 ) ,
366
- opaque: SyntaxContext ( 0 ) ,
367
- opaque_and_semitransparent: SyntaxContext ( 0 ) ,
368
- dollar_crate_name: kw:: DollarCrate ,
369
- } ] ,
373
+ syntax_context_data : vec ! [ (
374
+ SyntaxContextKey {
375
+ outer_expn: ExpnId :: root( ) ,
376
+ outer_transparency: Transparency :: Opaque ,
377
+ parent: SyntaxContext ( 0 ) ,
378
+ } ,
379
+ SyntaxContextData {
380
+ opaque: SyntaxContext ( 0 ) ,
381
+ opaque_and_semitransparent: SyntaxContext ( 0 ) ,
382
+ dollar_crate_name: kw:: DollarCrate ,
383
+ } ,
384
+ ) ] ,
385
+ syntax_context_data_map : FxHashMap :: default ( ) ,
370
386
syntax_context_map : FxHashMap :: default ( ) ,
371
387
expn_data_disambiguators : UnhashMap :: default ( ) ,
372
388
}
@@ -416,24 +432,24 @@ impl HygieneData {
416
432
}
417
433
418
434
fn normalize_to_macros_2_0 ( & self , ctxt : SyntaxContext ) -> SyntaxContext {
419
- self . syntax_context_data [ ctxt. 0 as usize ] . opaque
435
+ self . syntax_context_data [ ctxt. 0 as usize ] . 1 . opaque
420
436
}
421
437
422
438
fn normalize_to_macro_rules ( & self , ctxt : SyntaxContext ) -> SyntaxContext {
423
- self . syntax_context_data [ ctxt. 0 as usize ] . opaque_and_semitransparent
439
+ self . syntax_context_data [ ctxt. 0 as usize ] . 1 . opaque_and_semitransparent
424
440
}
425
441
426
442
fn outer_expn ( & self , ctxt : SyntaxContext ) -> ExpnId {
427
- self . syntax_context_data [ ctxt. 0 as usize ] . outer_expn
443
+ self . syntax_context_data [ ctxt. 0 as usize ] . 0 . outer_expn
428
444
}
429
445
430
446
fn outer_mark ( & self , ctxt : SyntaxContext ) -> ( ExpnId , Transparency ) {
431
- let data = & self . syntax_context_data [ ctxt. 0 as usize ] ;
447
+ let data = & self . syntax_context_data [ ctxt. 0 as usize ] . 0 ;
432
448
( data. outer_expn , data. outer_transparency )
433
449
}
434
450
435
451
fn parent_ctxt ( & self , ctxt : SyntaxContext ) -> SyntaxContext {
436
- self . syntax_context_data [ ctxt. 0 as usize ] . parent
452
+ self . syntax_context_data [ ctxt. 0 as usize ] . 0 . parent
437
453
}
438
454
439
455
fn remove_mark ( & self , ctxt : & mut SyntaxContext ) -> ( ExpnId , Transparency ) {
@@ -542,61 +558,55 @@ impl HygieneData {
542
558
transparency : Transparency ,
543
559
) -> SyntaxContext {
544
560
let syntax_context_data = & mut self . syntax_context_data ;
545
- let mut opaque = syntax_context_data[ ctxt. 0 as usize ] . opaque ;
561
+ let mut opaque = syntax_context_data[ ctxt. 0 as usize ] . 1 . opaque ;
546
562
let mut opaque_and_semitransparent =
547
- syntax_context_data[ ctxt. 0 as usize ] . opaque_and_semitransparent ;
563
+ syntax_context_data[ ctxt. 0 as usize ] . 1 . opaque_and_semitransparent ;
548
564
549
565
if transparency >= Transparency :: Opaque {
550
566
let parent = opaque;
551
- opaque = * self
552
- . syntax_context_map
553
- . entry ( ( parent, expn_id, transparency) )
554
- . or_insert_with ( || {
555
- let new_opaque = SyntaxContext ( syntax_context_data. len ( ) as u32 ) ;
556
- syntax_context_data. push ( SyntaxContextData {
557
- outer_expn : expn_id,
558
- outer_transparency : transparency,
559
- parent,
560
- opaque : new_opaque,
561
- opaque_and_semitransparent : new_opaque,
562
- dollar_crate_name : kw:: DollarCrate ,
563
- } ) ;
564
- new_opaque
565
- } ) ;
567
+ let key = SyntaxContextKey :: new ( expn_id, transparency, parent) ;
568
+ opaque = * self . syntax_context_map . entry ( key) . or_insert_with ( || {
569
+ let new_opaque = SyntaxContext ( syntax_context_data. len ( ) as u32 ) ;
570
+ let data = SyntaxContextData {
571
+ opaque : new_opaque,
572
+ opaque_and_semitransparent : new_opaque,
573
+ dollar_crate_name : kw:: DollarCrate ,
574
+ } ;
575
+ syntax_context_data. push ( ( key, data) ) ;
576
+ self . syntax_context_data_map . insert ( key, data) ;
577
+ new_opaque
578
+ } ) ;
566
579
}
567
580
568
581
if transparency >= Transparency :: SemiTransparent {
569
582
let parent = opaque_and_semitransparent;
570
- opaque_and_semitransparent = * self
571
- . syntax_context_map
572
- . entry ( ( parent, expn_id, transparency) )
573
- . or_insert_with ( || {
574
- let new_opaque_and_semitransparent =
575
- SyntaxContext ( syntax_context_data. len ( ) as u32 ) ;
576
- syntax_context_data. push ( SyntaxContextData {
577
- outer_expn : expn_id,
578
- outer_transparency : transparency,
579
- parent,
580
- opaque,
581
- opaque_and_semitransparent : new_opaque_and_semitransparent,
582
- dollar_crate_name : kw:: DollarCrate ,
583
- } ) ;
584
- new_opaque_and_semitransparent
585
- } ) ;
583
+ let key = SyntaxContextKey :: new ( expn_id, transparency, parent) ;
584
+ opaque_and_semitransparent = * self . syntax_context_map . entry ( key) . or_insert_with ( || {
585
+ let new_opaque_and_semitransparent =
586
+ SyntaxContext ( syntax_context_data. len ( ) as u32 ) ;
587
+ let data = SyntaxContextData {
588
+ opaque,
589
+ opaque_and_semitransparent : new_opaque_and_semitransparent,
590
+ dollar_crate_name : kw:: DollarCrate ,
591
+ } ;
592
+ syntax_context_data. push ( ( key, data) ) ;
593
+ self . syntax_context_data_map . insert ( key, data) ;
594
+ new_opaque_and_semitransparent
595
+ } ) ;
586
596
}
587
597
588
598
let parent = ctxt;
589
- * self . syntax_context_map . entry ( ( parent, expn_id, transparency) ) . or_insert_with ( || {
599
+ let key = SyntaxContextKey :: new ( expn_id, transparency, parent) ;
600
+ * self . syntax_context_map . entry ( key) . or_insert_with ( || {
590
601
let new_opaque_and_semitransparent_and_transparent =
591
602
SyntaxContext ( syntax_context_data. len ( ) as u32 ) ;
592
- syntax_context_data. push ( SyntaxContextData {
593
- outer_expn : expn_id,
594
- outer_transparency : transparency,
595
- parent,
603
+ let data = SyntaxContextData {
596
604
opaque,
597
605
opaque_and_semitransparent,
598
606
dollar_crate_name : kw:: DollarCrate ,
599
- } ) ;
607
+ } ;
608
+ syntax_context_data. push ( ( key, data) ) ;
609
+ self . syntax_context_data_map . insert ( key, data) ;
600
610
new_opaque_and_semitransparent_and_transparent
601
611
} )
602
612
}
@@ -623,7 +633,7 @@ pub fn update_dollar_crate_names(mut get_name: impl FnMut(SyntaxContext) -> Symb
623
633
data. syntax_context_data
624
634
. iter ( )
625
635
. rev ( )
626
- . take_while ( |scdata| scdata. dollar_crate_name == kw:: DollarCrate )
636
+ . take_while ( |scdata| scdata. 1 . dollar_crate_name == kw:: DollarCrate )
627
637
. count ( ) ,
628
638
)
629
639
} ) ;
@@ -634,7 +644,7 @@ pub fn update_dollar_crate_names(mut get_name: impl FnMut(SyntaxContext) -> Symb
634
644
range_to_update. clone ( ) . map ( |idx| get_name ( SyntaxContext :: from_u32 ( idx as u32 ) ) ) . collect ( ) ;
635
645
HygieneData :: with ( |data| {
636
646
range_to_update. zip ( names) . for_each ( |( idx, name) | {
637
- data. syntax_context_data [ idx] . dollar_crate_name = name;
647
+ data. syntax_context_data [ idx] . 1 . dollar_crate_name = name;
638
648
} )
639
649
} )
640
650
}
@@ -670,7 +680,7 @@ pub fn debug_hygiene_data(verbose: bool) -> String {
670
680
data. syntax_context_data . iter ( ) . enumerate ( ) . for_each ( |( id, ctxt) | {
671
681
s. push_str ( & format ! (
672
682
"\n #{}: parent: {:?}, outer_mark: ({:?}, {:?})" ,
673
- id, ctxt. parent, ctxt. outer_expn, ctxt. outer_transparency,
683
+ id, ctxt. 0 . parent, ctxt. 0 . outer_expn, ctxt. 0 . outer_transparency,
674
684
) ) ;
675
685
} ) ;
676
686
s
@@ -884,7 +894,7 @@ impl SyntaxContext {
884
894
}
885
895
886
896
pub ( crate ) fn dollar_crate_name ( self ) -> Symbol {
887
- HygieneData :: with ( |data| data. syntax_context_data [ self . 0 as usize ] . dollar_crate_name )
897
+ HygieneData :: with ( |data| data. syntax_context_data [ self . 0 as usize ] . 1 . dollar_crate_name )
888
898
}
889
899
890
900
pub fn edition ( self ) -> Edition {
@@ -1210,7 +1220,7 @@ impl HygieneEncodeContext {
1210
1220
pub fn encode < T > (
1211
1221
& self ,
1212
1222
encoder : & mut T ,
1213
- mut encode_ctxt : impl FnMut ( & mut T , u32 , & SyntaxContextData ) ,
1223
+ mut encode_ctxt : impl FnMut ( & mut T , u32 , & ( SyntaxContextKey , SyntaxContextData ) ) ,
1214
1224
mut encode_expn : impl FnMut ( & mut T , ExpnId , & ExpnData , ExpnHash ) ,
1215
1225
) {
1216
1226
// When we serialize a `SyntaxContextData`, we may end up serializing
@@ -1342,10 +1352,15 @@ pub fn decode_expn_id(
1342
1352
// to track which `SyntaxContext`s we have already decoded.
1343
1353
// The provided closure will be invoked to deserialize a `SyntaxContextData`
1344
1354
// if we haven't already seen the id of the `SyntaxContext` we are deserializing.
1345
- pub fn decode_syntax_context < D : Decoder , F : FnOnce ( & mut D , u32 ) -> SyntaxContextData > (
1355
+ pub fn decode_syntax_context <
1356
+ D : Decoder ,
1357
+ F0 : FnOnce ( & mut D , u32 ) -> SyntaxContextKey ,
1358
+ F1 : FnOnce ( & mut D , u32 ) -> SyntaxContextData ,
1359
+ > (
1346
1360
d : & mut D ,
1347
1361
context : & HygieneDecodeContext ,
1348
- decode_data : F ,
1362
+ decode_ctxt_key : F0 ,
1363
+ decode_ctxt_data : F1 ,
1349
1364
) -> SyntaxContext {
1350
1365
let raw_id: u32 = Decodable :: decode ( d) ;
1351
1366
if raw_id == 0 {
@@ -1387,16 +1402,20 @@ pub fn decode_syntax_context<D: Decoder, F: FnOnce(&mut D, u32) -> SyntaxContext
1387
1402
// as the SyntaxContextData may reference itself.
1388
1403
let new_ctxt = HygieneData :: with ( |hygiene_data| {
1389
1404
let new_ctxt = SyntaxContext ( hygiene_data. syntax_context_data . len ( ) as u32 ) ;
1390
- // Push a dummy SyntaxContextData to ensure that nobody else can get the
1391
- // same ID as us. This will be overwritten after call `decode_Data`
1392
- hygiene_data. syntax_context_data . push ( SyntaxContextData {
1393
- outer_expn : ExpnId :: root ( ) ,
1394
- outer_transparency : Transparency :: Transparent ,
1395
- parent : SyntaxContext :: root ( ) ,
1396
- opaque : SyntaxContext :: root ( ) ,
1397
- opaque_and_semitransparent : SyntaxContext :: root ( ) ,
1398
- dollar_crate_name : kw:: Empty ,
1399
- } ) ;
1405
+ // Push a dummy data to ensure that nobody else can get the
1406
+ // same ID as us. `SyntaxContextKey` will be overwritten after call `decode_Data`
1407
+ hygiene_data. syntax_context_data . push ( (
1408
+ SyntaxContextKey {
1409
+ outer_expn : ExpnId :: root ( ) ,
1410
+ outer_transparency : Transparency :: Transparent ,
1411
+ parent : SyntaxContext :: root ( ) ,
1412
+ } ,
1413
+ SyntaxContextData {
1414
+ opaque : SyntaxContext :: root ( ) ,
1415
+ opaque_and_semitransparent : SyntaxContext :: root ( ) ,
1416
+ dollar_crate_name : kw:: Empty ,
1417
+ } ,
1418
+ ) ) ;
1400
1419
new_ctxt
1401
1420
} ) ;
1402
1421
entry. insert ( new_ctxt) ;
@@ -1407,33 +1426,25 @@ pub fn decode_syntax_context<D: Decoder, F: FnOnce(&mut D, u32) -> SyntaxContext
1407
1426
1408
1427
// Don't try to decode data while holding the lock, since we need to
1409
1428
// be able to recursively decode a SyntaxContext
1410
- let mut ctxt_data = decode_data ( d, raw_id) ;
1411
- // Reset `dollar_crate_name` so that it will be updated by `update_dollar_crate_names`
1412
- // We don't care what the encoding crate set this to - we want to resolve it
1413
- // from the perspective of the current compilation session
1414
- ctxt_data . dollar_crate_name = kw :: DollarCrate ;
1429
+ let ctxt_key = decode_ctxt_key ( d, raw_id) ;
1430
+ let ctxt_data = HygieneData :: with ( |hygiene_data| {
1431
+ hygiene_data . syntax_context_data_map . get ( & ctxt_key ) . copied ( )
1432
+ } )
1433
+ . unwrap_or_else ( || decode_ctxt_data ( d , raw_id ) ) ;
1415
1434
1416
1435
// Overwrite the dummy data with our decoded SyntaxContextData
1417
1436
HygieneData :: with ( |hygiene_data| {
1418
- if let Some ( old) = hygiene_data. syntax_context_data . get ( raw_id as usize )
1419
- && old. outer_expn == ctxt_data. outer_expn
1420
- && old. outer_transparency == ctxt_data. outer_transparency
1421
- && old. parent == ctxt_data. parent
1422
- {
1423
- ctxt_data = old. clone ( ) ;
1424
- }
1425
-
1426
1437
let dummy = std:: mem:: replace (
1427
1438
& mut hygiene_data. syntax_context_data [ ctxt. as_u32 ( ) as usize ] ,
1428
- ctxt_data,
1439
+ ( ctxt_key , ctxt_data) ,
1429
1440
) ;
1430
1441
if cfg ! ( not( parallel_compiler) ) {
1431
1442
// Make sure nothing weird happened while `decode_data` was running.
1432
1443
// We used `kw::Empty` for the dummy value and we expect nothing to be
1433
1444
// modifying the dummy entry.
1434
1445
// This does not hold for the parallel compiler as another thread may
1435
1446
// have inserted the fully decoded data.
1436
- assert_eq ! ( dummy. dollar_crate_name, kw:: Empty ) ;
1447
+ assert_eq ! ( dummy. 1 . dollar_crate_name, kw:: Empty ) ;
1437
1448
}
1438
1449
} ) ;
1439
1450
@@ -1452,7 +1463,7 @@ pub fn decode_syntax_context<D: Decoder, F: FnOnce(&mut D, u32) -> SyntaxContext
1452
1463
ctxt
1453
1464
}
1454
1465
1455
- fn for_all_ctxts_in < F : FnMut ( u32 , SyntaxContext , & SyntaxContextData ) > (
1466
+ fn for_all_ctxts_in < F : FnMut ( u32 , SyntaxContext , & ( SyntaxContextKey , SyntaxContextData ) ) > (
1456
1467
ctxts : impl Iterator < Item = SyntaxContext > ,
1457
1468
mut f : F ,
1458
1469
) {
0 commit comments