Skip to content

Commit fcb40d2

Browse files
Handle bounds that come from the trait itself
1 parent e7bb737 commit fcb40d2

File tree

1 file changed

+39
-25
lines changed

1 file changed

+39
-25
lines changed

compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs

+39-25
Original file line numberDiff line numberDiff line change
@@ -2052,23 +2052,27 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
20522052
match path.res {
20532053
Res::Def(DefKind::TyParam, _) | Res::SelfTyParam { trait_: _ } => {
20542054
let mut bounds =
2055-
self.for_each_in_scope_predicate(path.res).filter_map(|trait_| {
2055+
self.for_each_trait_bound_on_res(path.res).filter_map(|trait_def_id| {
20562056
BoundVarContext::supertrait_hrtb_vars(
20572057
self.tcx,
2058-
trait_.trait_ref.trait_def_id()?,
2058+
trait_def_id,
20592059
item_segment.ident,
20602060
ty::AssocKind::Fn,
20612061
)
20622062
});
20632063

20642064
let one_bound = bounds.next();
2065-
let second_bound = bounds.next();
20662065

2067-
if second_bound.is_some() {
2068-
self.tcx
2069-
.dcx()
2070-
.span_delayed_bug(path.span, "ambiguous resolution for RTN path");
2071-
return;
2066+
// Don't bail if we have identical bounds, which may be collected from
2067+
// something like `T: Bound + Bound`, or via elaborating supertraits.
2068+
for second_bound in bounds {
2069+
if Some(&second_bound) != one_bound.as_ref() {
2070+
self.tcx.dcx().span_delayed_bug(
2071+
path.span,
2072+
"ambiguous resolution for RTN path",
2073+
);
2074+
return;
2075+
}
20722076
}
20732077

20742078
let Some((bound_vars, assoc_item)) = one_bound else {
@@ -2077,6 +2081,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
20772081
.span_delayed_bug(path.span, "no resolution for RTN path");
20782082
return;
20792083
};
2084+
20802085
(bound_vars, assoc_item.def_id, item_segment)
20812086
}
20822087
// If we have a self type alias (in an impl), try to resolve an
@@ -2145,10 +2150,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
21452150

21462151
/// Walk the generics of the item for a trait-ref whose self type
21472152
/// corresponds to the expected res.
2148-
fn for_each_in_scope_predicate(
2153+
fn for_each_trait_bound_on_res(
21492154
&self,
21502155
expected_res: Res,
2151-
) -> impl Iterator<Item = &'tcx hir::PolyTraitRef<'tcx>> + use<'tcx, '_> {
2156+
) -> impl Iterator<Item = DefId> + use<'tcx, '_> {
21522157
std::iter::from_coroutine(
21532158
#[coroutine]
21542159
move || {
@@ -2164,7 +2169,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
21642169
| Scope::ObjectLifetimeDefault { s, .. }
21652170
| Scope::Supertrait { s, .. }
21662171
| Scope::TraitRefBoundary { s }
2167-
| Scope::LateBoundary { s, .. } => {
2172+
| Scope::LateBoundary { s, .. }
2173+
| Scope::Opaque { s, .. } => {
21682174
next_scope = Some(s);
21692175
continue;
21702176
}
@@ -2177,7 +2183,15 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
21772183
}
21782184
};
21792185
let node = self.tcx.hir_node(hir_id);
2180-
if let Some(generics) = node.generics() {
2186+
// If this is a `Self` bound in a trait, yield the trait self.
2187+
if let Res::SelfTyParam { trait_: _ } = expected_res
2188+
&& let hir::Node::Item(item) = node
2189+
&& let hir::ItemKind::Trait(..) = item.kind
2190+
{
2191+
// Yield the trait's def id. Supertraits will be
2192+
// elaborated from that.
2193+
yield item.owner_id.def_id.to_def_id();
2194+
} else if let Some(generics) = node.generics() {
21812195
for pred in generics.predicates {
21822196
let hir::WherePredicate::BoundPredicate(pred) = pred else {
21832197
continue;
@@ -2191,24 +2205,24 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
21912205
if bounded_path.res != expected_res {
21922206
continue;
21932207
}
2194-
yield pred.bounds;
2208+
for pred in pred.bounds {
2209+
match pred {
2210+
hir::GenericBound::Trait(poly_trait_ref) => {
2211+
if let Some(def_id) =
2212+
poly_trait_ref.trait_ref.trait_def_id()
2213+
{
2214+
yield def_id;
2215+
}
2216+
}
2217+
hir::GenericBound::Outlives(_)
2218+
| hir::GenericBound::Use(_, _) => {}
2219+
}
2220+
}
21952221
}
21962222
}
2197-
// Also consider supertraits for `Self` res...
2198-
if let Res::SelfTyParam { trait_: _ } = expected_res
2199-
&& let hir::Node::Item(item) = node
2200-
&& let hir::ItemKind::Trait(_, _, _, supertraits, _) = item.kind
2201-
{
2202-
yield supertraits;
2203-
}
22042223
}
22052224
},
22062225
)
2207-
.flatten()
2208-
.filter_map(|pred| match pred {
2209-
hir::GenericBound::Trait(poly_trait_ref) => Some(poly_trait_ref),
2210-
hir::GenericBound::Outlives(_) | hir::GenericBound::Use(_, _) => None,
2211-
})
22122226
.fuse()
22132227
}
22142228
}

0 commit comments

Comments
 (0)