@@ -30,7 +30,7 @@ use crate::with_session_globals;
30
30
use crate :: { HashStableContext , Span , DUMMY_SP } ;
31
31
32
32
use crate :: def_id:: { CrateNum , DefId , StableCrateId , CRATE_DEF_ID , LOCAL_CRATE } ;
33
- use rustc_data_structures:: fingerprint:: Fingerprint ;
33
+ use rustc_data_structures:: fingerprint:: { Fingerprint , PackedFingerprint } ;
34
34
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
35
35
use rustc_data_structures:: stable_hasher:: HashingControls ;
36
36
use rustc_data_structures:: stable_hasher:: { Hash64 , HashStable , StableHasher } ;
@@ -195,34 +195,44 @@ impl LocalExpnId {
195
195
#[ instrument( level = "trace" , skip( ctx) , ret) ]
196
196
pub fn create_untracked_expansion (
197
197
mut expn_data : ExpnData ,
198
+ dep_node : FakeDepNode ,
198
199
ctx : impl HashStableContext ,
199
200
) -> LocalExpnId {
200
201
debug_assert_eq ! ( expn_data. parent. krate, LOCAL_CRATE ) ;
201
- let expn_hash = update_disambiguator ( & mut expn_data, ctx) ;
202
+ let expn_hash = update_disambiguator ( & mut expn_data, dep_node , ctx) ;
202
203
HygieneData :: with ( |data| {
203
204
let expn_id = data. local_expn_data . push ( Some ( expn_data) ) ;
204
205
let _eid = data. local_expn_hashes . push ( expn_hash) ;
205
206
debug_assert_eq ! ( expn_id, _eid) ;
206
207
let _old_id = data. expn_hash_to_expn_id . insert ( expn_hash, expn_id. to_expn_id ( ) ) ;
207
- debug_assert ! ( _old_id. is_none( ) ) ;
208
+ if !_old_id. is_none ( ) {
209
+ panic ! ( "Hash collision while creating expansion. Cannot continue." ) ;
210
+ }
208
211
expn_id
209
212
} )
210
213
}
211
214
212
215
/// Implementation detail of `TyCtxt::finalize_expansion`.
213
216
#[ inline]
214
217
#[ instrument( level = "trace" , skip( ctx) ) ]
215
- pub fn set_untracked_expn_data ( self , mut expn_data : ExpnData , ctx : impl HashStableContext ) {
218
+ pub fn set_untracked_expn_data (
219
+ self ,
220
+ mut expn_data : ExpnData ,
221
+ dep_node : FakeDepNode ,
222
+ ctx : impl HashStableContext ,
223
+ ) {
216
224
debug_assert_eq ! ( expn_data. parent. krate, LOCAL_CRATE ) ;
217
- let expn_hash = update_disambiguator ( & mut expn_data, ctx) ;
225
+ let expn_hash = update_disambiguator ( & mut expn_data, dep_node , ctx) ;
218
226
HygieneData :: with ( |data| {
219
227
let old_expn_data = & mut data. local_expn_data [ self ] ;
220
228
assert ! ( old_expn_data. is_none( ) , "expansion data is reset for an expansion ID" ) ;
221
229
* old_expn_data = Some ( expn_data) ;
222
230
debug_assert_eq ! ( data. local_expn_hashes[ self ] . 0 , Fingerprint :: ZERO ) ;
223
231
data. local_expn_hashes [ self ] = expn_hash;
224
232
let _old_id = data. expn_hash_to_expn_id . insert ( expn_hash, self . to_expn_id ( ) ) ;
225
- debug_assert ! ( _old_id. is_none( ) ) ;
233
+ if !_old_id. is_none ( ) {
234
+ panic ! ( "Hash collision while creating expansion. Cannot continue." ) ;
235
+ }
226
236
} ) ;
227
237
}
228
238
@@ -339,6 +349,14 @@ impl ExpnId {
339
349
}
340
350
}
341
351
352
+ /// This struct is meant to be a surrogate for the actual `DepNode` in rustc_middle.
353
+ /// Both types should be kept in sync.
354
+ #[ derive( Copy , Clone , Debug , Hash , PartialEq , Eq ) ]
355
+ pub struct FakeDepNode {
356
+ pub kind : u16 ,
357
+ pub hash : PackedFingerprint ,
358
+ }
359
+
342
360
#[ derive( Debug ) ]
343
361
pub struct HygieneData {
344
362
/// Each expansion should have an associated expansion data, but sometimes there's a delay
@@ -358,7 +376,7 @@ pub struct HygieneData {
358
376
/// would have collisions without a disambiguator.
359
377
/// The keys of this map are always computed with `ExpnData.disambiguator`
360
378
/// set to 0.
361
- expn_data_disambiguators : FxHashMap < Hash64 , u32 > ,
379
+ expn_data_disambiguators : FxHashMap < FakeDepNode , FxHashMap < Hash64 , u32 > > ,
362
380
}
363
381
364
382
impl HygieneData {
@@ -1031,9 +1049,10 @@ impl ExpnData {
1031
1049
}
1032
1050
1033
1051
#[ inline]
1034
- fn hash_expn ( & self , ctx : & mut impl HashStableContext ) -> Hash64 {
1052
+ fn hash_expn ( & self , dep_node : FakeDepNode , ctx : & mut impl HashStableContext ) -> Hash64 {
1035
1053
let mut hasher = StableHasher :: new ( ) ;
1036
1054
self . hash_stable ( ctx, & mut hasher) ;
1055
+ dep_node. hash ( & mut hasher) ;
1037
1056
hasher. finish ( )
1038
1057
}
1039
1058
}
@@ -1248,7 +1267,9 @@ pub fn register_local_expn_id(data: ExpnData, hash: ExpnHash) -> ExpnId {
1248
1267
let expn_id = expn_id. to_expn_id ( ) ;
1249
1268
1250
1269
let _old_id = hygiene_data. expn_hash_to_expn_id . insert ( hash, expn_id) ;
1251
- debug_assert ! ( _old_id. is_none( ) ) ;
1270
+ if !_old_id. is_none ( ) {
1271
+ panic ! ( "Hash collision while creating expansion. Cannot continue." ) ;
1272
+ }
1252
1273
expn_id
1253
1274
} )
1254
1275
}
@@ -1268,7 +1289,9 @@ pub fn register_expn_id(
1268
1289
let _old_hash = hygiene_data. foreign_expn_hashes . insert ( expn_id, hash) ;
1269
1290
debug_assert ! ( _old_hash. is_none( ) ) ;
1270
1291
let _old_id = hygiene_data. expn_hash_to_expn_id . insert ( hash, expn_id) ;
1271
- debug_assert ! ( _old_id. is_none( ) ) ;
1292
+ if !_old_id. is_none ( ) {
1293
+ panic ! ( "Hash collision while creating expansion. Cannot continue." ) ;
1294
+ }
1272
1295
} ) ;
1273
1296
expn_id
1274
1297
}
@@ -1452,16 +1475,27 @@ impl<D: Decoder> Decodable<D> for SyntaxContext {
1452
1475
/// `set_expn_data`). It is *not* called for foreign `ExpnId`s deserialized
1453
1476
/// from another crate's metadata - since `ExpnHash` includes the stable crate id,
1454
1477
/// collisions are only possible between `ExpnId`s within the same crate.
1455
- fn update_disambiguator ( expn_data : & mut ExpnData , mut ctx : impl HashStableContext ) -> ExpnHash {
1478
+ #[ instrument( level = "trace" , skip( ctx) , ret) ]
1479
+ fn update_disambiguator (
1480
+ expn_data : & mut ExpnData ,
1481
+ dep_node : FakeDepNode ,
1482
+ mut ctx : impl HashStableContext ,
1483
+ ) -> ExpnHash {
1456
1484
// This disambiguator should not have been set yet.
1457
1485
assert_eq ! ( expn_data. disambiguator, 0 , "Already set disambiguator for ExpnData: {expn_data:?}" ) ;
1458
1486
assert_default_hashing_controls ( & ctx, "ExpnData (disambiguator)" ) ;
1459
- let mut expn_hash = expn_data. hash_expn ( & mut ctx) ;
1487
+ let mut expn_hash = expn_data. hash_expn ( dep_node, & mut ctx) ;
1488
+ debug ! ( ?expn_hash) ;
1460
1489
1461
1490
let disambiguator = HygieneData :: with ( |data| {
1462
1491
// If this is the first ExpnData with a given hash, then keep our
1463
1492
// disambiguator at 0 (the default u32 value)
1464
- let disambig = data. expn_data_disambiguators . entry ( expn_hash) . or_default ( ) ;
1493
+ let disambig = data
1494
+ . expn_data_disambiguators
1495
+ . entry ( dep_node)
1496
+ . or_default ( )
1497
+ . entry ( expn_hash)
1498
+ . or_default ( ) ;
1465
1499
let disambiguator = * disambig;
1466
1500
* disambig += 1 ;
1467
1501
disambiguator
@@ -1471,13 +1505,13 @@ fn update_disambiguator(expn_data: &mut ExpnData, mut ctx: impl HashStableContex
1471
1505
debug ! ( "Set disambiguator for expn_data={:?} expn_hash={:?}" , expn_data, expn_hash) ;
1472
1506
1473
1507
expn_data. disambiguator = disambiguator;
1474
- expn_hash = expn_data. hash_expn ( & mut ctx) ;
1508
+ expn_hash = expn_data. hash_expn ( dep_node , & mut ctx) ;
1475
1509
1476
1510
// Verify that the new disambiguator makes the hash unique
1477
1511
#[ cfg( debug_assertions) ]
1478
1512
HygieneData :: with ( |data| {
1479
1513
assert_eq ! (
1480
- data. expn_data_disambiguators. get( & expn_hash) ,
1514
+ data. expn_data_disambiguators[ & dep_node ] . get( & expn_hash) ,
1481
1515
None ,
1482
1516
"Hash collision after disambiguator update!" ,
1483
1517
) ;
0 commit comments