@@ -909,20 +909,16 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
909909 // already resolved.
910910 self . visit_path ( path, id) ;
911911 if let Some ( qself) = maybe_qself {
912- // Read more about containers in fn `visit_path_segment_args`.
913- let container = match path. res {
914- Res :: Def ( DefKind :: AssocTy , def_id) => Some ( (
915- self . tcx . parent ( def_id) ,
916- & path. segments [ ..path. segments . len ( ) - 1 ] ,
917- ) ) ,
918- _ => None ,
919- } ;
912+ let container =
913+ self . eligible_container ( path, RevSegIdx ( 1 ) . reverse ( path. segments ) ) ;
914+
920915 let object_lifetime_defaults =
921916 container. map_or ( Vec :: new ( ) , |( def_id, segs) | {
922917 let generics = self . tcx . generics_of ( def_id) ;
923918 self . compute_object_lifetime_defaults ( generics, segs)
924919 } ) ;
925- if let Some ( & lt) = object_lifetime_defaults. get ( 0 ) {
920+
921+ if let Some ( & lt) = object_lifetime_defaults. first ( ) {
926922 let scope = Scope :: ObjectLifetimeDefault { lifetime : lt, s : self . scope } ;
927923 self . with ( scope, |this| this. visit_ty_unambig ( qself) ) ;
928924 } else {
@@ -952,7 +948,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
952948 fn visit_path ( & mut self , path : & hir:: Path < ' tcx > , hir_id : HirId ) {
953949 for ( index, segment) in path. segments . iter ( ) . enumerate ( ) {
954950 if let Some ( args) = segment. args {
955- self . visit_path_segment_args ( args, index, path) ;
951+ self . visit_path_segment_args ( args, SegIdx ( index) , path) ;
956952 }
957953 }
958954 if let Res :: Def ( DefKind :: TyParam | DefKind :: ConstParam , param_def_id) = path. res {
@@ -1723,7 +1719,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
17231719 fn visit_path_segment_args (
17241720 & mut self ,
17251721 generic_args : & ' tcx hir:: GenericArgs < ' tcx > ,
1726- index : usize ,
1722+ seg_idx : SegIdx ,
17271723 path : & hir:: Path < ' tcx > ,
17281724 ) {
17291725 if let Some ( ( inputs, output) ) = generic_args. paren_sugar_inputs_output ( ) {
@@ -1739,35 +1735,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
17391735 }
17401736 }
17411737
1742- // Figure out if this is an eligible container that induces lifetime defaults for
1743- // trait object types contained in any of the type arguments passed to it
1744- // (any inner containers will of course end up shadowing that default).
1745- //
1746- // FIXME(mgca, #151649): Assoc (and free?) consts should also qualify.
1747- // FIXME(return_type_notation, #151662): Assoc fns should also qualify.
1748- let depth = path. segments . len ( ) - index - 1 ;
1749- let container = match path. res {
1750- Res :: Def ( DefKind :: AssocTy | DefKind :: Variant , def_id) if depth == 1 => {
1751- Some ( ( self . tcx . parent ( def_id) , & path. segments [ ..=index] ) )
1752- }
1753- Res :: Def ( DefKind :: Variant , def_id) if depth == 0 => {
1754- Some ( ( self . tcx . parent ( def_id) , path. segments ) )
1755- }
1756- Res :: Def (
1757- DefKind :: Struct
1758- | DefKind :: Union
1759- | DefKind :: Enum
1760- | DefKind :: TyAlias
1761- | DefKind :: Trait
1762- | DefKind :: TraitAlias
1763- | DefKind :: AssocTy ,
1764- def_id,
1765- ) if depth == 0 => Some ( ( def_id, path. segments ) ) ,
1766- // Note: We don't need to care about definition kinds that may have generics if they
1767- // can only ever appear in positions where we can perform type inference (i.e., bodies).
1768- _ => None ,
1769- } ;
1770-
1738+ let container = self . eligible_container ( path, seg_idx) ;
17711739 debug ! ( ?container) ;
17721740
17731741 let ( has_self, object_lifetime_defaults) = container
@@ -1922,6 +1890,90 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
19221890 }
19231891 }
19241892
1893+ /// Return the eligible container for the path segment given by the index if applicable.
1894+ ///
1895+ /// Such a container induces lifetime defaults for trait object types contained
1896+ /// in any of the type arguments passed to it (any inner containers will of course
1897+ /// end up shadowing that default).
1898+ fn eligible_container < ' b > (
1899+ & self ,
1900+ path : & ' b hir:: Path < ' tcx > ,
1901+ seg_idx : SegIdx ,
1902+ ) -> Option < ( DefId , & ' b [ hir:: PathSegment < ' tcx > ] ) > {
1903+ let RevSegIdx ( rev_seg_idx) = seg_idx. reverse ( path. segments ) ;
1904+ let SegIdx ( seg_idx) = seg_idx;
1905+
1906+ // NOTE: We don't need to care about definition kinds that may have generics if they
1907+ // can only ever appear in positions where we can perform type inference (i.e., bodies).
1908+
1909+ // FIXME(mgca, #151649): Type-level free/assoc consts, const&fn ctors should also qualify.
1910+ // FIXME(return_type_notation, #151662): Assoc fns should also qualify.
1911+
1912+ let ( kind, def_id) = match path. res {
1913+ Res :: Def ( kind, def_id) => ( kind, def_id) ,
1914+ Res :: PrimTy ( ..)
1915+ | Res :: SelfTyParam { .. }
1916+ | Res :: SelfTyAlias { .. }
1917+ | Res :: SelfCtor ( _)
1918+ | Res :: Local ( _)
1919+ | Res :: ToolMod
1920+ | Res :: OpenMod ( _)
1921+ | Res :: NonMacroAttr ( _)
1922+ | Res :: Err => return None , // see NOTE above!
1923+ } ;
1924+
1925+ match kind {
1926+ DefKind :: AssocTy => match rev_seg_idx {
1927+ 0 => Some ( ( def_id, path. segments ) ) ,
1928+ // We're looking at the trait ref of an assoc type projection.
1929+ // E.g., the `TraitRef<…>` in `<… as path::to::TraitRef<…>>::AssocTy<…>`.
1930+ 1 => Some ( ( self . tcx . parent ( def_id) , & path. segments [ ..=seg_idx] ) ) ,
1931+ _ => None ,
1932+ } ,
1933+ DefKind :: Variant => match rev_seg_idx {
1934+ // We're looking at the `Variant::<…>` in `path::to::Variant::<…> { … }`.
1935+ // Even if it's the variant segment that has the generic args and not the
1936+ // enum segment, it's the enum that has the corresponding generic params.
1937+ 0 => Some ( ( self . tcx . parent ( def_id) , path. segments ) ) ,
1938+ // We're looking at the `Enum::<…>` in `path::to::Enum::<…>::Variant { … }`.
1939+ 1 => Some ( ( self . tcx . parent ( def_id) , & path. segments [ ..=seg_idx] ) ) ,
1940+ _ => None ,
1941+ } ,
1942+ DefKind :: Enum
1943+ | DefKind :: Struct
1944+ | DefKind :: Trait
1945+ | DefKind :: TraitAlias
1946+ | DefKind :: TyAlias
1947+ | DefKind :: Union => match rev_seg_idx {
1948+ 0 => Some ( ( def_id, path. segments ) ) ,
1949+ _ => None ,
1950+ } ,
1951+ DefKind :: AnonConst
1952+ | DefKind :: AssocConst { .. }
1953+ | DefKind :: AssocFn
1954+ | DefKind :: Closure
1955+ | DefKind :: Const { .. }
1956+ | DefKind :: ConstParam
1957+ | DefKind :: Ctor ( ..)
1958+ | DefKind :: ExternCrate
1959+ | DefKind :: Field
1960+ | DefKind :: Fn
1961+ | DefKind :: ForeignMod
1962+ | DefKind :: ForeignTy
1963+ | DefKind :: GlobalAsm
1964+ | DefKind :: Impl { .. }
1965+ | DefKind :: InlineConst
1966+ | DefKind :: LifetimeParam
1967+ | DefKind :: Macro ( _)
1968+ | DefKind :: Mod
1969+ | DefKind :: OpaqueTy
1970+ | DefKind :: Static { .. }
1971+ | DefKind :: SyntheticCoroutineBody
1972+ | DefKind :: TyParam
1973+ | DefKind :: Use => None , // see NOTE above!
1974+ }
1975+ }
1976+
19251977 /// Compute a list of trait object lifetime defaults, one for each type parameter,
19261978 /// per the rules initially given in RFCs [599] and [1156]. Example:
19271979 ///
@@ -1973,31 +2025,38 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
19732025 }
19742026 ObjectLifetimeDefault :: Static => Some ( ResolvedArg :: StaticLifetime ) ,
19752027 ObjectLifetimeDefault :: Param ( param_def_id) => {
1976- fn param_to_depth_and_index (
2028+ struct ArgIdx ( usize ) ;
2029+
2030+ fn resolve_param (
2031+ param_def_id : DefId ,
19772032 generics : & ty:: Generics ,
19782033 tcx : TyCtxt < ' _ > ,
1979- def_id : DefId ,
1980- ) -> ( usize , usize ) {
1981- if let Some ( & index) = generics. param_def_id_to_index . get ( & def_id) {
2034+ ) -> ( RevSegIdx , ArgIdx ) {
2035+ if let Some ( & index) = generics. param_def_id_to_index . get ( & param_def_id) {
19822036 let has_self = generics. has_own_self ( ) ;
1983- ( 0 , index as usize - generics. parent_count - has_self as usize )
2037+ let index = index as usize - generics. parent_count - has_self as usize ;
2038+ ( RevSegIdx ( 0 ) , ArgIdx ( index) )
19842039 } else if let Some ( parent) = generics. parent {
1985- let parent = tcx. generics_of ( parent) ;
1986- let ( depth, index) = param_to_depth_and_index ( parent, tcx, def_id) ;
1987- ( depth + 1 , index)
2040+ let parent_generics = tcx. generics_of ( parent) ;
2041+ let ( RevSegIdx ( rev_seg_idx) , arg_idx) =
2042+ resolve_param ( param_def_id, parent_generics, tcx) ;
2043+ ( RevSegIdx ( rev_seg_idx + 1 ) , arg_idx)
19882044 } else {
19892045 unreachable ! ( )
19902046 }
19912047 }
19922048
1993- let ( depth, index) = param_to_depth_and_index ( generics, self . tcx , param_def_id) ;
1994- segments[ segments. len ( ) - depth - 1 ]
1995- . args
1996- . and_then ( |args| args. args . get ( index) )
1997- . and_then ( |arg| match arg {
2049+ let ( rev_seg_idx, ArgIdx ( arg_idx) ) =
2050+ resolve_param ( param_def_id, generics, self . tcx ) ;
2051+
2052+ let SegIdx ( seg_idx) = rev_seg_idx. reverse ( segments) ;
2053+
2054+ segments[ seg_idx] . args . and_then ( |args| args. args . get ( arg_idx) ) . and_then ( |arg| {
2055+ match arg {
19982056 GenericArg :: Lifetime ( lt) => self . rbv . defs . get ( & lt. hir_id . local_id ) . copied ( ) ,
19992057 _ => None ,
2000- } )
2058+ }
2059+ } )
20012060 }
20022061 ObjectLifetimeDefault :: Ambiguous => None ,
20032062 } ;
@@ -2673,3 +2732,27 @@ fn deny_non_region_late_bound(
26732732 * arg = ResolvedArg :: Error ( guar) ;
26742733 }
26752734}
2735+
2736+ /// A path segment index.
2737+ #[ derive( Clone , Copy , Debug ) ]
2738+ struct SegIdx ( usize ) ;
2739+
2740+ impl SegIdx {
2741+ fn reverse ( self , segments : & [ hir:: PathSegment < ' _ > ] ) -> RevSegIdx {
2742+ let SegIdx ( seg_idx) = self ;
2743+ RevSegIdx ( segments. len ( ) - seg_idx - 1 )
2744+ }
2745+ }
2746+
2747+ /// A reversed path segment index.
2748+ ///
2749+ /// E.g., for qualified path `<() as path::to::TraitRef<…>>::AssocTy<…>` the mapping from reversed
2750+ /// index to path segment would look like 3 ↦ `path`, 2 ↦ `to`, 1 ↦ `TraitRef<…>`, 0 ↦ `AssocTy<…>`.
2751+ struct RevSegIdx ( usize ) ;
2752+
2753+ impl RevSegIdx {
2754+ fn reverse ( self , segments : & [ hir:: PathSegment < ' _ > ] ) -> SegIdx {
2755+ let RevSegIdx ( rev_seg_idx) = self ;
2756+ SegIdx ( segments. len ( ) - rev_seg_idx - 1 )
2757+ }
2758+ }
0 commit comments