Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions compiler/rustc_trait_selection/src/traits/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -825,6 +825,11 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
let mut ambiguous = false;
let _ = selcx.for_each_item_bound(
obligation.predicate.self_ty(),
|clause, _| {
clause.as_projection_clause().is_some_and(|clause| {
clause.item_def_id() == obligation.predicate.expect_projection_def_id()
})
},
|selcx, clause, _, _| {
let Some(clause) = clause.as_projection_clause() else {
return ControlFlow::Continue(());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// normalization, so try to deduplicate when possible to avoid
// unnecessary ambiguity.
let mut distinct_normalized_bounds = FxHashSet::default();
// Sizedness candidates are only lazily elaborated for `MetaSized`
// obligations, so check the obligation once instead of per bound.
let obligation_is_metasized =
self.tcx().is_lang_item(obligation.predicate.def_id(), LangItem::MetaSized);
let _ = self.for_each_item_bound::<!>(
placeholder_trait_predicate.self_ty(),
|bound, _| {
bound.as_trait_clause().is_some_and(|bound| {
bound.polarity() == placeholder_trait_predicate.polarity
&& (obligation_is_metasized
|| bound.def_id() == placeholder_trait_predicate.def_id())
})
},
|selcx, bound, idx, alias_bound_kind| {
let Some(bound) = bound.as_trait_clause() else {
return ControlFlow::Continue(());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let candidate_predicate = self
.for_each_item_bound(
placeholder_self_ty,
|_, clause_idx| clause_idx == idx,
|_, clause, clause_idx, _| {
if clause_idx == idx {
ControlFlow::Break(clause)
Expand Down
11 changes: 9 additions & 2 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,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
pub(super) fn for_each_item_bound<T>(
&mut self,
mut self_ty: Ty<'tcx>,
mut filter: impl FnMut(ty::Clause<'tcx>, usize) -> bool,
mut for_each: impl FnMut(
&mut Self,
ty::Clause<'tcx>,
Expand Down Expand Up @@ -1642,8 +1643,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
self.tcx().item_self_bounds(def_id)
};

for bound in relevant_bounds.instantiate(self.tcx(), alias_ty.args).skip_norm_wip() {
for_each(self, bound, idx, alias_bound_kind)?;
// Inspect only parameter-independent data in the uninstantiated clause.
// Keep the original index even for skipped clauses: selection stores it
// and confirmation must retrieve the same bound later.
for bound in relevant_bounds.transpose_iter() {
if filter(bound.skip_binder(), idx) {
let bound = bound.instantiate(self.tcx(), alias_ty.args).skip_norm_wip();
for_each(self, bound, idx, alias_bound_kind)?;
}
idx += 1;
}

Expand Down