Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 1add34f

Browse files
committedNov 4, 2024
Don't duplicate collection results
1 parent 239084c commit 1add34f

File tree

5 files changed

+84
-46
lines changed

5 files changed

+84
-46
lines changed
 

‎compiler/rustc_monomorphize/src/collector.rs

+55-17
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,44 @@ pub(crate) struct UsageMap<'tcx> {
255255
user_map: UnordMap<MonoItem<'tcx>, Vec<MonoItem<'tcx>>>,
256256
}
257257

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+
}
259296

260297
/// The state that is shared across the concurrent threads that are doing collection.
261298
struct SharedState<'tcx> {
@@ -273,14 +310,11 @@ impl<'tcx> UsageMap<'tcx> {
273310
UsageMap { used_map: Default::default(), user_map: Default::default() }
274311
}
275312

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
281315
'tcx: 'a,
282316
{
283-
let used_items: Vec<_> = used_items.iter().map(|item| item.node).collect();
317+
let used_items = used_items.items();
284318
for &used_item in used_items.iter() {
285319
self.user_map.entry(used_item).or_default().push(user_item);
286320
}
@@ -343,8 +377,8 @@ fn collect_items_rec<'tcx>(
343377
// harm in that, the mention visit will trigger all the queries and the results are cached.
344378
}
345379

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);
348382
let recursion_depth_reset;
349383

350384
// Post-monomorphization errors MVP
@@ -430,8 +464,8 @@ fn collect_items_rec<'tcx>(
430464

431465
rustc_data_structures::stack::ensure_sufficient_stack(|| {
432466
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());
435469
});
436470
}
437471
MonoItem::GlobalAsm(item_id) => {
@@ -503,7 +537,7 @@ fn collect_items_rec<'tcx>(
503537
if mode == CollectionMode::MentionedItems {
504538
assert!(used_items.is_empty(), "'mentioned' collection should never encounter used items");
505539
} else {
506-
for used_item in used_items {
540+
for used_item in used_items.into_iter() {
507541
collect_items_rec(
508542
tcx,
509543
used_item,
@@ -517,7 +551,7 @@ fn collect_items_rec<'tcx>(
517551

518552
// Walk over mentioned items *after* used items, so that if an item is both mentioned and used then
519553
// 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() {
521555
collect_items_rec(
522556
tcx,
523557
mentioned_item,
@@ -1194,8 +1228,8 @@ fn collect_items_of_instance<'tcx>(
11941228
// mentioned item. So instead we collect all pre-monomorphized `MentionedItem` that were already
11951229
// added to `used_items` in a hash set, which can efficiently query in the
11961230
// `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);
11991233
let mut used_mentioned_items = Default::default();
12001234
let mut collector = MirUsedCollector {
12011235
tcx,
@@ -1238,7 +1272,11 @@ fn items_of_instance<'tcx>(
12381272
(instance, mode): (Instance<'tcx>, CollectionMode),
12391273
) -> (&'tcx [Spanned<MonoItem<'tcx>>], &'tcx [Spanned<MonoItem<'tcx>>]) {
12401274
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)
12421280
}
12431281

12441282
/// `item` must be already monomorphized.
@@ -1319,7 +1357,7 @@ fn collect_const_value<'tcx>(
13191357
#[instrument(skip(tcx, mode), level = "debug")]
13201358
fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionStrategy) -> Vec<MonoItem<'_>> {
13211359
debug!("collecting roots");
1322-
let mut roots = Vec::new();
1360+
let mut roots = MonoItems::new(tcx);
13231361

13241362
{
13251363
let entry_fn = tcx.entry_fn(());

‎tests/ui/codegen/overflow-during-mono.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//~ ERROR overflow evaluating the requirement `{closure@$DIR/overflow-during-mono.rs:13:41: 13:44}: Sized`
1+
//~ ERROR overflow evaluating the requirement
22
//@ build-fail
33

44
#![recursion_limit = "32"]

‎tests/ui/codegen/overflow-during-mono.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
error[E0275]: overflow evaluating the requirement `{closure@$DIR/overflow-during-mono.rs:13:41: 13:44}: Sized`
1+
error[E0275]: overflow evaluating the requirement `{closure@$DIR/overflow-during-mono.rs:14:36: 14:39}: Sized`
22
|
33
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "64"]` attribute to your crate (`overflow_during_mono`)
4-
= note: required for `Filter<std::array::IntoIter<i32, 11>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>` to implement `Iterator`
4+
= note: required for `Filter<std::array::IntoIter<i32, 11>, {closure@$DIR/overflow-during-mono.rs:14:36: 14:39}>` to implement `Iterator`
55
= note: 31 redundant requirements hidden
6-
= note: required for `Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<std::array::IntoIter<i32, 11>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>` to implement `Iterator`
7-
= note: required for `Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<std::array::IntoIter<i32, 11>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>` to implement `IntoIterator`
6+
= note: required for `Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<std::array::IntoIter<i32, 11>, {closure@$DIR/overflow-during-mono.rs:14:36: 14:39}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:14:36: 14:39}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:14:36: 14:39}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:14:36: 14:39}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:14:36: 14:39}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:14:36: 14:39}>, {closure@$DIR/overflow-during-mono.rs:14:36: 14:39}>, {closure@$DIR/overflow-during-mono.rs:14:36: 14:39}>, {closure@$DIR/overflow-during-mono.rs:14:36: 14:39}>, {closure@$DIR/overflow-during-mono.rs:14:36: 14:39}>, {closure@$DIR/overflow-during-mono.rs:14:36: 14:39}>, {closure@$DIR/overflow-during-mono.rs:14:36: 14:39}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:14:36: 14:39}>, {closure@$DIR/overflow-during-mono.rs:14:36: 14:39}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:14:36: 14:39}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>` to implement `Iterator`
7+
= note: required for `Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<std::array::IntoIter<i32, 11>, {closure@$DIR/overflow-during-mono.rs:14:36: 14:39}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:14:36: 14:39}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:14:36: 14:39}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:14:36: 14:39}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:14:36: 14:39}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:14:36: 14:39}>, {closure@$DIR/overflow-during-mono.rs:14:36: 14:39}>, {closure@$DIR/overflow-during-mono.rs:14:36: 14:39}>, {closure@$DIR/overflow-during-mono.rs:14:36: 14:39}>, {closure@$DIR/overflow-during-mono.rs:14:36: 14:39}>, {closure@$DIR/overflow-during-mono.rs:14:36: 14:39}>, {closure@$DIR/overflow-during-mono.rs:14:36: 14:39}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:14:36: 14:39}>, {closure@$DIR/overflow-during-mono.rs:14:36: 14:39}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:14:36: 14:39}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>` to implement `IntoIterator`
88

99
error: aborting due to 1 previous error
1010

Original file line numberDiff line numberDiff line change
@@ -1,23 +1,3 @@
1-
error[E0080]: evaluation of `foo::<i32>::{constant#0}` failed
2-
--> $DIR/const-expr-generic-err.rs:4:13
3-
|
4-
LL | const { assert!(std::mem::size_of::<T>() == 0); }
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: std::mem::size_of::<T>() == 0', $DIR/const-expr-generic-err.rs:4:13
6-
|
7-
= note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
8-
9-
note: erroneous constant encountered
10-
--> $DIR/const-expr-generic-err.rs:4:5
11-
|
12-
LL | const { assert!(std::mem::size_of::<T>() == 0); }
13-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
14-
15-
note: the above error was encountered while instantiating `fn foo::<i32>`
16-
--> $DIR/const-expr-generic-err.rs:12:5
17-
|
18-
LL | foo::<i32>();
19-
| ^^^^^^^^^^^^
20-
211
error[E0080]: evaluation of `bar::<0>::{constant#0}` failed
222
--> $DIR/const-expr-generic-err.rs:8:13
233
|
@@ -44,6 +24,26 @@ note: the above error was encountered while instantiating `fn bar::<0>`
4424
LL | bar::<0>();
4525
| ^^^^^^^^^^
4626

27+
error[E0080]: evaluation of `foo::<i32>::{constant#0}` failed
28+
--> $DIR/const-expr-generic-err.rs:4:13
29+
|
30+
LL | const { assert!(std::mem::size_of::<T>() == 0); }
31+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: std::mem::size_of::<T>() == 0', $DIR/const-expr-generic-err.rs:4:13
32+
|
33+
= note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
34+
35+
note: erroneous constant encountered
36+
--> $DIR/const-expr-generic-err.rs:4:5
37+
|
38+
LL | const { assert!(std::mem::size_of::<T>() == 0); }
39+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
40+
41+
note: the above error was encountered while instantiating `fn foo::<i32>`
42+
--> $DIR/const-expr-generic-err.rs:12:5
43+
|
44+
LL | foo::<i32>();
45+
| ^^^^^^^^^^^^
46+
4747
error: aborting due to 2 previous errors
4848

4949
For more information about this error, try `rustc --explain E0080`.

‎tests/ui/type_length_limit.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
error: reached the type-length limit while instantiating `<{closure@rt::lang_start<()>::{closure#0}} as FnMut<()>>::call_mut`
2+
|
3+
= help: consider adding a `#![type_length_limit="10"]` attribute to your crate
4+
15
error: reached the type-length limit while instantiating `std::mem::drop::<Option<((((..., ..., ...), ..., ...), ..., ...), ..., ...)>>`
26
--> $DIR/type_length_limit.rs:32:5
37
|
@@ -7,9 +11,5 @@ LL | drop::<Option<A>>(None);
711
= help: consider adding a `#![type_length_limit="4010"]` attribute to your crate
812
= note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit/type_length_limit.long-type.txt'
913

10-
error: reached the type-length limit while instantiating `<{closure@rt::lang_start<()>::{closure#0}} as FnMut<()>>::call_mut`
11-
|
12-
= help: consider adding a `#![type_length_limit="10"]` attribute to your crate
13-
1414
error: aborting due to 2 previous errors
1515

0 commit comments

Comments
 (0)
Failed to load comments.