@@ -72,21 +72,6 @@ struct SyntaxContextData {
7272}
7373
7474impl SyntaxContextData {
75- fn new (
76- ( parent, outer_expn, outer_transparency) : SyntaxContextKey ,
77- opaque : SyntaxContext ,
78- opaque_and_semiopaque : SyntaxContext ,
79- ) -> SyntaxContextData {
80- SyntaxContextData {
81- outer_expn,
82- outer_transparency,
83- parent,
84- opaque,
85- opaque_and_semiopaque,
86- dollar_crate_name : kw:: DollarCrate ,
87- }
88- }
89-
9075 fn root ( ) -> SyntaxContextData {
9176 SyntaxContextData {
9277 outer_expn : ExpnId :: root ( ) ,
@@ -98,14 +83,6 @@ impl SyntaxContextData {
9883 }
9984 }
10085
101- fn decode_placeholder ( ) -> SyntaxContextData {
102- SyntaxContextData { dollar_crate_name : kw:: Empty , ..SyntaxContextData :: root ( ) }
103- }
104-
105- fn is_decode_placeholder ( & self ) -> bool {
106- self . dollar_crate_name == kw:: Empty
107- }
108-
10986 fn key ( & self ) -> SyntaxContextKey {
11087 ( self . parent , self . outer_expn , self . outer_transparency )
11188 }
@@ -148,7 +125,7 @@ impl !PartialOrd for LocalExpnId {}
148125/// with a non-default mode. With this check in place, we can avoid the need
149126/// to maintain separate versions of `ExpnData` hashes for each permutation
150127/// of `HashingControls` settings.
151- fn assert_default_hashing_controls < CTX : HashStableContext > ( ctx : & CTX , msg : & str ) {
128+ fn assert_default_hashing_controls ( ctx : & impl HashStableContext , msg : & str ) {
152129 match ctx. hashing_controls ( ) {
153130 // Note that we require that `hash_spans` be set according to the global
154131 // `-Z incremental-ignore-spans` option. Normally, this option is disabled,
@@ -416,7 +393,7 @@ impl HygieneData {
416393 }
417394 }
418395
419- fn with < T , F : FnOnce ( & mut HygieneData ) -> T > ( f : F ) -> T {
396+ fn with < R > ( f : impl FnOnce ( & mut HygieneData ) -> R ) -> R {
420397 with_session_globals ( |session_globals| f ( & mut session_globals. hygiene_data . borrow_mut ( ) ) )
421398 }
422399
@@ -460,28 +437,23 @@ impl HygieneData {
460437 }
461438
462439 fn normalize_to_macros_2_0 ( & self , ctxt : SyntaxContext ) -> SyntaxContext {
463- debug_assert ! ( !self . syntax_context_data[ ctxt. 0 as usize ] . is_decode_placeholder( ) ) ;
464440 self . syntax_context_data [ ctxt. 0 as usize ] . opaque
465441 }
466442
467443 fn normalize_to_macro_rules ( & self , ctxt : SyntaxContext ) -> SyntaxContext {
468- debug_assert ! ( !self . syntax_context_data[ ctxt. 0 as usize ] . is_decode_placeholder( ) ) ;
469444 self . syntax_context_data [ ctxt. 0 as usize ] . opaque_and_semiopaque
470445 }
471446
472447 fn outer_expn ( & self , ctxt : SyntaxContext ) -> ExpnId {
473- debug_assert ! ( !self . syntax_context_data[ ctxt. 0 as usize ] . is_decode_placeholder( ) ) ;
474448 self . syntax_context_data [ ctxt. 0 as usize ] . outer_expn
475449 }
476450
477451 fn outer_mark ( & self , ctxt : SyntaxContext ) -> ( ExpnId , Transparency ) {
478- debug_assert ! ( !self . syntax_context_data[ ctxt. 0 as usize ] . is_decode_placeholder( ) ) ;
479452 let data = & self . syntax_context_data [ ctxt. 0 as usize ] ;
480453 ( data. outer_expn , data. outer_transparency )
481454 }
482455
483456 fn parent_ctxt ( & self , ctxt : SyntaxContext ) -> SyntaxContext {
484- debug_assert ! ( !self . syntax_context_data[ ctxt. 0 as usize ] . is_decode_placeholder( ) ) ;
485457 self . syntax_context_data [ ctxt. 0 as usize ] . parent
486458 }
487459
@@ -592,25 +564,27 @@ impl HygieneData {
592564 expn_id : ExpnId ,
593565 transparency : Transparency ,
594566 ) -> SyntaxContext {
595- debug_assert ! ( !self . syntax_context_data[ parent. 0 as usize ] . is_decode_placeholder( ) ) ;
596-
597567 // Look into the cache first.
598568 let key = ( parent, expn_id, transparency) ;
599569 if let Some ( ctxt) = self . syntax_context_map . get ( & key) {
600570 return * ctxt;
601571 }
602572
603573 // Reserve a new syntax context.
574+ // The inserted dummy data can only be potentially accessed by nested `alloc_ctxt` calls,
575+ // the assert below ensures that it doesn't happen.
604576 let ctxt = SyntaxContext :: from_usize ( self . syntax_context_data . len ( ) ) ;
605- self . syntax_context_data . push ( SyntaxContextData :: decode_placeholder ( ) ) ;
577+ self . syntax_context_data
578+ . push ( SyntaxContextData { dollar_crate_name : sym:: dummy, ..SyntaxContextData :: root ( ) } ) ;
606579 self . syntax_context_map . insert ( key, ctxt) ;
607580
608581 // Opaque and semi-opaque versions of the parent. Note that they may be equal to the
609582 // parent itself. E.g. `parent_opaque` == `parent` if the expn chain contains only opaques,
610583 // and `parent_opaque_and_semiopaque` == `parent` if the expn contains only (semi-)opaques.
611- let parent_opaque = self . syntax_context_data [ parent. 0 as usize ] . opaque ;
612- let parent_opaque_and_semiopaque =
613- self . syntax_context_data [ parent. 0 as usize ] . opaque_and_semiopaque ;
584+ let parent_data = & self . syntax_context_data [ parent. 0 as usize ] ;
585+ assert_ne ! ( parent_data. dollar_crate_name, sym:: dummy) ;
586+ let parent_opaque = parent_data. opaque ;
587+ let parent_opaque_and_semiopaque = parent_data. opaque_and_semiopaque ;
614588
615589 // Evaluate opaque and semi-opaque versions of the new syntax context.
616590 let ( opaque, opaque_and_semiopaque) = match transparency {
@@ -629,8 +603,14 @@ impl HygieneData {
629603 } ;
630604
631605 // Fill the full data, now that we have it.
632- self . syntax_context_data [ ctxt. as_u32 ( ) as usize ] =
633- SyntaxContextData :: new ( key, opaque, opaque_and_semiopaque) ;
606+ self . syntax_context_data [ ctxt. as_u32 ( ) as usize ] = SyntaxContextData {
607+ outer_expn : expn_id,
608+ outer_transparency : transparency,
609+ parent,
610+ opaque,
611+ opaque_and_semiopaque,
612+ dollar_crate_name : kw:: DollarCrate ,
613+ } ;
634614 ctxt
635615 }
636616}
@@ -650,13 +630,12 @@ pub fn walk_chain_collapsed(span: Span, to: Span) -> Span {
650630
651631pub fn update_dollar_crate_names ( mut get_name : impl FnMut ( SyntaxContext ) -> Symbol ) {
652632 // The new contexts that need updating are at the end of the list and have `$crate` as a name.
653- // Also decoding placeholders can be encountered among both old and new contexts.
654633 let mut to_update = vec ! [ ] ;
655634 HygieneData :: with ( |data| {
656635 for ( idx, scdata) in data. syntax_context_data . iter ( ) . enumerate ( ) . rev ( ) {
657636 if scdata. dollar_crate_name == kw:: DollarCrate {
658637 to_update. push ( ( idx, kw:: DollarCrate ) ) ;
659- } else if !scdata . is_decode_placeholder ( ) {
638+ } else {
660639 break ;
661640 }
662641 }
@@ -922,10 +901,7 @@ impl SyntaxContext {
922901 }
923902
924903 pub ( crate ) fn dollar_crate_name ( self ) -> Symbol {
925- HygieneData :: with ( |data| {
926- debug_assert ! ( !data. syntax_context_data[ self . 0 as usize ] . is_decode_placeholder( ) ) ;
927- data. syntax_context_data [ self . 0 as usize ] . dollar_crate_name
928- } )
904+ HygieneData :: with ( |data| data. syntax_context_data [ self . 0 as usize ] . dollar_crate_name )
929905 }
930906
931907 pub fn edition ( self ) -> Edition {
@@ -1293,49 +1269,47 @@ impl HygieneEncodeContext {
12931269 self . latest_ctxts
12941270 ) ;
12951271
1296- // Consume the current round of SyntaxContexts.
1297- // Drop the lock() temporary early
1298- let latest_ctxts = { mem:: take ( & mut * self . latest_ctxts . lock ( ) ) } ;
1299-
1300- // It's fine to iterate over a HashMap, because the serialization
1301- // of the table that we insert data into doesn't depend on insertion
1302- // order
1272+ // Consume the current round of syntax contexts.
1273+ // Drop the lock() temporary early.
1274+ // It's fine to iterate over a HashMap, because the serialization of the table
1275+ // that we insert data into doesn't depend on insertion order.
13031276 #[ allow( rustc:: potential_query_instability) ]
1304- for_all_ctxts_in ( latest_ctxts. into_iter ( ) , |index, ctxt, data| {
1277+ let latest_ctxts = { mem:: take ( & mut * self . latest_ctxts . lock ( ) ) } . into_iter ( ) ;
1278+ let all_ctxt_data: Vec < _ > = HygieneData :: with ( |data| {
1279+ latest_ctxts
1280+ . map ( |ctxt| ( ctxt, data. syntax_context_data [ ctxt. 0 as usize ] . key ( ) ) )
1281+ . collect ( )
1282+ } ) ;
1283+ for ( ctxt, ctxt_key) in all_ctxt_data {
13051284 if self . serialized_ctxts . lock ( ) . insert ( ctxt) {
1306- encode_ctxt ( encoder, index , data ) ;
1285+ encode_ctxt ( encoder, ctxt . 0 , & ctxt_key ) ;
13071286 }
1308- } ) ;
1309-
1310- let latest_expns = { mem:: take ( & mut * self . latest_expns . lock ( ) ) } ;
1287+ }
13111288
1312- // Same as above, this is fine as we are inserting into a order-independent hashset
1289+ // Same as above, but for expansions instead of syntax contexts.
13131290 #[ allow( rustc:: potential_query_instability) ]
1314- for_all_expns_in ( latest_expns. into_iter ( ) , |expn, data, hash| {
1291+ let latest_expns = { mem:: take ( & mut * self . latest_expns . lock ( ) ) } . into_iter ( ) ;
1292+ let all_expn_data: Vec < _ > = HygieneData :: with ( |data| {
1293+ latest_expns
1294+ . map ( |expn| ( expn, data. expn_data ( expn) . clone ( ) , data. expn_hash ( expn) ) )
1295+ . collect ( )
1296+ } ) ;
1297+ for ( expn, expn_data, expn_hash) in all_expn_data {
13151298 if self . serialized_expns . lock ( ) . insert ( expn) {
1316- encode_expn ( encoder, expn, data , hash ) ;
1299+ encode_expn ( encoder, expn, & expn_data , expn_hash ) ;
13171300 }
1318- } ) ;
1301+ }
13191302 }
13201303 debug ! ( "encode_hygiene: Done serializing SyntaxContextData" ) ;
13211304 }
13221305}
13231306
1324- #[ derive( Default ) ]
13251307/// Additional information used to assist in decoding hygiene data
1326- struct HygieneDecodeContextInner {
1327- // Maps serialized `SyntaxContext` ids to a `SyntaxContext` in the current
1328- // global `HygieneData`. When we deserialize a `SyntaxContext`, we need to create
1329- // a new id in the global `HygieneData`. This map tracks the ID we end up picking,
1330- // so that multiple occurrences of the same serialized id are decoded to the same
1331- // `SyntaxContext`. This only stores `SyntaxContext`s which are completely decoded.
1332- remapped_ctxts : Vec < Option < SyntaxContext > > ,
1333- }
1334-
13351308#[ derive( Default ) ]
1336- /// Additional information used to assist in decoding hygiene data
13371309pub struct HygieneDecodeContext {
1338- inner : Lock < HygieneDecodeContextInner > ,
1310+ // A cache mapping raw serialized per-crate syntax context ids to corresponding decoded
1311+ // `SyntaxContext`s in the current global `HygieneData`.
1312+ remapped_ctxts : Lock < IndexVec < u32 , Option < SyntaxContext > > > ,
13391313}
13401314
13411315/// Register an expansion which has been decoded from the on-disk-cache for the local crate.
@@ -1406,10 +1380,10 @@ pub fn decode_expn_id(
14061380// to track which `SyntaxContext`s we have already decoded.
14071381// The provided closure will be invoked to deserialize a `SyntaxContextData`
14081382// if we haven't already seen the id of the `SyntaxContext` we are deserializing.
1409- pub fn decode_syntax_context < D : Decoder , F : FnOnce ( & mut D , u32 ) -> SyntaxContextKey > (
1383+ pub fn decode_syntax_context < D : Decoder > (
14101384 d : & mut D ,
14111385 context : & HygieneDecodeContext ,
1412- decode_data : F ,
1386+ decode_data : impl FnOnce ( & mut D , u32 ) -> SyntaxContextKey ,
14131387) -> SyntaxContext {
14141388 let raw_id: u32 = Decodable :: decode ( d) ;
14151389 if raw_id == 0 {
@@ -1418,12 +1392,11 @@ pub fn decode_syntax_context<D: Decoder, F: FnOnce(&mut D, u32) -> SyntaxContext
14181392 return SyntaxContext :: root ( ) ;
14191393 }
14201394
1395+ // Look into the cache first.
14211396 // Reminder: `HygieneDecodeContext` is per-crate, so there are no collisions between
14221397 // raw ids from different crate metadatas.
1423- if let Some ( ctxt) = context. inner . lock ( ) . remapped_ctxts . get ( raw_id as usize ) . copied ( ) . flatten ( )
1424- {
1425- // This has already been decoded.
1426- return ctxt;
1398+ if let Some ( Some ( ctxt) ) = context. remapped_ctxts . lock ( ) . get ( raw_id) {
1399+ return * ctxt;
14271400 }
14281401
14291402 // Don't try to decode data while holding the lock, since we need to
@@ -1432,48 +1405,11 @@ pub fn decode_syntax_context<D: Decoder, F: FnOnce(&mut D, u32) -> SyntaxContext
14321405 let ctxt =
14331406 HygieneData :: with ( |hygiene_data| hygiene_data. alloc_ctxt ( parent, expn_id, transparency) ) ;
14341407
1435- let mut inner = context. inner . lock ( ) ;
1436- let new_len = raw_id as usize + 1 ;
1437- if inner. remapped_ctxts . len ( ) < new_len {
1438- inner. remapped_ctxts . resize ( new_len, None ) ;
1439- }
1440- inner. remapped_ctxts [ raw_id as usize ] = Some ( ctxt) ;
1408+ context. remapped_ctxts . lock ( ) . insert ( raw_id, ctxt) ;
14411409
14421410 ctxt
14431411}
14441412
1445- fn for_all_ctxts_in < F : FnMut ( u32 , SyntaxContext , & SyntaxContextKey ) > (
1446- ctxts : impl Iterator < Item = SyntaxContext > ,
1447- mut f : F ,
1448- ) {
1449- let all_data: Vec < _ > = HygieneData :: with ( |data| {
1450- ctxts
1451- . map ( |ctxt| {
1452- ( ctxt, {
1453- let item = data. syntax_context_data [ ctxt. 0 as usize ] ;
1454- debug_assert ! ( !item. is_decode_placeholder( ) ) ;
1455- item. key ( )
1456- } )
1457- } )
1458- . collect ( )
1459- } ) ;
1460- for ( ctxt, data) in all_data. into_iter ( ) {
1461- f ( ctxt. 0 , ctxt, & data) ;
1462- }
1463- }
1464-
1465- fn for_all_expns_in (
1466- expns : impl Iterator < Item = ExpnId > ,
1467- mut f : impl FnMut ( ExpnId , & ExpnData , ExpnHash ) ,
1468- ) {
1469- let all_data: Vec < _ > = HygieneData :: with ( |data| {
1470- expns. map ( |expn| ( expn, data. expn_data ( expn) . clone ( ) , data. expn_hash ( expn) ) ) . collect ( )
1471- } ) ;
1472- for ( expn, data, hash) in all_data. into_iter ( ) {
1473- f ( expn, & data, hash) ;
1474- }
1475- }
1476-
14771413impl < E : SpanEncoder > Encodable < E > for LocalExpnId {
14781414 fn encode ( & self , e : & mut E ) {
14791415 self . to_expn_id ( ) . encode ( e) ;
@@ -1486,10 +1422,10 @@ impl<D: SpanDecoder> Decodable<D> for LocalExpnId {
14861422 }
14871423}
14881424
1489- pub fn raw_encode_syntax_context < E : Encoder > (
1425+ pub fn raw_encode_syntax_context (
14901426 ctxt : SyntaxContext ,
14911427 context : & HygieneEncodeContext ,
1492- e : & mut E ,
1428+ e : & mut impl Encoder ,
14931429) {
14941430 if !context. serialized_ctxts . lock ( ) . contains ( & ctxt) {
14951431 context. latest_ctxts . lock ( ) . insert ( ctxt) ;
0 commit comments