@@ -72,21 +72,6 @@ struct SyntaxContextData {
72
72
}
73
73
74
74
impl 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
-
90
75
fn root ( ) -> SyntaxContextData {
91
76
SyntaxContextData {
92
77
outer_expn : ExpnId :: root ( ) ,
@@ -98,14 +83,6 @@ impl SyntaxContextData {
98
83
}
99
84
}
100
85
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
-
109
86
fn key ( & self ) -> SyntaxContextKey {
110
87
( self . parent , self . outer_expn , self . outer_transparency )
111
88
}
@@ -148,7 +125,7 @@ impl !PartialOrd for LocalExpnId {}
148
125
/// with a non-default mode. With this check in place, we can avoid the need
149
126
/// to maintain separate versions of `ExpnData` hashes for each permutation
150
127
/// 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 ) {
152
129
match ctx. hashing_controls ( ) {
153
130
// Note that we require that `hash_spans` be set according to the global
154
131
// `-Z incremental-ignore-spans` option. Normally, this option is disabled,
@@ -416,7 +393,7 @@ impl HygieneData {
416
393
}
417
394
}
418
395
419
- fn with < T , F : FnOnce ( & mut HygieneData ) -> T > ( f : F ) -> T {
396
+ fn with < R > ( f : impl FnOnce ( & mut HygieneData ) -> R ) -> R {
420
397
with_session_globals ( |session_globals| f ( & mut session_globals. hygiene_data . borrow_mut ( ) ) )
421
398
}
422
399
@@ -460,28 +437,23 @@ impl HygieneData {
460
437
}
461
438
462
439
fn normalize_to_macros_2_0 ( & self , ctxt : SyntaxContext ) -> SyntaxContext {
463
- debug_assert ! ( !self . syntax_context_data[ ctxt. 0 as usize ] . is_decode_placeholder( ) ) ;
464
440
self . syntax_context_data [ ctxt. 0 as usize ] . opaque
465
441
}
466
442
467
443
fn normalize_to_macro_rules ( & self , ctxt : SyntaxContext ) -> SyntaxContext {
468
- debug_assert ! ( !self . syntax_context_data[ ctxt. 0 as usize ] . is_decode_placeholder( ) ) ;
469
444
self . syntax_context_data [ ctxt. 0 as usize ] . opaque_and_semiopaque
470
445
}
471
446
472
447
fn outer_expn ( & self , ctxt : SyntaxContext ) -> ExpnId {
473
- debug_assert ! ( !self . syntax_context_data[ ctxt. 0 as usize ] . is_decode_placeholder( ) ) ;
474
448
self . syntax_context_data [ ctxt. 0 as usize ] . outer_expn
475
449
}
476
450
477
451
fn outer_mark ( & self , ctxt : SyntaxContext ) -> ( ExpnId , Transparency ) {
478
- debug_assert ! ( !self . syntax_context_data[ ctxt. 0 as usize ] . is_decode_placeholder( ) ) ;
479
452
let data = & self . syntax_context_data [ ctxt. 0 as usize ] ;
480
453
( data. outer_expn , data. outer_transparency )
481
454
}
482
455
483
456
fn parent_ctxt ( & self , ctxt : SyntaxContext ) -> SyntaxContext {
484
- debug_assert ! ( !self . syntax_context_data[ ctxt. 0 as usize ] . is_decode_placeholder( ) ) ;
485
457
self . syntax_context_data [ ctxt. 0 as usize ] . parent
486
458
}
487
459
@@ -592,25 +564,27 @@ impl HygieneData {
592
564
expn_id : ExpnId ,
593
565
transparency : Transparency ,
594
566
) -> SyntaxContext {
595
- debug_assert ! ( !self . syntax_context_data[ parent. 0 as usize ] . is_decode_placeholder( ) ) ;
596
-
597
567
// Look into the cache first.
598
568
let key = ( parent, expn_id, transparency) ;
599
569
if let Some ( ctxt) = self . syntax_context_map . get ( & key) {
600
570
return * ctxt;
601
571
}
602
572
603
573
// 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.
604
576
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 ( ) } ) ;
606
579
self . syntax_context_map . insert ( key, ctxt) ;
607
580
608
581
// Opaque and semi-opaque versions of the parent. Note that they may be equal to the
609
582
// parent itself. E.g. `parent_opaque` == `parent` if the expn chain contains only opaques,
610
583
// 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 ;
614
588
615
589
// Evaluate opaque and semi-opaque versions of the new syntax context.
616
590
let ( opaque, opaque_and_semiopaque) = match transparency {
@@ -629,8 +603,14 @@ impl HygieneData {
629
603
} ;
630
604
631
605
// 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
+ } ;
634
614
ctxt
635
615
}
636
616
}
@@ -650,13 +630,12 @@ pub fn walk_chain_collapsed(span: Span, to: Span) -> Span {
650
630
651
631
pub fn update_dollar_crate_names ( mut get_name : impl FnMut ( SyntaxContext ) -> Symbol ) {
652
632
// 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.
654
633
let mut to_update = vec ! [ ] ;
655
634
HygieneData :: with ( |data| {
656
635
for ( idx, scdata) in data. syntax_context_data . iter ( ) . enumerate ( ) . rev ( ) {
657
636
if scdata. dollar_crate_name == kw:: DollarCrate {
658
637
to_update. push ( ( idx, kw:: DollarCrate ) ) ;
659
- } else if !scdata . is_decode_placeholder ( ) {
638
+ } else {
660
639
break ;
661
640
}
662
641
}
@@ -922,10 +901,7 @@ impl SyntaxContext {
922
901
}
923
902
924
903
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 )
929
905
}
930
906
931
907
pub fn edition ( self ) -> Edition {
@@ -1293,49 +1269,47 @@ impl HygieneEncodeContext {
1293
1269
self . latest_ctxts
1294
1270
) ;
1295
1271
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.
1303
1276
#[ 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 {
1305
1284
if self . serialized_ctxts . lock ( ) . insert ( ctxt) {
1306
- encode_ctxt ( encoder, index , data ) ;
1285
+ encode_ctxt ( encoder, ctxt . 0 , & ctxt_key ) ;
1307
1286
}
1308
- } ) ;
1309
-
1310
- let latest_expns = { mem:: take ( & mut * self . latest_expns . lock ( ) ) } ;
1287
+ }
1311
1288
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.
1313
1290
#[ 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 {
1315
1298
if self . serialized_expns . lock ( ) . insert ( expn) {
1316
- encode_expn ( encoder, expn, data , hash ) ;
1299
+ encode_expn ( encoder, expn, & expn_data , expn_hash ) ;
1317
1300
}
1318
- } ) ;
1301
+ }
1319
1302
}
1320
1303
debug ! ( "encode_hygiene: Done serializing SyntaxContextData" ) ;
1321
1304
}
1322
1305
}
1323
1306
1324
- #[ derive( Default ) ]
1325
1307
/// 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
-
1335
1308
#[ derive( Default ) ]
1336
- /// Additional information used to assist in decoding hygiene data
1337
1309
pub 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 > > > ,
1339
1313
}
1340
1314
1341
1315
/// 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(
1406
1380
// to track which `SyntaxContext`s we have already decoded.
1407
1381
// The provided closure will be invoked to deserialize a `SyntaxContextData`
1408
1382
// 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 > (
1410
1384
d : & mut D ,
1411
1385
context : & HygieneDecodeContext ,
1412
- decode_data : F ,
1386
+ decode_data : impl FnOnce ( & mut D , u32 ) -> SyntaxContextKey ,
1413
1387
) -> SyntaxContext {
1414
1388
let raw_id: u32 = Decodable :: decode ( d) ;
1415
1389
if raw_id == 0 {
@@ -1418,12 +1392,11 @@ pub fn decode_syntax_context<D: Decoder, F: FnOnce(&mut D, u32) -> SyntaxContext
1418
1392
return SyntaxContext :: root ( ) ;
1419
1393
}
1420
1394
1395
+ // Look into the cache first.
1421
1396
// Reminder: `HygieneDecodeContext` is per-crate, so there are no collisions between
1422
1397
// 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;
1427
1400
}
1428
1401
1429
1402
// 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
1432
1405
let ctxt =
1433
1406
HygieneData :: with ( |hygiene_data| hygiene_data. alloc_ctxt ( parent, expn_id, transparency) ) ;
1434
1407
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) ;
1441
1409
1442
1410
ctxt
1443
1411
}
1444
1412
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
-
1477
1413
impl < E : SpanEncoder > Encodable < E > for LocalExpnId {
1478
1414
fn encode ( & self , e : & mut E ) {
1479
1415
self . to_expn_id ( ) . encode ( e) ;
@@ -1486,10 +1422,10 @@ impl<D: SpanDecoder> Decodable<D> for LocalExpnId {
1486
1422
}
1487
1423
}
1488
1424
1489
- pub fn raw_encode_syntax_context < E : Encoder > (
1425
+ pub fn raw_encode_syntax_context (
1490
1426
ctxt : SyntaxContext ,
1491
1427
context : & HygieneEncodeContext ,
1492
- e : & mut E ,
1428
+ e : & mut impl Encoder ,
1493
1429
) {
1494
1430
if !context. serialized_ctxts . lock ( ) . contains ( & ctxt) {
1495
1431
context. latest_ctxts . lock ( ) . insert ( ctxt) ;
0 commit comments