diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 08d7ff12662c1..05a34beedd272 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -2052,23 +2052,27 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { match path.res { Res::Def(DefKind::TyParam, _) | Res::SelfTyParam { trait_: _ } => { let mut bounds = - self.for_each_in_scope_predicate(path.res).filter_map(|trait_| { + self.for_each_trait_bound_on_res(path.res).filter_map(|trait_def_id| { BoundVarContext::supertrait_hrtb_vars( self.tcx, - trait_.trait_ref.trait_def_id()?, + trait_def_id, item_segment.ident, ty::AssocKind::Fn, ) }); let one_bound = bounds.next(); - let second_bound = bounds.next(); - if second_bound.is_some() { - self.tcx - .dcx() - .span_delayed_bug(path.span, "ambiguous resolution for RTN path"); - return; + // Don't bail if we have identical bounds, which may be collected from + // something like `T: Bound + Bound`, or via elaborating supertraits. + for second_bound in bounds { + if Some(&second_bound) != one_bound.as_ref() { + self.tcx.dcx().span_delayed_bug( + path.span, + "ambiguous resolution for RTN path", + ); + return; + } } let Some((bound_vars, assoc_item)) = one_bound else { @@ -2077,6 +2081,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { .span_delayed_bug(path.span, "no resolution for RTN path"); return; }; + (bound_vars, assoc_item.def_id, item_segment) } // If we have a self type alias (in an impl), try to resolve an @@ -2145,10 +2150,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { /// Walk the generics of the item for a trait-ref whose self type /// corresponds to the expected res. - fn for_each_in_scope_predicate( + fn for_each_trait_bound_on_res( &self, expected_res: Res, - ) -> impl Iterator> + use<'tcx, '_> { + ) -> impl Iterator + use<'tcx, '_> { std::iter::from_coroutine( #[coroutine] move || { @@ -2164,7 +2169,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { | Scope::ObjectLifetimeDefault { s, .. } | Scope::Supertrait { s, .. } | Scope::TraitRefBoundary { s } - | Scope::LateBoundary { s, .. } => { + | Scope::LateBoundary { s, .. } + | Scope::Opaque { s, .. } => { next_scope = Some(s); continue; } @@ -2177,7 +2183,15 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { } }; let node = self.tcx.hir_node(hir_id); - if let Some(generics) = node.generics() { + // If this is a `Self` bound in a trait, yield the trait self. + if let Res::SelfTyParam { trait_: _ } = expected_res + && let hir::Node::Item(item) = node + && let hir::ItemKind::Trait(..) = item.kind + { + // Yield the trait's def id. Supertraits will be + // elaborated from that. + yield item.owner_id.def_id.to_def_id(); + } else if let Some(generics) = node.generics() { for pred in generics.predicates { let hir::WherePredicate::BoundPredicate(pred) = pred else { continue; @@ -2191,24 +2205,24 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { if bounded_path.res != expected_res { continue; } - yield pred.bounds; + for pred in pred.bounds { + match pred { + hir::GenericBound::Trait(poly_trait_ref) => { + if let Some(def_id) = + poly_trait_ref.trait_ref.trait_def_id() + { + yield def_id; + } + } + hir::GenericBound::Outlives(_) + | hir::GenericBound::Use(_, _) => {} + } + } } } - // Also consider supertraits for `Self` res... - if let Res::SelfTyParam { trait_: _ } = expected_res - && let hir::Node::Item(item) = node - && let hir::ItemKind::Trait(_, _, _, supertraits, _) = item.kind - { - yield supertraits; - } } }, ) - .flatten() - .filter_map(|pred| match pred { - hir::GenericBound::Trait(poly_trait_ref) => Some(poly_trait_ref), - hir::GenericBound::Outlives(_) | hir::GenericBound::Use(_, _) => None, - }) .fuse() } }