Skip to content

Commit

Permalink
Don't duplicate collection results
Browse files Browse the repository at this point in the history
  • Loading branch information
saethlin committed Nov 4, 2024
1 parent 239084c commit 1add34f
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 46 deletions.
72 changes: 55 additions & 17 deletions compiler/rustc_monomorphize/src/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,44 @@ pub(crate) struct UsageMap<'tcx> {
user_map: UnordMap<MonoItem<'tcx>, Vec<MonoItem<'tcx>>>,
}

type MonoItems<'tcx> = Vec<Spanned<MonoItem<'tcx>>>;
struct MonoItems<'tcx> {
tcx: TyCtxt<'tcx>,
// We want a set of MonoItem + Span where trying to re-insert a MonoItem with a different Span
// is ignored. Map does that, but it looks wrong.
items: UnordMap<MonoItem<'tcx>, Span>,
}

impl<'tcx> MonoItems<'tcx> {
fn new(tcx: TyCtxt<'tcx>) -> Self {
Self { tcx, items: UnordMap::default() }
}

fn is_empty(&self) -> bool {
self.items.is_empty()
}

fn push(&mut self, item: Spanned<MonoItem<'tcx>>) {
// Insert only if the entry does not exist. A normal insert would stomp the first span that
// got inserted.
self.items.entry(item.node).or_insert(item.span);
}

fn extend(&mut self, iter: impl IntoIterator<Item = Spanned<MonoItem<'tcx>>>) {
for item in iter {
self.push(item.clone());
}
}

fn into_iter(self) -> impl Iterator<Item = Spanned<MonoItem<'tcx>>> {
self.tcx.with_stable_hashing_context(|hcx| {
self.items.into_sorted(&hcx, true).into_iter().map(|(item, span)| respan(span, item))
})
}

fn items(&self) -> Vec<MonoItem<'tcx>> {
self.tcx.with_stable_hashing_context(|hcx| self.items.keys().cloned().into_sorted(&hcx))
}
}

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

fn record_used<'a>(
&mut self,
user_item: MonoItem<'tcx>,
used_items: &'a [Spanned<MonoItem<'tcx>>],
) where
fn record_used<'a>(&mut self, user_item: MonoItem<'tcx>, used_items: &'a MonoItems<'tcx>)
where
'tcx: 'a,
{
let used_items: Vec<_> = used_items.iter().map(|item| item.node).collect();
let used_items = used_items.items();
for &used_item in used_items.iter() {
self.user_map.entry(used_item).or_default().push(user_item);
}
Expand Down Expand Up @@ -343,8 +377,8 @@ fn collect_items_rec<'tcx>(
// harm in that, the mention visit will trigger all the queries and the results are cached.
}

let mut used_items = MonoItems::new();
let mut mentioned_items = MonoItems::new();
let mut used_items = MonoItems::new(tcx);
let mut mentioned_items = MonoItems::new(tcx);
let recursion_depth_reset;

// Post-monomorphization errors MVP
Expand Down Expand Up @@ -430,8 +464,8 @@ fn collect_items_rec<'tcx>(

rustc_data_structures::stack::ensure_sufficient_stack(|| {
let (used, mentioned) = tcx.items_of_instance((instance, mode));
used_items.extend(used);
mentioned_items.extend(mentioned);
used_items.extend(used.into_iter().copied());
mentioned_items.extend(mentioned.into_iter().copied());
});
}
MonoItem::GlobalAsm(item_id) => {
Expand Down Expand Up @@ -503,7 +537,7 @@ fn collect_items_rec<'tcx>(
if mode == CollectionMode::MentionedItems {
assert!(used_items.is_empty(), "'mentioned' collection should never encounter used items");
} else {
for used_item in used_items {
for used_item in used_items.into_iter() {
collect_items_rec(
tcx,
used_item,
Expand All @@ -517,7 +551,7 @@ fn collect_items_rec<'tcx>(

// Walk over mentioned items *after* used items, so that if an item is both mentioned and used then
// the loop above has fully collected it, so this loop will skip it.
for mentioned_item in mentioned_items {
for mentioned_item in mentioned_items.into_iter() {
collect_items_rec(
tcx,
mentioned_item,
Expand Down Expand Up @@ -1194,8 +1228,8 @@ fn collect_items_of_instance<'tcx>(
// mentioned item. So instead we collect all pre-monomorphized `MentionedItem` that were already
// added to `used_items` in a hash set, which can efficiently query in the
// `body.mentioned_items` loop below without even having to monomorphize the item.
let mut used_items = Default::default();
let mut mentioned_items = Default::default();
let mut used_items = MonoItems::new(tcx);
let mut mentioned_items = MonoItems::new(tcx);
let mut used_mentioned_items = Default::default();
let mut collector = MirUsedCollector {
tcx,
Expand Down Expand Up @@ -1238,7 +1272,11 @@ fn items_of_instance<'tcx>(
(instance, mode): (Instance<'tcx>, CollectionMode),
) -> (&'tcx [Spanned<MonoItem<'tcx>>], &'tcx [Spanned<MonoItem<'tcx>>]) {
let (used_items, mentioned_items) = collect_items_of_instance(tcx, instance, mode);
(tcx.arena.alloc_slice(&used_items), tcx.arena.alloc_slice(&mentioned_items))

let used_items = tcx.arena.alloc_from_iter(used_items.into_iter());
let mentioned_items = tcx.arena.alloc_from_iter(mentioned_items.into_iter());

(used_items, mentioned_items)
}

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

{
let entry_fn = tcx.entry_fn(());
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/codegen/overflow-during-mono.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//~ ERROR overflow evaluating the requirement `{closure@$DIR/overflow-during-mono.rs:13:41: 13:44}: Sized`
//~ ERROR overflow evaluating the requirement
//@ build-fail

#![recursion_limit = "32"]
Expand Down
8 changes: 4 additions & 4 deletions tests/ui/codegen/overflow-during-mono.stderr
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
error[E0275]: overflow evaluating the requirement `{closure@$DIR/overflow-during-mono.rs:13:41: 13:44}: Sized`
error[E0275]: overflow evaluating the requirement `{closure@$DIR/overflow-during-mono.rs:14:36: 14:39}: Sized`
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "64"]` attribute to your crate (`overflow_during_mono`)
= note: required for `Filter<std::array::IntoIter<i32, 11>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>` to implement `Iterator`
= note: required for `Filter<std::array::IntoIter<i32, 11>, {closure@$DIR/overflow-during-mono.rs:14:36: 14:39}>` to implement `Iterator`
= note: 31 redundant requirements hidden
= 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`
= 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`
= 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`
= 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`

error: aborting due to 1 previous error

Expand Down
40 changes: 20 additions & 20 deletions tests/ui/inline-const/const-expr-generic-err.stderr
Original file line number Diff line number Diff line change
@@ -1,23 +1,3 @@
error[E0080]: evaluation of `foo::<i32>::{constant#0}` failed
--> $DIR/const-expr-generic-err.rs:4:13
|
LL | const { assert!(std::mem::size_of::<T>() == 0); }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: std::mem::size_of::<T>() == 0', $DIR/const-expr-generic-err.rs:4:13
|
= note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)

note: erroneous constant encountered
--> $DIR/const-expr-generic-err.rs:4:5
|
LL | const { assert!(std::mem::size_of::<T>() == 0); }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

note: the above error was encountered while instantiating `fn foo::<i32>`
--> $DIR/const-expr-generic-err.rs:12:5
|
LL | foo::<i32>();
| ^^^^^^^^^^^^

error[E0080]: evaluation of `bar::<0>::{constant#0}` failed
--> $DIR/const-expr-generic-err.rs:8:13
|
Expand All @@ -44,6 +24,26 @@ note: the above error was encountered while instantiating `fn bar::<0>`
LL | bar::<0>();
| ^^^^^^^^^^

error[E0080]: evaluation of `foo::<i32>::{constant#0}` failed
--> $DIR/const-expr-generic-err.rs:4:13
|
LL | const { assert!(std::mem::size_of::<T>() == 0); }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: std::mem::size_of::<T>() == 0', $DIR/const-expr-generic-err.rs:4:13
|
= note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)

note: erroneous constant encountered
--> $DIR/const-expr-generic-err.rs:4:5
|
LL | const { assert!(std::mem::size_of::<T>() == 0); }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

note: the above error was encountered while instantiating `fn foo::<i32>`
--> $DIR/const-expr-generic-err.rs:12:5
|
LL | foo::<i32>();
| ^^^^^^^^^^^^

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0080`.
8 changes: 4 additions & 4 deletions tests/ui/type_length_limit.stderr
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
error: reached the type-length limit while instantiating `<{closure@rt::lang_start<()>::{closure#0}} as FnMut<()>>::call_mut`
|
= help: consider adding a `#![type_length_limit="10"]` attribute to your crate

error: reached the type-length limit while instantiating `std::mem::drop::<Option<((((..., ..., ...), ..., ...), ..., ...), ..., ...)>>`
--> $DIR/type_length_limit.rs:32:5
|
Expand All @@ -7,9 +11,5 @@ LL | drop::<Option<A>>(None);
= help: consider adding a `#![type_length_limit="4010"]` attribute to your crate
= note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit/type_length_limit.long-type.txt'

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

error: aborting due to 2 previous errors

0 comments on commit 1add34f

Please sign in to comment.