@@ -2060,48 +2060,37 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
2060
2060
} ;
2061
2061
match path. res {
2062
2062
Res :: Def ( DefKind :: TyParam , _) | Res :: SelfTyParam { trait_ : _ } => {
2063
- // Get the generics of this type's hir owner. This is *different*
2064
- // from the generics of the parameter's definition, since we want
2065
- // to be able to resolve an RTN path on a nested body (e.g. method
2066
- // inside an impl) using the where clauses on the method.
2067
- // FIXME(return_type_notation): Think of some better way of doing this.
2068
- let Some ( generics) = self . tcx . hir_owner_node ( hir_id. owner ) . generics ( )
2069
- else {
2070
- return ;
2071
- } ;
2072
-
2073
- // Look for the first bound that contains an associated type that
2074
- // matches the segment that we're looking for. We ignore any subsequent
2075
- // bounds since we'll be emitting a hard error in HIR lowering, so this
2076
- // is purely speculative.
2077
- let one_bound = generics. predicates . iter ( ) . find_map ( |predicate| {
2078
- let hir:: WherePredicateKind :: BoundPredicate ( predicate) = predicate. kind
2079
- else {
2080
- return None ;
2081
- } ;
2082
- let hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None , bounded_path) ) =
2083
- predicate. bounded_ty . kind
2084
- else {
2085
- return None ;
2086
- } ;
2087
- if bounded_path. res != path. res {
2088
- return None ;
2089
- }
2090
- predicate. bounds . iter ( ) . find_map ( |bound| {
2091
- let hir:: GenericBound :: Trait ( trait_) = bound else {
2092
- return None ;
2093
- } ;
2063
+ let mut bounds =
2064
+ self . for_each_trait_bound_on_res ( path. res ) . filter_map ( |trait_def_id| {
2094
2065
BoundVarContext :: supertrait_hrtb_vars (
2095
2066
self . tcx ,
2096
- trait_ . trait_ref . trait_def_id ( ) ? ,
2067
+ trait_def_id,
2097
2068
item_segment. ident ,
2098
2069
ty:: AssocKind :: Fn ,
2099
2070
)
2100
- } )
2101
- } ) ;
2102
- let Some ( ( bound_vars, assoc_item) ) = one_bound else {
2071
+ } ) ;
2072
+
2073
+ let Some ( ( bound_vars, assoc_item) ) = bounds. next ( ) else {
2074
+ // This will error in HIR lowering.
2075
+ self . tcx
2076
+ . dcx ( )
2077
+ . span_delayed_bug ( path. span , "no resolution for RTN path" ) ;
2103
2078
return ;
2104
2079
} ;
2080
+
2081
+ // Don't bail if we have identical bounds, which may be collected from
2082
+ // something like `T: Bound + Bound`, or via elaborating supertraits.
2083
+ for ( second_vars, second_assoc_item) in bounds {
2084
+ if second_vars != bound_vars || second_assoc_item != assoc_item {
2085
+ // This will error in HIR lowering.
2086
+ self . tcx . dcx ( ) . span_delayed_bug (
2087
+ path. span ,
2088
+ "ambiguous resolution for RTN path" ,
2089
+ ) ;
2090
+ return ;
2091
+ }
2092
+ }
2093
+
2105
2094
( bound_vars, assoc_item. def_id , item_segment)
2106
2095
}
2107
2096
// If we have a self type alias (in an impl), try to resolve an
@@ -2167,6 +2156,92 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
2167
2156
existing_bound_vars. extend ( bound_vars) ;
2168
2157
self . record_late_bound_vars ( item_segment. hir_id , existing_bound_vars_saved) ;
2169
2158
}
2159
+
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 (
2163
+ & self ,
2164
+ expected_res : Res ,
2165
+ ) -> impl Iterator < Item = DefId > + use < ' tcx , ' _ > {
2166
+ std:: iter:: from_coroutine (
2167
+ #[ coroutine]
2168
+ move || {
2169
+ let mut scope = self . scope ;
2170
+ loop {
2171
+ let hir_id = match * scope {
2172
+ Scope :: Binder { hir_id, .. } => Some ( hir_id) ,
2173
+ Scope :: Root { opt_parent_item : Some ( parent_def_id) } => {
2174
+ Some ( self . tcx . local_def_id_to_hir_id ( parent_def_id) )
2175
+ }
2176
+ Scope :: Body { .. }
2177
+ | Scope :: ObjectLifetimeDefault { .. }
2178
+ | Scope :: Supertrait { .. }
2179
+ | Scope :: TraitRefBoundary { .. }
2180
+ | Scope :: LateBoundary { .. }
2181
+ | Scope :: Opaque { .. }
2182
+ | Scope :: Root { opt_parent_item : None } => None ,
2183
+ } ;
2184
+
2185
+ if let Some ( hir_id) = hir_id {
2186
+ let node = self . tcx . hir_node ( hir_id) ;
2187
+ // If this is a `Self` bound in a trait, yield the trait itself.
2188
+ // Specifically, we don't need to look at any supertraits since
2189
+ // we already do that in `BoundVarContext::supertrait_hrtb_vars`.
2190
+ if let Res :: SelfTyParam { trait_ : _ } = expected_res
2191
+ && let hir:: Node :: Item ( item) = node
2192
+ && let hir:: ItemKind :: Trait ( ..) = item. kind
2193
+ {
2194
+ // Yield the trait's def id. Supertraits will be
2195
+ // elaborated from that.
2196
+ yield item. owner_id . def_id . to_def_id ( ) ;
2197
+ } else if let Some ( generics) = node. generics ( ) {
2198
+ for pred in generics. predicates {
2199
+ let hir:: WherePredicateKind :: BoundPredicate ( pred) = pred. kind
2200
+ else {
2201
+ continue ;
2202
+ } ;
2203
+ let hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None , bounded_path) ) =
2204
+ pred. bounded_ty . kind
2205
+ else {
2206
+ continue ;
2207
+ } ;
2208
+ // Match the expected res.
2209
+ if bounded_path. res != expected_res {
2210
+ continue ;
2211
+ }
2212
+ for pred in pred. bounds {
2213
+ match pred {
2214
+ hir:: GenericBound :: Trait ( poly_trait_ref) => {
2215
+ if let Some ( def_id) =
2216
+ poly_trait_ref. trait_ref . trait_def_id ( )
2217
+ {
2218
+ yield def_id;
2219
+ }
2220
+ }
2221
+ hir:: GenericBound :: Outlives ( _)
2222
+ | hir:: GenericBound :: Use ( _, _) => { }
2223
+ }
2224
+ }
2225
+ }
2226
+ }
2227
+ }
2228
+
2229
+ match * scope {
2230
+ Scope :: Binder { s, .. }
2231
+ | Scope :: Body { s, .. }
2232
+ | Scope :: ObjectLifetimeDefault { s, .. }
2233
+ | Scope :: Supertrait { s, .. }
2234
+ | Scope :: TraitRefBoundary { s }
2235
+ | Scope :: LateBoundary { s, .. }
2236
+ | Scope :: Opaque { s, .. } => {
2237
+ scope = s;
2238
+ }
2239
+ Scope :: Root { .. } => break ,
2240
+ }
2241
+ }
2242
+ } ,
2243
+ )
2244
+ }
2170
2245
}
2171
2246
2172
2247
/// Detects late-bound lifetimes and inserts them into
0 commit comments