@@ -90,6 +90,10 @@ impl SyntaxContextData {
90
90
fn is_decode_placeholder ( & self ) -> bool {
91
91
self . dollar_crate_name == kw:: Empty
92
92
}
93
+
94
+ fn key ( & self ) -> SyntaxContextKey {
95
+ ( self . parent , self . outer_expn , self . outer_transparency )
96
+ }
93
97
}
94
98
95
99
rustc_index:: newtype_index! {
@@ -386,7 +390,7 @@ impl HygieneData {
386
390
expn_hash_to_expn_id : iter:: once ( ( ExpnHash ( Fingerprint :: ZERO ) , ExpnId :: root ( ) ) )
387
391
. collect ( ) ,
388
392
syntax_context_data : vec ! [ root_ctxt_data] ,
389
- syntax_context_map : FxHashMap :: default ( ) ,
393
+ syntax_context_map : iter :: once ( ( root_ctxt_data . key ( ) , SyntaxContext ( 0 ) ) ) . collect ( ) ,
390
394
expn_data_disambiguators : UnhashMap :: default ( ) ,
391
395
}
392
396
}
@@ -1436,35 +1440,39 @@ pub fn decode_syntax_context<D: Decoder, F: FnOnce(&mut D, u32) -> SyntaxContext
1436
1440
// Don't try to decode data while holding the lock, since we need to
1437
1441
// be able to recursively decode a SyntaxContext
1438
1442
let ctxt_data = decode_data ( d, raw_id) ;
1443
+ let ctxt_key = ctxt_data. key ( ) ;
1439
1444
1440
1445
let ctxt = HygieneData :: with ( |hygiene_data| {
1441
- let old = if let Some ( old) = hygiene_data. syntax_context_data . get ( raw_id as usize )
1442
- && old. outer_expn == ctxt_data. outer_expn
1443
- && old. outer_transparency == ctxt_data. outer_transparency
1444
- && old. parent == ctxt_data. parent
1445
- {
1446
- Some ( old. clone ( ) )
1447
- } else {
1448
- None
1449
- } ;
1450
- // Overwrite its placeholder data with our decoded data.
1451
- let ctxt_data_ref = & mut hygiene_data. syntax_context_data [ pending_ctxt. as_u32 ( ) as usize ] ;
1452
- let prev_ctxt_data = mem:: replace ( ctxt_data_ref, ctxt_data) ;
1453
- // Reset `dollar_crate_name` so that it will be updated by `update_dollar_crate_names`.
1454
- // We don't care what the encoding crate set this to - we want to resolve it
1455
- // from the perspective of the current compilation session
1456
- ctxt_data_ref. dollar_crate_name = kw:: DollarCrate ;
1457
- if let Some ( old) = old {
1458
- * ctxt_data_ref = old;
1459
- }
1460
- // Make sure nothing weird happened while `decode_data` was running.
1461
- if !prev_ctxt_data. is_decode_placeholder ( ) {
1462
- // With parallel compiler another thread may have already inserted the decoded
1463
- // data, but the decoded data should match.
1464
- assert ! ( cfg!( parallel_compiler) ) ;
1465
- assert_eq ! ( prev_ctxt_data, * ctxt_data_ref) ;
1446
+ match hygiene_data. syntax_context_map . get ( & ctxt_key) {
1447
+ // Ensure that syntax contexts are unique.
1448
+ // If syntax contexts with the given key already exists, reuse it instead of
1449
+ // using `pending_ctxt`.
1450
+ // `pending_ctxt` will leave an unused hole in the vector of syntax contexts.
1451
+ // Hopefully its value isn't stored anywhere during decoding and its dummy data
1452
+ // is never accessed later. The `is_decode_placeholder` asserts on all
1453
+ // accesses to syntax context data attempt to ensure it.
1454
+ Some ( & ctxt) => ctxt,
1455
+ // This is a completely new context.
1456
+ // Overwrite its placeholder data with our decoded data.
1457
+ None => {
1458
+ let ctxt_data_ref =
1459
+ & mut hygiene_data. syntax_context_data [ pending_ctxt. as_u32 ( ) as usize ] ;
1460
+ let prev_ctxt_data = mem:: replace ( ctxt_data_ref, ctxt_data) ;
1461
+ // Reset `dollar_crate_name` so that it will be updated by `update_dollar_crate_names`.
1462
+ // We don't care what the encoding crate set this to - we want to resolve it
1463
+ // from the perspective of the current compilation session
1464
+ ctxt_data_ref. dollar_crate_name = kw:: DollarCrate ;
1465
+ // Make sure nothing weird happened while `decode_data` was running.
1466
+ if !prev_ctxt_data. is_decode_placeholder ( ) {
1467
+ // With parallel compiler another thread may have already inserted the decoded
1468
+ // data, but the decoded data should match.
1469
+ assert ! ( cfg!( parallel_compiler) ) ;
1470
+ assert_eq ! ( prev_ctxt_data, * ctxt_data_ref) ;
1471
+ }
1472
+ hygiene_data. syntax_context_map . insert ( ctxt_key, pending_ctxt) ;
1473
+ pending_ctxt
1474
+ }
1466
1475
}
1467
- pending_ctxt
1468
1476
} ) ;
1469
1477
1470
1478
// Mark the context as completed
0 commit comments