@@ -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
}
@@ -1454,34 +1458,38 @@ pub fn decode_syntax_context<D: Decoder, F: FnOnce(&mut D, u32) -> SyntaxContext
1454
1458
// Don't try to decode data while holding the lock, since we need to
1455
1459
// be able to recursively decode a SyntaxContext
1456
1460
let ctxt_data = decode_data ( d, raw_id) ;
1461
+ let ctxt_key = ctxt_data. key ( ) ;
1457
1462
1458
1463
let ctxt = HygieneData :: with ( |hygiene_data| {
1459
- let old = if let Some ( old) = hygiene_data. syntax_context_data . get ( raw_id as usize )
1460
- && old. outer_expn == ctxt_data. outer_expn
1461
- && old. outer_transparency == ctxt_data. outer_transparency
1462
- && old. parent == ctxt_data. parent
1463
- {
1464
- Some ( old. clone ( ) )
1465
- } else {
1466
- None
1467
- } ;
1468
- // Overwrite its placeholder data with our decoded data.
1469
- let ctxt_data_ref = & mut hygiene_data. syntax_context_data [ pending_ctxt. as_u32 ( ) as usize ] ;
1470
- let prev_ctxt_data = mem:: replace ( ctxt_data_ref, ctxt_data) ;
1471
- // Reset `dollar_crate_name` so that it will be updated by `update_dollar_crate_names`.
1472
- // We don't care what the encoding crate set this to - we want to resolve it
1473
- // from the perspective of the current compilation session
1474
- ctxt_data_ref. dollar_crate_name = kw:: DollarCrate ;
1475
- if let Some ( old) = old {
1476
- * ctxt_data_ref = old;
1477
- }
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) ;
1464
+ match hygiene_data. syntax_context_map . get ( & ctxt_key) {
1465
+ // Ensure that syntax contexts are unique.
1466
+ // If syntax contexts with the given key already exists, reuse it instead of
1467
+ // using `pending_ctxt`.
1468
+ // `pending_ctxt` will leave an unused hole in the vector of syntax contexts.
1469
+ // Hopefully its value isn't stored anywhere during decoding and its dummy data
1470
+ // is never accessed later. The `is_decode_placeholder` asserts on all
1471
+ // accesses to syntax context data attempt to ensure it.
1472
+ Some ( & ctxt) => ctxt,
1473
+ // This is a completely new context.
1474
+ // Overwrite its placeholder data with our decoded data.
1475
+ None => {
1476
+ let ctxt_data_ref =
1477
+ & mut hygiene_data. syntax_context_data [ pending_ctxt. as_u32 ( ) as usize ] ;
1478
+ let prev_ctxt_data = mem:: replace ( ctxt_data_ref, ctxt_data) ;
1479
+ // Reset `dollar_crate_name` so that it will be updated by `update_dollar_crate_names`.
1480
+ // We don't care what the encoding crate set this to - we want to resolve it
1481
+ // from the perspective of the current compilation session.
1482
+ ctxt_data_ref. dollar_crate_name = kw:: DollarCrate ;
1483
+ // Make sure nothing weird happened while `decode_data` was running.
1484
+ if !prev_ctxt_data. is_decode_placeholder ( ) {
1485
+ // Another thread may have already inserted the decoded data,
1486
+ // but the decoded data should match.
1487
+ assert_eq ! ( prev_ctxt_data, * ctxt_data_ref) ;
1488
+ }
1489
+ hygiene_data. syntax_context_map . insert ( ctxt_key, pending_ctxt) ;
1490
+ pending_ctxt
1491
+ }
1483
1492
}
1484
- pending_ctxt
1485
1493
} ) ;
1486
1494
1487
1495
// Mark the context as completed
0 commit comments