@@ -1891,45 +1891,30 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
1891
1891
} ;
1892
1892
match path. res {
1893
1893
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_| {
1924
1896
BoundVarContext :: supertrait_hrtb_vars (
1925
1897
self . tcx ,
1926
1898
trait_. trait_ref . trait_def_id ( ) ?,
1927
1899
item_segment. ident ,
1928
1900
ty:: AssocKind :: Fn ,
1929
1901
)
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
+
1932
1914
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" ) ;
1933
1918
return ;
1934
1919
} ;
1935
1920
( bound_vars, assoc_item. def_id , item_segment)
@@ -2001,6 +1986,75 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
2001
1986
existing_bound_vars. extend ( bound_vars) ;
2002
1987
self . record_late_bound_vars ( item_segment. hir_id , existing_bound_vars_saved) ;
2003
1988
}
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
+ }
2004
2058
}
2005
2059
2006
2060
/// Detects late-bound lifetimes and inserts them into
0 commit comments