@@ -2051,45 +2051,30 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
2051
2051
} ;
2052
2052
match path. res {
2053
2053
Res :: Def ( DefKind :: TyParam , _) | Res :: SelfTyParam { trait_ : _ } => {
2054
- // Get the generics of this type's hir owner. This is *different*
2055
- // from the generics of the parameter's definition, since we want
2056
- // to be able to resolve an RTN path on a nested body (e.g. method
2057
- // inside an impl) using the where clauses on the method.
2058
- // FIXME(return_type_notation): Think of some better way of doing this.
2059
- let Some ( generics) = self . tcx . hir_owner_node ( hir_id. owner ) . generics ( )
2060
- else {
2061
- return ;
2062
- } ;
2063
-
2064
- // Look for the first bound that contains an associated type that
2065
- // matches the segment that we're looking for. We ignore any subsequent
2066
- // bounds since we'll be emitting a hard error in HIR lowering, so this
2067
- // is purely speculative.
2068
- let one_bound = generics. predicates . iter ( ) . find_map ( |predicate| {
2069
- let hir:: WherePredicate :: BoundPredicate ( predicate) = predicate else {
2070
- return None ;
2071
- } ;
2072
- let hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None , bounded_path) ) =
2073
- predicate. bounded_ty . kind
2074
- else {
2075
- return None ;
2076
- } ;
2077
- if bounded_path. res != path. res {
2078
- return None ;
2079
- }
2080
- predicate. bounds . iter ( ) . find_map ( |bound| {
2081
- let hir:: GenericBound :: Trait ( trait_) = bound else {
2082
- return None ;
2083
- } ;
2054
+ let mut bounds =
2055
+ self . for_each_in_scope_predicate ( path. res ) . filter_map ( |trait_| {
2084
2056
BoundVarContext :: supertrait_hrtb_vars (
2085
2057
self . tcx ,
2086
2058
trait_. trait_ref . trait_def_id ( ) ?,
2087
2059
item_segment. ident ,
2088
2060
ty:: AssocKind :: Fn ,
2089
2061
)
2090
- } )
2091
- } ) ;
2062
+ } ) ;
2063
+
2064
+ let one_bound = bounds. next ( ) ;
2065
+ let second_bound = bounds. next ( ) ;
2066
+
2067
+ if second_bound. is_some ( ) {
2068
+ self . tcx
2069
+ . dcx ( )
2070
+ . span_delayed_bug ( path. span , "ambiguous resolution for RTN path" ) ;
2071
+ return ;
2072
+ }
2073
+
2092
2074
let Some ( ( bound_vars, assoc_item) ) = one_bound else {
2075
+ self . tcx
2076
+ . dcx ( )
2077
+ . span_delayed_bug ( path. span , "no resolution for RTN path" ) ;
2093
2078
return ;
2094
2079
} ;
2095
2080
( bound_vars, assoc_item. def_id , item_segment)
@@ -2157,6 +2142,75 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
2157
2142
existing_bound_vars. extend ( bound_vars) ;
2158
2143
self . record_late_bound_vars ( item_segment. hir_id , existing_bound_vars_saved) ;
2159
2144
}
2145
+
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 (
2149
+ & self ,
2150
+ expected_res : Res ,
2151
+ ) -> impl Iterator < Item = & ' tcx hir:: PolyTraitRef < ' tcx > > + use < ' tcx , ' _ > {
2152
+ std:: iter:: from_coroutine (
2153
+ #[ coroutine]
2154
+ move || {
2155
+ let mut next_scope = Some ( self . scope ) ;
2156
+ while let Some ( current_scope) = next_scope {
2157
+ next_scope = None ;
2158
+ let hir_id = match * current_scope {
2159
+ Scope :: Binder { s, hir_id, .. } => {
2160
+ next_scope = Some ( s) ;
2161
+ hir_id
2162
+ }
2163
+ Scope :: Body { s, .. }
2164
+ | Scope :: ObjectLifetimeDefault { s, .. }
2165
+ | Scope :: Supertrait { s, .. }
2166
+ | Scope :: TraitRefBoundary { s }
2167
+ | Scope :: LateBoundary { s, .. } => {
2168
+ next_scope = Some ( s) ;
2169
+ continue ;
2170
+ }
2171
+ Scope :: Root { opt_parent_item } => {
2172
+ if let Some ( parent_id) = opt_parent_item {
2173
+ self . tcx . local_def_id_to_hir_id ( parent_id)
2174
+ } else {
2175
+ continue ;
2176
+ }
2177
+ }
2178
+ } ;
2179
+ let node = self . tcx . hir_node ( hir_id) ;
2180
+ if let Some ( generics) = node. generics ( ) {
2181
+ for pred in generics. predicates {
2182
+ let hir:: WherePredicate :: BoundPredicate ( pred) = pred else {
2183
+ continue ;
2184
+ } ;
2185
+ let hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None , bounded_path) ) =
2186
+ pred. bounded_ty . kind
2187
+ else {
2188
+ continue ;
2189
+ } ;
2190
+ // Match the expected res.
2191
+ if bounded_path. res != expected_res {
2192
+ continue ;
2193
+ }
2194
+ yield pred. bounds ;
2195
+ }
2196
+ }
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
+ }
2204
+ }
2205
+ } ,
2206
+ )
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
+ } )
2212
+ . fuse ( )
2213
+ }
2160
2214
}
2161
2215
2162
2216
/// Detects late-bound lifetimes and inserts them into
0 commit comments