@@ -900,6 +900,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
900900                            self . tcx . parent ( def_id) , 
901901                            & path. segments [ ..path. segments . len ( )  - 1 ] , 
902902                        ) ) , 
903+                         // FIXME(mgca): @fmease thinks we also need to handle AssocConsts here. 
903904                        _ => None , 
904905                    } ; 
905906                    let  object_lifetime_defaults =
@@ -914,17 +915,27 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
914915                    } 
915916                } 
916917            } 
917-             hir:: QPath :: TypeRelative ( qself,  segment)  => { 
918-                 // Resolving object lifetime defaults for type-relative paths requires full 
919-                 // type-dependent resolution as performed by HIR ty lowering whose results 
920-                 // we don't have access to (and we'd results for both FnCtxts and ItemCtxts). 
921-                 // FIXME: Figure out if there's a feasible way to obtain the map of 
922-                 //        type-dependent definitions. 
918+             & hir:: QPath :: TypeRelative ( qself,  segment)  => { 
919+                 if  let  Some ( args)  = segment. args  { 
920+                     // FIXME(mgca): @fmease thinks we also need to handle AssocConsts here. 
921+                     let  container = self 
922+                         . limited_resolve_type_relative_path ( 
923+                             ty:: AssocTag :: Type , 
924+                             qself, 
925+                             segment, 
926+                             true , 
927+                         ) 
928+                         . map ( |( _,  assoc_item) | ( assoc_item. def_id ,  std:: slice:: from_ref ( segment) ) ) ; 
929+                     self . visit_segment_args ( container,  args) ; 
930+                 } 
931+ 
932+                 // For forward compatibility we reject elided object lifetimes in the self type as 
933+                 // "indeterminate" by passing `None`. `limited_resolve_type_relative_path` is not 
934+                 // complete compared to HIR ty lowering's `lower_assoc_path_shared`, so we need to 
935+                 // be conservative. Consider paths like `<dyn Trait>::X` which may resolve in the 
936+                 // future (under IATs or mGCA (IACs)). 
923937                let  scope = Scope :: ObjectLifetimeDefault  {  lifetime :  None ,  s :  self . scope  } ; 
924-                 self . with ( scope,  |this| { 
925-                     this. visit_ty_unambig ( qself) ; 
926-                     this. visit_path_segment ( segment) 
927-                 } ) ; 
938+                 self . with ( scope,  |this| this. visit_ty_unambig ( qself) ) ; 
928939            } 
929940            hir:: QPath :: LangItem ( ..)  => { } 
930941        } 
@@ -933,7 +944,38 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
933944    fn  visit_path ( & mut  self ,  path :  & hir:: Path < ' tcx > ,  hir_id :  HirId )  { 
934945        for  ( index,  segment)  in  path. segments . iter ( ) . enumerate ( )  { 
935946            if  let  Some ( args)  = segment. args  { 
936-                 self . visit_segment_args ( path,  index,  args) ; 
947+                 // Figure out if this is an "eligible generic container" that brings along ambient object 
948+                 // lifetime defaults for trait object types contained in any of the type arguments passed to 
949+                 // it (any inner generic containers will of course end up shadowing that the default). 
950+                 let  depth = path. segments . len ( )  - index - 1 ; 
951+                 let  container = match  ( path. res ,  depth)  { 
952+                     ( Res :: Def ( DefKind :: AssocTy ,  def_id) ,  1 )  => { 
953+                         Some ( ( self . tcx . parent ( def_id) ,  & path. segments [ ..=index] ) ) 
954+                     } 
955+                     ( Res :: Def ( DefKind :: Variant ,  def_id) ,  0 )  => { 
956+                         Some ( ( self . tcx . parent ( def_id) ,  path. segments ) ) 
957+                     } 
958+                     // FIXME(trait_alias): Arguably, trait aliases are eligible generic containers. 
959+                     ( 
960+                         Res :: Def ( 
961+                             DefKind :: Struct 
962+                             | DefKind :: Union 
963+                             | DefKind :: Enum 
964+                             | DefKind :: TyAlias 
965+                             | DefKind :: Trait 
966+                             | DefKind :: AssocTy , 
967+                             def_id, 
968+                         ) , 
969+                         0 , 
970+                     )  => Some ( ( def_id,  path. segments ) ) , 
971+                     // Note: We don't need to care about definitions kinds that can have generics if they 
972+                     // can only ever appear in positions where we can perform type inference (i.e., bodies). 
973+                     // FIXME(mgca): @fmease thinks that under (m)GCA we now also need to care about e.g., 
974+                     //              type-level Consts (GCI) and AssocConsts (maybe also Fns, AssocFns) here 
975+                     //              since they appear outside of bodies (once the feature is more complete). 
976+                     _ => None , 
977+                 } ; 
978+                 self . visit_segment_args ( container,  args) ; 
937979            } 
938980        } 
939981        if  let  Res :: Def ( DefKind :: TyParam  | DefKind :: ConstParam ,  param_def_id)  = path. res  { 
@@ -1653,8 +1695,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
16531695    #[ instrument( level = "debug" ,  skip( self ) ) ]  
16541696    fn  visit_segment_args ( 
16551697        & mut  self , 
1656-         path :  & hir:: Path < ' tcx > , 
1657-         index :  usize , 
1698+         container :  Option < ( DefId ,  & [ hir:: PathSegment < ' tcx > ] ) > , 
16581699        generic_args :  & ' tcx  hir:: GenericArgs < ' tcx > , 
16591700    )  { 
16601701        if  let  Some ( ( inputs,  output) )  = generic_args. paren_sugar_inputs_output ( )  { 
@@ -1670,40 +1711,6 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
16701711            } 
16711712        } 
16721713
1673-         // Figure out if this is an "eligible generic container" that brings along ambient object 
1674-         // lifetime defaults for trait object types contained in any of the type arguments passed to 
1675-         // it (any inner generic containers will of course end up shadowing that the default). 
1676-         let  depth = path. segments . len ( )  - index - 1 ; 
1677-         let  container = match  ( path. res ,  depth)  { 
1678-             ( Res :: Def ( DefKind :: AssocTy ,  def_id) ,  1 )  => { 
1679-                 Some ( ( self . tcx . parent ( def_id) ,  & path. segments [ ..=index] ) ) 
1680-             } 
1681-             ( Res :: Def ( DefKind :: Variant ,  def_id) ,  0 )  => { 
1682-                 Some ( ( self . tcx . parent ( def_id) ,  path. segments ) ) 
1683-             } 
1684-             // FIXME(trait_alias): Arguably, trait aliases are eligible generic containers. 
1685-             ( 
1686-                 Res :: Def ( 
1687-                     DefKind :: Struct 
1688-                     | DefKind :: Union 
1689-                     | DefKind :: Enum 
1690-                     | DefKind :: TyAlias 
1691-                     | DefKind :: Trait 
1692-                     | DefKind :: AssocTy , 
1693-                     def_id, 
1694-                 ) , 
1695-                 0 , 
1696-             )  => Some ( ( def_id,  path. segments ) ) , 
1697-             // Note: We don't need to care about definitions kinds that can have generics if they 
1698-             // can only ever appear in positions where we can perform type inference (i.e., bodies). 
1699-             // FIXME(mgca): @fmease thinks that under (m)GCA we now also need to care about e.g., 
1700-             //              type-level Consts (GCI) and AssocConsts (maybe also Fns, AssocFns) here 
1701-             //              since they appear outside of bodies (once the feature is more complete). 
1702-             _ => None , 
1703-         } ; 
1704- 
1705-         debug ! ( ?container) ; 
1706- 
17071714        let  object_lifetime_defaults = container. map_or_else ( Vec :: new,  |( def_id,  segs) | { 
17081715            self . compute_ambient_object_lifetime_defaults ( def_id,  segs) 
17091716        } ) ; 
@@ -2149,72 +2156,15 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
21492156                    matches ! ( args. parenthesized,  hir:: GenericArgsParentheses :: ReturnTypeNotation ) 
21502157                } )  =>
21512158            { 
2152-                 // First, ignore a qself that isn't a type or `Self` param. Those are the 
2153-                 // only ones that support `T::Assoc` anyways in HIR lowering. 
2154-                 let  hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None ,  path) )  = qself. kind  else  { 
2159+                 let  Some ( ( bound_vars,  assoc_item) )  = self . limited_resolve_type_relative_path ( 
2160+                     ty:: AssocTag :: Fn , 
2161+                     qself, 
2162+                     item_segment, 
2163+                     false , 
2164+                 )  else  { 
21552165                    return ; 
21562166                } ; 
2157-                 match  path. res  { 
2158-                     Res :: Def ( DefKind :: TyParam ,  _)  | Res :: SelfTyParam  {  trait_ :  _ }  => { 
2159-                         let  mut  bounds =
2160-                             self . for_each_trait_bound_on_res ( path. res ) . filter_map ( |trait_def_id| { 
2161-                                 BoundVarContext :: supertrait_hrtb_vars ( 
2162-                                     self . tcx , 
2163-                                     trait_def_id, 
2164-                                     item_segment. ident , 
2165-                                     ty:: AssocTag :: Fn , 
2166-                                 ) 
2167-                             } ) ; 
2168- 
2169-                         let  Some ( ( bound_vars,  assoc_item) )  = bounds. next ( )  else  { 
2170-                             // This will error in HIR lowering. 
2171-                             self . tcx 
2172-                                 . dcx ( ) 
2173-                                 . span_delayed_bug ( path. span ,  "no resolution for RTN path" ) ; 
2174-                             return ; 
2175-                         } ; 
2176- 
2177-                         // Don't bail if we have identical bounds, which may be collected from 
2178-                         // something like `T: Bound + Bound`, or via elaborating supertraits. 
2179-                         for  ( second_vars,  second_assoc_item)  in  bounds { 
2180-                             if  second_vars != bound_vars || second_assoc_item != assoc_item { 
2181-                                 // This will error in HIR lowering. 
2182-                                 self . tcx . dcx ( ) . span_delayed_bug ( 
2183-                                     path. span , 
2184-                                     "ambiguous resolution for RTN path" , 
2185-                                 ) ; 
2186-                                 return ; 
2187-                             } 
2188-                         } 
2189- 
2190-                         ( bound_vars,  assoc_item. def_id ,  item_segment) 
2191-                     } 
2192-                     // If we have a self type alias (in an impl), try to resolve an 
2193-                     // associated item from one of the supertraits of the impl's trait. 
2194-                     Res :: SelfTyAlias  {  alias_to :  impl_def_id,  is_trait_impl :  true ,  .. }  => { 
2195-                         let  hir:: ItemKind :: Impl ( hir:: Impl  {  of_trait :  Some ( trait_ref) ,  .. } )  = self 
2196-                             . tcx 
2197-                             . hir_node_by_def_id ( impl_def_id. expect_local ( ) ) 
2198-                             . expect_item ( ) 
2199-                             . kind 
2200-                         else  { 
2201-                             return ; 
2202-                         } ; 
2203-                         let  Some ( trait_def_id)  = trait_ref. trait_def_id ( )  else  { 
2204-                             return ; 
2205-                         } ; 
2206-                         let  Some ( ( bound_vars,  assoc_item) )  = BoundVarContext :: supertrait_hrtb_vars ( 
2207-                             self . tcx , 
2208-                             trait_def_id, 
2209-                             item_segment. ident , 
2210-                             ty:: AssocTag :: Fn , 
2211-                         )  else  { 
2212-                             return ; 
2213-                         } ; 
2214-                         ( bound_vars,  assoc_item. def_id ,  item_segment) 
2215-                     } 
2216-                     _ => return , 
2217-                 } 
2167+                 ( bound_vars,  assoc_item. def_id ,  item_segment) 
22182168            } 
22192169
22202170            _ => return , 
@@ -2253,6 +2203,83 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
22532203        self . record_late_bound_vars ( item_segment. hir_id ,  existing_bound_vars_saved) ; 
22542204    } 
22552205
2206+     /// In a limited fashion, try to resolve the given type-relative path of the given kind. 
2207+ fn  limited_resolve_type_relative_path ( 
2208+         & self , 
2209+         tag :  ty:: AssocTag , 
2210+         qself :  & ' tcx  hir:: Ty < ' tcx > , 
2211+         segment :  & ' tcx  hir:: PathSegment < ' tcx > , 
2212+         speculative :  bool , 
2213+     )  -> Option < ( Vec < ty:: BoundVariableKind > ,  & ' tcx  ty:: AssocItem ) >  { 
2214+         // This mimics HIR ty lowering's `lower_assoc_path_shared`. 
2215+         // FIXME: Duplicating efforts is not robust or sustainable/maintainable. 
2216+         // Ideally, we'd simply obtain the resulting type-dependent defs from 
2217+         // HIR ty lowering (not only in FnCtxts but also in ItemCtxts!). 
2218+ 
2219+         // First, ignore a qself that isn't a type or `Self` param. Those are the only ones 
2220+         // that support `T::Assoc` anyways in HIR ty lowering at the time of writing. 
2221+         let  hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None ,  path) )  = qself. kind  else  { 
2222+             return  None ; 
2223+         } ; 
2224+ 
2225+         match  path. res  { 
2226+             Res :: Def ( DefKind :: TyParam ,  _)  | Res :: SelfTyParam  {  trait_ :  _ }  => { 
2227+                 let  mut  bounds =
2228+                     self . for_each_trait_bound_on_res ( path. res ) . filter_map ( |trait_def_id| { 
2229+                         BoundVarContext :: supertrait_hrtb_vars ( 
2230+                             self . tcx , 
2231+                             trait_def_id, 
2232+                             segment. ident , 
2233+                             tag, 
2234+                         ) 
2235+                     } ) ; 
2236+ 
2237+                 let  Some ( ( bound_vars,  assoc_item) )  = bounds. next ( )  else  { 
2238+                     if  !speculative { 
2239+                         // This will error in HIR ty lowering. 
2240+                         self . tcx 
2241+                             . dcx ( ) 
2242+                             . span_delayed_bug ( path. span ,  "no resolution for type-relative path" ) ; 
2243+                     } 
2244+                     return  None ; 
2245+                 } ; 
2246+ 
2247+                 // Don't bail if we have identical bounds, which may be collected from 
2248+                 // something like `T: Bound + Bound`, or via elaborating supertraits. 
2249+                 for  ( second_vars,  second_assoc_item)  in  bounds { 
2250+                     if  second_vars != bound_vars || second_assoc_item != assoc_item { 
2251+                         if  !speculative { 
2252+                             // This will error in HIR ty lowering. 
2253+                             self . tcx . dcx ( ) . span_delayed_bug ( 
2254+                                 path. span , 
2255+                                 "ambiguous resolution for type-relative path" , 
2256+                             ) ; 
2257+                         } 
2258+                         return  None ; 
2259+                     } 
2260+                 } 
2261+ 
2262+                 Some ( ( bound_vars,  assoc_item) ) 
2263+             } 
2264+             // If we have a self type alias (in an impl), try to resolve an 
2265+             // associated item from one of the supertraits of the impl's trait. 
2266+             Res :: SelfTyAlias  {  alias_to :  impl_def_id,  is_trait_impl :  true ,  .. }  => { 
2267+                 let  hir:: ItemKind :: Impl ( hir:: Impl  {  of_trait :  Some ( trait_ref) ,  .. } )  =
2268+                     self . tcx . hir_node_by_def_id ( impl_def_id. expect_local ( ) ) . expect_item ( ) . kind 
2269+                 else  { 
2270+                     return  None ; 
2271+                 } ; 
2272+                 BoundVarContext :: supertrait_hrtb_vars ( 
2273+                     self . tcx , 
2274+                     trait_ref. trait_def_id ( ) ?, 
2275+                     segment. ident , 
2276+                     tag, 
2277+                 ) 
2278+             } 
2279+             _ => None , 
2280+         } 
2281+     } 
2282+ 
22562283    /// Walk the generics of the item for a trait bound whose self type 
22572284/// corresponds to the expected res, and return the trait def id. 
22582285fn  for_each_trait_bound_on_res ( & self ,  expected_res :  Res )  -> impl  Iterator < Item  = DefId >  { 
0 commit comments