Skip to content

Commit 4211805

Browse files
Handle bounds that come from the trait itself
1 parent 18a08f1 commit 4211805

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
@@ -2059,23 +2059,27 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
20592059
match path.res {
20602060
Res::Def(DefKind::TyParam, _) | Res::SelfTyParam { trait_: _ } => {
20612061
let mut bounds =
2062-
self.for_each_in_scope_predicate(path.res).filter_map(|trait_| {
2062+
self.for_each_trait_bound_on_res(path.res).filter_map(|trait_def_id| {
20632063
BoundVarContext::supertrait_hrtb_vars(
20642064
self.tcx,
2065-
trait_.trait_ref.trait_def_id()?,
2065+
trait_def_id,
20662066
item_segment.ident,
20672067
ty::AssocKind::Fn,
20682068
)
20692069
});
20702070

20712071
let one_bound = bounds.next();
2072-
let second_bound = bounds.next();
20732072

2074-
if second_bound.is_some() {
2075-
self.tcx
2076-
.dcx()
2077-
.span_delayed_bug(path.span, "ambiguous resolution for RTN path");
2078-
return;
2073+
// Don't bail if we have identical bounds, which may be collected from
2074+
// something like `T: Bound + Bound`, or via elaborating supertraits.
2075+
for second_bound in bounds {
2076+
if Some(&second_bound) != one_bound.as_ref() {
2077+
self.tcx.dcx().span_delayed_bug(
2078+
path.span,
2079+
"ambiguous resolution for RTN path",
2080+
);
2081+
return;
2082+
}
20792083
}
20802084

20812085
let Some((bound_vars, assoc_item)) = one_bound else {
@@ -2084,6 +2088,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
20842088
.span_delayed_bug(path.span, "no resolution for RTN path");
20852089
return;
20862090
};
2091+
20872092
(bound_vars, assoc_item.def_id, item_segment)
20882093
}
20892094
// If we have a self type alias (in an impl), try to resolve an
@@ -2150,12 +2155,12 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
21502155
self.record_late_bound_vars(item_segment.hir_id, existing_bound_vars_saved);
21512156
}
21522157

2153-
/// Walk the generics of the item for a trait-ref whose self type
2154-
/// corresponds to the expected res.
2155-
fn for_each_in_scope_predicate(
2158+
/// Walk the generics of the item for a trait bound whose self type
2159+
/// corresponds to the expected res, and return the trait def id.
2160+
fn for_each_trait_bound_on_res(
21562161
&self,
21572162
expected_res: Res,
2158-
) -> impl Iterator<Item = &'tcx hir::PolyTraitRef<'tcx>> + use<'tcx, '_> {
2163+
) -> impl Iterator<Item = DefId> + use<'tcx, '_> {
21592164
std::iter::from_coroutine(
21602165
#[coroutine]
21612166
move || {
@@ -2171,7 +2176,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
21712176
| Scope::ObjectLifetimeDefault { s, .. }
21722177
| Scope::Supertrait { s, .. }
21732178
| Scope::TraitRefBoundary { s }
2174-
| Scope::LateBoundary { s, .. } => {
2179+
| Scope::LateBoundary { s, .. }
2180+
| Scope::Opaque { s, .. } => {
21752181
next_scope = Some(s);
21762182
continue;
21772183
}
@@ -2184,7 +2190,17 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
21842190
}
21852191
};
21862192
let node = self.tcx.hir_node(hir_id);
2187-
if let Some(generics) = node.generics() {
2193+
// If this is a `Self` bound in a trait, yield the trait itself.
2194+
// Specifically, we don't need to look at any supertraits since
2195+
// we already do that in `BoundVarContext::supertrait_hrtb_vars`.
2196+
if let Res::SelfTyParam { trait_: _ } = expected_res
2197+
&& let hir::Node::Item(item) = node
2198+
&& let hir::ItemKind::Trait(..) = item.kind
2199+
{
2200+
// Yield the trait's def id. Supertraits will be
2201+
// elaborated from that.
2202+
yield item.owner_id.def_id.to_def_id();
2203+
} else if let Some(generics) = node.generics() {
21882204
for pred in generics.predicates {
21892205
let hir::WherePredicate::BoundPredicate(pred) = pred else {
21902206
continue;
@@ -2198,24 +2214,24 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
21982214
if bounded_path.res != expected_res {
21992215
continue;
22002216
}
2201-
yield pred.bounds;
2217+
for pred in pred.bounds {
2218+
match pred {
2219+
hir::GenericBound::Trait(poly_trait_ref) => {
2220+
if let Some(def_id) =
2221+
poly_trait_ref.trait_ref.trait_def_id()
2222+
{
2223+
yield def_id;
2224+
}
2225+
}
2226+
hir::GenericBound::Outlives(_)
2227+
| hir::GenericBound::Use(_, _) => {}
2228+
}
2229+
}
22022230
}
22032231
}
2204-
// Also consider supertraits for `Self` res...
2205-
if let Res::SelfTyParam { trait_: _ } = expected_res
2206-
&& let hir::Node::Item(item) = node
2207-
&& let hir::ItemKind::Trait(_, _, _, supertraits, _) = item.kind
2208-
{
2209-
yield supertraits;
2210-
}
22112232
}
22122233
},
22132234
)
2214-
.flatten()
2215-
.filter_map(|pred| match pred {
2216-
hir::GenericBound::Trait(poly_trait_ref) => Some(poly_trait_ref),
2217-
hir::GenericBound::Outlives(_) | hir::GenericBound::Use(_, _) => None,
2218-
})
22192235
.fuse()
22202236
}
22212237
}

0 commit comments

Comments
 (0)