@@ -2060,46 +2060,30 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
20602060 } ;
20612061 match path. res {
20622062 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_in_scope_predicate ( path. res ) . filter_map ( |trait_| {
20942065 BoundVarContext :: supertrait_hrtb_vars (
20952066 self . tcx ,
20962067 trait_. trait_ref . trait_def_id ( ) ?,
20972068 item_segment. ident ,
20982069 ty:: AssocKind :: Fn ,
20992070 )
2100- } )
2101- } ) ;
2071+ } ) ;
2072+
2073+ let one_bound = bounds. next ( ) ;
2074+ let second_bound = bounds. next ( ) ;
2075+
2076+ if second_bound. is_some ( ) {
2077+ self . tcx
2078+ . dcx ( )
2079+ . span_delayed_bug ( path. span , "ambiguous resolution for RTN path" ) ;
2080+ return ;
2081+ }
2082+
21022083 let Some ( ( bound_vars, assoc_item) ) = one_bound else {
2084+ self . tcx
2085+ . dcx ( )
2086+ . span_delayed_bug ( path. span , "no resolution for RTN path" ) ;
21032087 return ;
21042088 } ;
21052089 ( bound_vars, assoc_item. def_id , item_segment)
@@ -2167,6 +2151,75 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
21672151 existing_bound_vars. extend ( bound_vars) ;
21682152 self . record_late_bound_vars ( item_segment. hir_id , existing_bound_vars_saved) ;
21692153 }
2154+
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 (
2158+ & self ,
2159+ expected_res : Res ,
2160+ ) -> impl Iterator < Item = & ' tcx hir:: PolyTraitRef < ' tcx > > + use < ' tcx , ' _ > {
2161+ std:: iter:: from_coroutine (
2162+ #[ coroutine]
2163+ move || {
2164+ let mut next_scope = Some ( self . scope ) ;
2165+ while let Some ( current_scope) = next_scope {
2166+ next_scope = None ;
2167+ let hir_id = match * current_scope {
2168+ Scope :: Binder { s, hir_id, .. } => {
2169+ next_scope = Some ( s) ;
2170+ hir_id
2171+ }
2172+ Scope :: Body { s, .. }
2173+ | Scope :: ObjectLifetimeDefault { s, .. }
2174+ | Scope :: Supertrait { s, .. }
2175+ | Scope :: TraitRefBoundary { s }
2176+ | Scope :: LateBoundary { s, .. } => {
2177+ next_scope = Some ( s) ;
2178+ continue ;
2179+ }
2180+ Scope :: Root { opt_parent_item } => {
2181+ if let Some ( parent_id) = opt_parent_item {
2182+ self . tcx . local_def_id_to_hir_id ( parent_id)
2183+ } else {
2184+ continue ;
2185+ }
2186+ }
2187+ } ;
2188+ let node = self . tcx . hir_node ( hir_id) ;
2189+ if let Some ( generics) = node. generics ( ) {
2190+ for pred in generics. predicates {
2191+ let hir:: WherePredicateKind :: BoundPredicate ( pred) = pred. kind else {
2192+ continue ;
2193+ } ;
2194+ let hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None , bounded_path) ) =
2195+ pred. bounded_ty . kind
2196+ else {
2197+ continue ;
2198+ } ;
2199+ // Match the expected res.
2200+ if bounded_path. res != expected_res {
2201+ continue ;
2202+ }
2203+ yield pred. bounds ;
2204+ }
2205+ }
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+ }
2213+ }
2214+ } ,
2215+ )
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+ } )
2221+ . fuse ( )
2222+ }
21702223}
21712224
21722225/// Detects late-bound lifetimes and inserts them into
0 commit comments