@@ -1891,45 +1891,30 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
18911891 } ;
18921892 match path. res {
18931893 Res :: Def ( DefKind :: TyParam , _) | Res :: SelfTyParam { trait_ : _ } => {
1894- // Get the generics of this type's hir owner. This is *different*
1895- // from the generics of the parameter's definition, since we want
1896- // to be able to resolve an RTN path on a nested body (e.g. method
1897- // inside an impl) using the where clauses on the method.
1898- // FIXME(return_type_notation): Think of some better way of doing this.
1899- let Some ( generics) = self . tcx . hir_owner_node ( hir_id. owner ) . generics ( )
1900- else {
1901- return ;
1902- } ;
1903-
1904- // Look for the first bound that contains an associated type that
1905- // matches the segment that we're looking for. We ignore any subsequent
1906- // bounds since we'll be emitting a hard error in HIR lowering, so this
1907- // is purely speculative.
1908- let one_bound = generics. predicates . iter ( ) . find_map ( |predicate| {
1909- let hir:: WherePredicate :: BoundPredicate ( predicate) = predicate else {
1910- return None ;
1911- } ;
1912- let hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None , bounded_path) ) =
1913- predicate. bounded_ty . kind
1914- else {
1915- return None ;
1916- } ;
1917- if bounded_path. res != path. res {
1918- return None ;
1919- }
1920- predicate. bounds . iter ( ) . find_map ( |bound| {
1921- let hir:: GenericBound :: Trait ( trait_) = bound else {
1922- return None ;
1923- } ;
1894+ let mut bounds =
1895+ self . for_each_in_scope_predicate ( path. res ) . filter_map ( |trait_| {
19241896 BoundVarContext :: supertrait_hrtb_vars (
19251897 self . tcx ,
19261898 trait_. trait_ref . trait_def_id ( ) ?,
19271899 item_segment. ident ,
19281900 ty:: AssocKind :: Fn ,
19291901 )
1930- } )
1931- } ) ;
1902+ } ) ;
1903+
1904+ let one_bound = bounds. next ( ) ;
1905+ let second_bound = bounds. next ( ) ;
1906+
1907+ if second_bound. is_some ( ) {
1908+ self . tcx
1909+ . dcx ( )
1910+ . span_delayed_bug ( path. span , "ambiguous resolution for RTN path" ) ;
1911+ return ;
1912+ }
1913+
19321914 let Some ( ( bound_vars, assoc_item) ) = one_bound else {
1915+ self . tcx
1916+ . dcx ( )
1917+ . span_delayed_bug ( path. span , "no resolution for RTN path" ) ;
19331918 return ;
19341919 } ;
19351920 ( bound_vars, assoc_item. def_id , item_segment)
@@ -2001,6 +1986,75 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
20011986 existing_bound_vars. extend ( bound_vars) ;
20021987 self . record_late_bound_vars ( item_segment. hir_id , existing_bound_vars_saved) ;
20031988 }
1989+
1990+ /// Walk the generics of the item for a trait-ref whose self type
1991+ /// corresponds to the expected res.
1992+ fn for_each_in_scope_predicate (
1993+ & self ,
1994+ expected_res : Res ,
1995+ ) -> impl Iterator < Item = & ' tcx hir:: PolyTraitRef < ' tcx > > + use < ' tcx , ' _ > {
1996+ std:: iter:: from_coroutine (
1997+ #[ coroutine]
1998+ move || {
1999+ let mut next_scope = Some ( self . scope ) ;
2000+ while let Some ( current_scope) = next_scope {
2001+ next_scope = None ;
2002+ let hir_id = match * current_scope {
2003+ Scope :: Binder { s, hir_id, .. } => {
2004+ next_scope = Some ( s) ;
2005+ hir_id
2006+ }
2007+ Scope :: Body { s, .. }
2008+ | Scope :: ObjectLifetimeDefault { s, .. }
2009+ | Scope :: Supertrait { s, .. }
2010+ | Scope :: TraitRefBoundary { s }
2011+ | Scope :: LateBoundary { s, .. } => {
2012+ next_scope = Some ( s) ;
2013+ continue ;
2014+ }
2015+ Scope :: Root { opt_parent_item } => {
2016+ if let Some ( parent_id) = opt_parent_item {
2017+ self . tcx . local_def_id_to_hir_id ( parent_id)
2018+ } else {
2019+ continue ;
2020+ }
2021+ }
2022+ } ;
2023+ let node = self . tcx . hir_node ( hir_id) ;
2024+ if let Some ( generics) = node. generics ( ) {
2025+ for pred in generics. predicates {
2026+ let hir:: WherePredicate :: BoundPredicate ( pred) = pred else {
2027+ continue ;
2028+ } ;
2029+ let hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None , bounded_path) ) =
2030+ pred. bounded_ty . kind
2031+ else {
2032+ continue ;
2033+ } ;
2034+ // Match the expected res.
2035+ if bounded_path. res != expected_res {
2036+ continue ;
2037+ }
2038+ yield pred. bounds ;
2039+ }
2040+ }
2041+ // Also consider supertraits for `Self` res...
2042+ if let Res :: SelfTyParam { trait_ : _ } = expected_res
2043+ && let hir:: Node :: Item ( item) = node
2044+ && let hir:: ItemKind :: Trait ( _, _, _, supertraits, _) = item. kind
2045+ {
2046+ yield supertraits;
2047+ }
2048+ }
2049+ } ,
2050+ )
2051+ . flatten ( )
2052+ . filter_map ( |pred| match pred {
2053+ hir:: GenericBound :: Trait ( poly_trait_ref) => Some ( poly_trait_ref) ,
2054+ hir:: GenericBound :: Outlives ( _) | hir:: GenericBound :: Use ( _, _) => None ,
2055+ } )
2056+ . fuse ( )
2057+ }
20042058}
20052059
20062060/// Detects late-bound lifetimes and inserts them into
0 commit comments