@@ -255,7 +255,44 @@ pub(crate) struct UsageMap<'tcx> {
255
255
user_map : UnordMap < MonoItem < ' tcx > , Vec < MonoItem < ' tcx > > > ,
256
256
}
257
257
258
- type MonoItems < ' tcx > = Vec < Spanned < MonoItem < ' tcx > > > ;
258
+ struct MonoItems < ' tcx > {
259
+ tcx : TyCtxt < ' tcx > ,
260
+ // We want a set of MonoItem + Span where trying to re-insert a MonoItem with a different Span
261
+ // is ignored. Map does that, but it looks wrong.
262
+ items : UnordMap < MonoItem < ' tcx > , Span > ,
263
+ }
264
+
265
+ impl < ' tcx > MonoItems < ' tcx > {
266
+ fn new ( tcx : TyCtxt < ' tcx > ) -> Self {
267
+ Self { tcx, items : UnordMap :: default ( ) }
268
+ }
269
+
270
+ fn is_empty ( & self ) -> bool {
271
+ self . items . is_empty ( )
272
+ }
273
+
274
+ fn push ( & mut self , item : Spanned < MonoItem < ' tcx > > ) {
275
+ // Insert only if the entry does not exist. A normal insert would stomp the first span that
276
+ // got inserted.
277
+ self . items . entry ( item. node ) . or_insert ( item. span ) ;
278
+ }
279
+
280
+ fn extend ( & mut self , iter : impl IntoIterator < Item = Spanned < MonoItem < ' tcx > > > ) {
281
+ for item in iter {
282
+ self . push ( item. clone ( ) ) ;
283
+ }
284
+ }
285
+
286
+ fn into_iter ( self ) -> impl Iterator < Item = Spanned < MonoItem < ' tcx > > > {
287
+ self . tcx . with_stable_hashing_context ( |hcx| {
288
+ self . items . into_sorted ( & hcx, true ) . into_iter ( ) . map ( |( item, span) | respan ( span, item) )
289
+ } )
290
+ }
291
+
292
+ fn items ( & self ) -> Vec < MonoItem < ' tcx > > {
293
+ self . tcx . with_stable_hashing_context ( |hcx| self . items . keys ( ) . cloned ( ) . into_sorted ( & hcx) )
294
+ }
295
+ }
259
296
260
297
/// The state that is shared across the concurrent threads that are doing collection.
261
298
struct SharedState < ' tcx > {
@@ -273,14 +310,11 @@ impl<'tcx> UsageMap<'tcx> {
273
310
UsageMap { used_map : Default :: default ( ) , user_map : Default :: default ( ) }
274
311
}
275
312
276
- fn record_used < ' a > (
277
- & mut self ,
278
- user_item : MonoItem < ' tcx > ,
279
- used_items : & ' a [ Spanned < MonoItem < ' tcx > > ] ,
280
- ) where
313
+ fn record_used < ' a > ( & mut self , user_item : MonoItem < ' tcx > , used_items : & ' a MonoItems < ' tcx > )
314
+ where
281
315
' tcx : ' a ,
282
316
{
283
- let used_items: Vec < _ > = used_items. iter ( ) . map ( |item| item . node ) . collect ( ) ;
317
+ let used_items = used_items. items ( ) ;
284
318
for & used_item in used_items. iter ( ) {
285
319
self . user_map . entry ( used_item) . or_default ( ) . push ( user_item) ;
286
320
}
@@ -343,8 +377,8 @@ fn collect_items_rec<'tcx>(
343
377
// harm in that, the mention visit will trigger all the queries and the results are cached.
344
378
}
345
379
346
- let mut used_items = MonoItems :: new ( ) ;
347
- let mut mentioned_items = MonoItems :: new ( ) ;
380
+ let mut used_items = MonoItems :: new ( tcx ) ;
381
+ let mut mentioned_items = MonoItems :: new ( tcx ) ;
348
382
let recursion_depth_reset;
349
383
350
384
// Post-monomorphization errors MVP
@@ -430,8 +464,8 @@ fn collect_items_rec<'tcx>(
430
464
431
465
rustc_data_structures:: stack:: ensure_sufficient_stack ( || {
432
466
let ( used, mentioned) = tcx. items_of_instance ( ( instance, mode) ) ;
433
- used_items. extend ( used) ;
434
- mentioned_items. extend ( mentioned) ;
467
+ used_items. extend ( used. into_iter ( ) . copied ( ) ) ;
468
+ mentioned_items. extend ( mentioned. into_iter ( ) . copied ( ) ) ;
435
469
} ) ;
436
470
}
437
471
MonoItem :: GlobalAsm ( item_id) => {
@@ -503,7 +537,7 @@ fn collect_items_rec<'tcx>(
503
537
if mode == CollectionMode :: MentionedItems {
504
538
assert ! ( used_items. is_empty( ) , "'mentioned' collection should never encounter used items" ) ;
505
539
} else {
506
- for used_item in used_items {
540
+ for used_item in used_items. into_iter ( ) {
507
541
collect_items_rec (
508
542
tcx,
509
543
used_item,
@@ -517,7 +551,7 @@ fn collect_items_rec<'tcx>(
517
551
518
552
// Walk over mentioned items *after* used items, so that if an item is both mentioned and used then
519
553
// the loop above has fully collected it, so this loop will skip it.
520
- for mentioned_item in mentioned_items {
554
+ for mentioned_item in mentioned_items. into_iter ( ) {
521
555
collect_items_rec (
522
556
tcx,
523
557
mentioned_item,
@@ -1194,8 +1228,8 @@ fn collect_items_of_instance<'tcx>(
1194
1228
// mentioned item. So instead we collect all pre-monomorphized `MentionedItem` that were already
1195
1229
// added to `used_items` in a hash set, which can efficiently query in the
1196
1230
// `body.mentioned_items` loop below without even having to monomorphize the item.
1197
- let mut used_items = Default :: default ( ) ;
1198
- let mut mentioned_items = Default :: default ( ) ;
1231
+ let mut used_items = MonoItems :: new ( tcx ) ;
1232
+ let mut mentioned_items = MonoItems :: new ( tcx ) ;
1199
1233
let mut used_mentioned_items = Default :: default ( ) ;
1200
1234
let mut collector = MirUsedCollector {
1201
1235
tcx,
@@ -1238,7 +1272,11 @@ fn items_of_instance<'tcx>(
1238
1272
( instance, mode) : ( Instance < ' tcx > , CollectionMode ) ,
1239
1273
) -> ( & ' tcx [ Spanned < MonoItem < ' tcx > > ] , & ' tcx [ Spanned < MonoItem < ' tcx > > ] ) {
1240
1274
let ( used_items, mentioned_items) = collect_items_of_instance ( tcx, instance, mode) ;
1241
- ( tcx. arena . alloc_slice ( & used_items) , tcx. arena . alloc_slice ( & mentioned_items) )
1275
+
1276
+ let used_items = tcx. arena . alloc_from_iter ( used_items. into_iter ( ) ) ;
1277
+ let mentioned_items = tcx. arena . alloc_from_iter ( mentioned_items. into_iter ( ) ) ;
1278
+
1279
+ ( used_items, mentioned_items)
1242
1280
}
1243
1281
1244
1282
/// `item` must be already monomorphized.
@@ -1319,7 +1357,7 @@ fn collect_const_value<'tcx>(
1319
1357
#[ instrument( skip( tcx, mode) , level = "debug" ) ]
1320
1358
fn collect_roots ( tcx : TyCtxt < ' _ > , mode : MonoItemCollectionStrategy ) -> Vec < MonoItem < ' _ > > {
1321
1359
debug ! ( "collecting roots" ) ;
1322
- let mut roots = Vec :: new ( ) ;
1360
+ let mut roots = MonoItems :: new ( tcx ) ;
1323
1361
1324
1362
{
1325
1363
let entry_fn = tcx. entry_fn ( ( ) ) ;
0 commit comments