@@ -2051,45 +2051,30 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
20512051 } ;
20522052 match path. res {
20532053 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_| {
20842056 BoundVarContext :: supertrait_hrtb_vars (
20852057 self . tcx ,
20862058 trait_. trait_ref . trait_def_id ( ) ?,
20872059 item_segment. ident ,
20882060 ty:: AssocKind :: Fn ,
20892061 )
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+
20922074 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" ) ;
20932078 return ;
20942079 } ;
20952080 ( bound_vars, assoc_item. def_id , item_segment)
@@ -2157,6 +2142,75 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
21572142 existing_bound_vars. extend ( bound_vars) ;
21582143 self . record_late_bound_vars ( item_segment. hir_id , existing_bound_vars_saved) ;
21592144 }
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+ }
21602214}
21612215
21622216/// Detects late-bound lifetimes and inserts them into
0 commit comments