@@ -93,6 +93,10 @@ impl SyntaxContextData {
93
93
fn is_decode_placeholder ( & self ) -> bool {
94
94
self . dollar_crate_name == kw:: Empty
95
95
}
96
+
97
+ fn key ( & self ) -> SyntaxContextKey {
98
+ ( self . parent , self . outer_expn , self . outer_transparency )
99
+ }
96
100
}
97
101
98
102
rustc_index:: newtype_index! {
@@ -395,7 +399,7 @@ impl HygieneData {
395
399
expn_hash_to_expn_id : iter:: once ( ( ExpnHash ( Fingerprint :: ZERO ) , ExpnId :: root ( ) ) )
396
400
. collect ( ) ,
397
401
syntax_context_data : vec ! [ root_ctxt_data] ,
398
- syntax_context_map : FxHashMap :: default ( ) ,
402
+ syntax_context_map : iter :: once ( ( root_ctxt_data . key ( ) , SyntaxContext ( 0 ) ) ) . collect ( ) ,
399
403
expn_data_disambiguators : UnhashMap :: default ( ) ,
400
404
}
401
405
}
@@ -1449,34 +1453,38 @@ pub fn decode_syntax_context<D: Decoder, F: FnOnce(&mut D, u32) -> SyntaxContext
1449
1453
// Don't try to decode data while holding the lock, since we need to
1450
1454
// be able to recursively decode a SyntaxContext
1451
1455
let ctxt_data = decode_data ( d, raw_id) ;
1456
+ let ctxt_key = ctxt_data. key ( ) ;
1452
1457
1453
1458
let ctxt = HygieneData :: with ( |hygiene_data| {
1454
- let old = if let Some ( old) = hygiene_data. syntax_context_data . get ( raw_id as usize )
1455
- && old. outer_expn == ctxt_data. outer_expn
1456
- && old. outer_transparency == ctxt_data. outer_transparency
1457
- && old. parent == ctxt_data. parent
1458
- {
1459
- Some ( old. clone ( ) )
1460
- } else {
1461
- None
1462
- } ;
1463
- // Overwrite its placeholder data with our decoded data.
1464
- let ctxt_data_ref = & mut hygiene_data. syntax_context_data [ pending_ctxt. as_u32 ( ) as usize ] ;
1465
- let prev_ctxt_data = mem:: replace ( ctxt_data_ref, ctxt_data) ;
1466
- // Reset `dollar_crate_name` so that it will be updated by `update_dollar_crate_names`.
1467
- // We don't care what the encoding crate set this to - we want to resolve it
1468
- // from the perspective of the current compilation session
1469
- ctxt_data_ref. dollar_crate_name = kw:: DollarCrate ;
1470
- if let Some ( old) = old {
1471
- * ctxt_data_ref = old;
1472
- }
1473
- // Make sure nothing weird happened while `decode_data` was running.
1474
- if !prev_ctxt_data. is_decode_placeholder ( ) {
1475
- // Another thread may have already inserted the decoded data,
1476
- // but the decoded data should match.
1477
- assert_eq ! ( prev_ctxt_data, * ctxt_data_ref) ;
1459
+ match hygiene_data. syntax_context_map . get ( & ctxt_key) {
1460
+ // Ensure that syntax contexts are unique.
1461
+ // If syntax contexts with the given key already exists, reuse it instead of
1462
+ // using `pending_ctxt`.
1463
+ // `pending_ctxt` will leave an unused hole in the vector of syntax contexts.
1464
+ // Hopefully its value isn't stored anywhere during decoding and its dummy data
1465
+ // is never accessed later. The `is_decode_placeholder` asserts on all
1466
+ // accesses to syntax context data attempt to ensure it.
1467
+ Some ( & ctxt) => ctxt,
1468
+ // This is a completely new context.
1469
+ // Overwrite its placeholder data with our decoded data.
1470
+ None => {
1471
+ let ctxt_data_ref =
1472
+ & mut hygiene_data. syntax_context_data [ pending_ctxt. as_u32 ( ) as usize ] ;
1473
+ let prev_ctxt_data = mem:: replace ( ctxt_data_ref, ctxt_data) ;
1474
+ // Reset `dollar_crate_name` so that it will be updated by `update_dollar_crate_names`.
1475
+ // We don't care what the encoding crate set this to - we want to resolve it
1476
+ // from the perspective of the current compilation session.
1477
+ ctxt_data_ref. dollar_crate_name = kw:: DollarCrate ;
1478
+ // Make sure nothing weird happened while `decode_data` was running.
1479
+ if !prev_ctxt_data. is_decode_placeholder ( ) {
1480
+ // Another thread may have already inserted the decoded data,
1481
+ // but the decoded data should match.
1482
+ assert_eq ! ( prev_ctxt_data, * ctxt_data_ref) ;
1483
+ }
1484
+ hygiene_data. syntax_context_map . insert ( ctxt_key, pending_ctxt) ;
1485
+ pending_ctxt
1486
+ }
1478
1487
}
1479
- pending_ctxt
1480
1488
} ) ;
1481
1489
1482
1490
// Mark the context as completed
0 commit comments