Skip to content

Commit 959801f

Browse files
Handle bounds that come from the trait itself
1 parent 87c045e commit 959801f

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

20732073
let one_bound = bounds.next();
2074-
let second_bound = bounds.next();
20752074

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

20832087
let Some((bound_vars, assoc_item)) = one_bound else {
@@ -2086,6 +2090,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
20862090
.span_delayed_bug(path.span, "no resolution for RTN path");
20872091
return;
20882092
};
2093+
20892094
(bound_vars, assoc_item.def_id, item_segment)
20902095
}
20912096
// If we have a self type alias (in an impl), try to resolve an
@@ -2152,12 +2157,12 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
21522157
self.record_late_bound_vars(item_segment.hir_id, existing_bound_vars_saved);
21532158
}
21542159

2155-
/// Walk the generics of the item for a trait-ref whose self type
2156-
/// corresponds to the expected res.
2157-
fn for_each_in_scope_predicate(
2160+
/// Walk the generics of the item for a trait bound whose self type
2161+
/// corresponds to the expected res, and return the trait def id.
2162+
fn for_each_trait_bound_on_res(
21582163
&self,
21592164
expected_res: Res,
2160-
) -> impl Iterator<Item = &'tcx hir::PolyTraitRef<'tcx>> + use<'tcx, '_> {
2165+
) -> impl Iterator<Item = DefId> + use<'tcx, '_> {
21612166
std::iter::from_coroutine(
21622167
#[coroutine]
21632168
move || {
@@ -2173,7 +2178,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
21732178
| Scope::ObjectLifetimeDefault { s, .. }
21742179
| Scope::Supertrait { s, .. }
21752180
| Scope::TraitRefBoundary { s }
2176-
| Scope::LateBoundary { s, .. } => {
2181+
| Scope::LateBoundary { s, .. }
2182+
| Scope::Opaque { s, .. } => {
21772183
next_scope = Some(s);
21782184
continue;
21792185
}
@@ -2186,7 +2192,17 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
21862192
}
21872193
};
21882194
let node = self.tcx.hir_node(hir_id);
2189-
if let Some(generics) = node.generics() {
2195+
// If this is a `Self` bound in a trait, yield the trait itself.
2196+
// Specifically, we don't need to look at any supertraits since
2197+
// we already do that in `BoundVarContext::supertrait_hrtb_vars`.
2198+
if let Res::SelfTyParam { trait_: _ } = expected_res
2199+
&& let hir::Node::Item(item) = node
2200+
&& let hir::ItemKind::Trait(..) = item.kind
2201+
{
2202+
// Yield the trait's def id. Supertraits will be
2203+
// elaborated from that.
2204+
yield item.owner_id.def_id.to_def_id();
2205+
} else if let Some(generics) = node.generics() {
21902206
for pred in generics.predicates {
21912207
let hir::WherePredicateKind::BoundPredicate(pred) = pred.kind else {
21922208
continue;
@@ -2200,24 +2216,24 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
22002216
if bounded_path.res != expected_res {
22012217
continue;
22022218
}
2203-
yield pred.bounds;
2219+
for pred in pred.bounds {
2220+
match pred {
2221+
hir::GenericBound::Trait(poly_trait_ref) => {
2222+
if let Some(def_id) =
2223+
poly_trait_ref.trait_ref.trait_def_id()
2224+
{
2225+
yield def_id;
2226+
}
2227+
}
2228+
hir::GenericBound::Outlives(_)
2229+
| hir::GenericBound::Use(_, _) => {}
2230+
}
2231+
}
22042232
}
22052233
}
2206-
// Also consider supertraits for `Self` res...
2207-
if let Res::SelfTyParam { trait_: _ } = expected_res
2208-
&& let hir::Node::Item(item) = node
2209-
&& let hir::ItemKind::Trait(_, _, _, supertraits, _) = item.kind
2210-
{
2211-
yield supertraits;
2212-
}
22132234
}
22142235
},
22152236
)
2216-
.flatten()
2217-
.filter_map(|pred| match pred {
2218-
hir::GenericBound::Trait(poly_trait_ref) => Some(poly_trait_ref),
2219-
hir::GenericBound::Outlives(_) | hir::GenericBound::Use(_, _) => None,
2220-
})
22212237
.fuse()
22222238
}
22232239
}

0 commit comments

Comments
 (0)