@@ -90,6 +90,10 @@ impl SyntaxContextData {
9090 fn is_decode_placeholder ( & self ) -> bool {
9191 self . dollar_crate_name == kw:: Empty
9292 }
93+
94+ fn key ( & self ) -> SyntaxContextKey {
95+ ( self . parent , self . outer_expn , self . outer_transparency )
96+ }
9397}
9498
9599rustc_index:: newtype_index! {
@@ -386,7 +390,7 @@ impl HygieneData {
386390 expn_hash_to_expn_id : iter:: once ( ( ExpnHash ( Fingerprint :: ZERO ) , ExpnId :: root ( ) ) )
387391 . collect ( ) ,
388392 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 ( ) ,
390394 expn_data_disambiguators : UnhashMap :: default ( ) ,
391395 }
392396 }
@@ -1436,35 +1440,39 @@ pub fn decode_syntax_context<D: Decoder, F: FnOnce(&mut D, u32) -> SyntaxContext
14361440 // Don't try to decode data while holding the lock, since we need to
14371441 // be able to recursively decode a SyntaxContext
14381442 let ctxt_data = decode_data ( d, raw_id) ;
1443+ let ctxt_key = ctxt_data. key ( ) ;
14391444
14401445 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+ }
14661475 }
1467- pending_ctxt
14681476 } ) ;
14691477
14701478 // Mark the context as completed
0 commit comments