Skip to content

Commit

Permalink
Auto merge of rust-lang#120942 - compiler-errors:deep-assoc-hang, r=lcnr
Browse files Browse the repository at this point in the history
Ignore own item bounds in parent alias types in `for_each_item_bound`

Fixes rust-lang#120912

I want to get a vibe check on this approach, which is very obviously a hack, but I believe something that is forwards-compatible with a more thorough solution and "good enough for now".

The problem here is that for a really deep rigid associated type, we are now repeatedly considering unrelated item bounds from the parent alias types, meaning we're doing a *lot* of extra work in the MIR inliner for deeply substituted rigid projections.

This feels intimately related to rust-lang#107614. In that PR, we split *supertrait* bounds (bound which share the same `Self` type as the predicate which is being elaborated) and *implied* bounds (anything that is implied by elaborating the predicate).

The problem here is related to the fact that we don't maintain the split between these two for `item_bounds`. If we did, then when recursing into a parent alias type, we'd want to consider only the bounds that are given by [`PredicateFilter::All`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/astconv/enum.PredicateFilter.html#variant.SelfOnly) **except** those given by [`PredicateFilter::SelfOnly`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/astconv/enum.PredicateFilter.html#variant.SelfOnly).
  • Loading branch information
bors committed Feb 13, 2024
2 parents fd9bb7f + 38df5bd commit c1b1174
Showing 1 changed file with 16 additions and 0 deletions.
16 changes: 16 additions & 0 deletions compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1605,6 +1605,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
on_ambiguity: impl FnOnce(),
) -> ControlFlow<T, ()> {
let mut idx = 0;
let mut in_parent_alias_type = false;

loop {
let (kind, alias_ty) = match *self_ty.kind() {
ty::Alias(kind @ (ty::Projection | ty::Opaque), alias_ty) => (kind, alias_ty),
Expand All @@ -1618,6 +1620,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
for bound in
self.tcx().item_bounds(alias_ty.def_id).instantiate(self.tcx(), alias_ty.args)
{
// HACK: On subsequent recursions, we only care about bounds that don't
// share the same type as `self_ty`. This is because for truly rigid
// projections, we will never be able to equate, e.g. `<T as Tr>::A`
// with `<<T as Tr>::A as Tr>::A`.
if in_parent_alias_type {
match bound.kind().skip_binder() {
ty::ClauseKind::Trait(tr) if tr.self_ty() == self_ty => continue,
ty::ClauseKind::Projection(p) if p.self_ty() == self_ty => continue,
_ => {}
}
}

for_each(self, bound, idx)?;
idx += 1;
}
Expand All @@ -1627,6 +1641,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
} else {
return ControlFlow::Continue(());
}

in_parent_alias_type = true;
}
}

Expand Down

0 comments on commit c1b1174

Please sign in to comment.