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