Skip to content

Commit 5fceae3

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

File tree

1 file changed

+43
-27
lines changed

1 file changed

+43
-27
lines changed

compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs

+43-27
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
@@ -2143,12 +2148,12 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
21432148
self.record_late_bound_vars(item_segment.hir_id, existing_bound_vars_saved);
21442149
}
21452150

2146-
/// Walk the generics of the item for a trait-ref whose self type
2147-
/// corresponds to the expected res.
2148-
fn for_each_in_scope_predicate(
2151+
/// Walk the generics of the item for a trait bound whose self type
2152+
/// corresponds to the expected res, and return the trait def id.
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,17 @@ 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 itself.
2187+
// Specifically, we don't need to look at any supertraits since
2188+
// we already do that in `BoundVarContext::supertrait_hrtb_vars`.
2189+
if let Res::SelfTyParam { trait_: _ } = expected_res
2190+
&& let hir::Node::Item(item) = node
2191+
&& let hir::ItemKind::Trait(..) = item.kind
2192+
{
2193+
// Yield the trait's def id. Supertraits will be
2194+
// elaborated from that.
2195+
yield item.owner_id.def_id.to_def_id();
2196+
} else if let Some(generics) = node.generics() {
21812197
for pred in generics.predicates {
21822198
let hir::WherePredicate::BoundPredicate(pred) = pred else {
21832199
continue;
@@ -2191,24 +2207,24 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
21912207
if bounded_path.res != expected_res {
21922208
continue;
21932209
}
2194-
yield pred.bounds;
2210+
for pred in pred.bounds {
2211+
match pred {
2212+
hir::GenericBound::Trait(poly_trait_ref) => {
2213+
if let Some(def_id) =
2214+
poly_trait_ref.trait_ref.trait_def_id()
2215+
{
2216+
yield def_id;
2217+
}
2218+
}
2219+
hir::GenericBound::Outlives(_)
2220+
| hir::GenericBound::Use(_, _) => {}
2221+
}
2222+
}
21952223
}
21962224
}
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-
}
22042225
}
22052226
},
22062227
)
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-
})
22122228
.fuse()
22132229
}
22142230
}

0 commit comments

Comments
 (0)