diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 496ddbfebd4f0..cccb6599359e4 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -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(()); diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index bd61bcc7f4d07..9b93ef3bd60ed 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -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(()); diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 3e84404e0dab9..e9e24afe2a7d1 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -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) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index a9ac96424d018..fe603c3395a03 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1605,6 +1605,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { pub(super) fn for_each_item_bound( &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>, @@ -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; }