@@ -777,7 +777,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
777777 // use the object lifetime defaulting
778778 // rules. So e.g., `Box<dyn Debug>` becomes
779779 // `Box<dyn Debug + 'static>`.
780- self . resolve_object_lifetime_default ( & * lifetime)
780+ self . resolve_object_lifetime_default ( & * lifetime) ;
781781 }
782782 LifetimeKind :: Infer => {
783783 // If the user writes `'_`, we use the *ordinary* elision
@@ -796,7 +796,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
796796 hir:: TyKind :: Ref ( lifetime_ref, ref mt) => {
797797 self . visit_lifetime ( lifetime_ref) ;
798798 let scope = Scope :: ObjectLifetimeDefault {
799- lifetime : self . rbv . defs . get ( & lifetime_ref. hir_id . local_id ) . cloned ( ) ,
799+ lifetime : self . rbv . defs . get ( & lifetime_ref. hir_id . local_id ) . copied ( ) ,
800800 s : self . scope ,
801801 } ;
802802 self . with ( scope, |this| this. visit_ty_unambig ( mt. ty ) ) ;
@@ -884,11 +884,35 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
884884 }
885885 }
886886
887+ fn visit_qpath ( & mut self , qpath : & ' tcx hir:: QPath < ' tcx > , id : HirId , _: Span ) {
888+ match qpath {
889+ hir:: QPath :: Resolved ( maybe_qself, path) => {
890+ if let Some ( qself) = maybe_qself {
891+ // FIXME: Actually determine the ambient object lifetime defaults for the self ty!
892+ let scope = Scope :: ObjectLifetimeDefault { lifetime : None , s : self . scope } ;
893+ self . with ( scope, |this| this. visit_ty_unambig ( qself) ) ;
894+ }
895+ self . visit_path ( path, id) ;
896+ }
897+ hir:: QPath :: TypeRelative ( qself, segment) => {
898+ // Resolving object lifetime defaults for type-relative paths requires full
899+ // type-dependent resolution as performed by HIR ty lowering whose results
900+ // we don't have access to (and we'd results for both FnCtxts and ItemCtxts).
901+ // FIXME: Figure out if there's a feasible way to obtain the map of
902+ // type-dependent definitions.
903+ let scope = Scope :: ObjectLifetimeDefault { lifetime : None , s : self . scope } ;
904+ self . with ( scope, |this| {
905+ this. visit_ty_unambig ( qself) ;
906+ this. visit_path_segment ( segment)
907+ } ) ;
908+ }
909+ }
910+ }
911+
887912 fn visit_path ( & mut self , path : & hir:: Path < ' tcx > , hir_id : HirId ) {
888- for ( i, segment) in path. segments . iter ( ) . enumerate ( ) {
889- let depth = path. segments . len ( ) - i - 1 ;
913+ for ( index, segment) in path. segments . iter ( ) . enumerate ( ) {
890914 if let Some ( args) = segment. args {
891- self . visit_segment_args ( path. res , depth , args) ;
915+ self . visit_segment_args ( path, index , args) ;
892916 }
893917 }
894918 if let Res :: Def ( DefKind :: TyParam | DefKind :: ConstParam , param_def_id) = path. res {
@@ -1617,55 +1641,72 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
16171641 #[ instrument( level = "debug" , skip( self ) ) ]
16181642 fn visit_segment_args (
16191643 & mut self ,
1620- res : Res ,
1621- depth : usize ,
1644+ path : & hir :: Path < ' tcx > ,
1645+ index : usize ,
16221646 generic_args : & ' tcx hir:: GenericArgs < ' tcx > ,
16231647 ) {
16241648 if let Some ( ( inputs, output) ) = generic_args. paren_sugar_inputs_output ( ) {
16251649 self . visit_fn_like_elision ( inputs, Some ( output) , false ) ;
16261650 return ;
16271651 }
16281652
1653+ // Let's first resolve all lifetime arguments because we need their resolution
1654+ // for computing the ambient object lifetime defaults.
16291655 for arg in generic_args. args {
16301656 if let hir:: GenericArg :: Lifetime ( lt) = arg {
16311657 self . visit_lifetime ( lt) ;
16321658 }
16331659 }
16341660
1635- // Figure out if this is a type/trait segment,
1636- // which requires object lifetime defaults.
1637- let type_def_id = match res {
1638- Res :: Def ( DefKind :: AssocTy , def_id) if depth == 1 => Some ( self . tcx . parent ( def_id) ) ,
1639- Res :: Def ( DefKind :: Variant , def_id) if depth == 0 => Some ( self . tcx . parent ( def_id) ) ,
1640- Res :: Def (
1641- DefKind :: Struct
1642- | DefKind :: Union
1643- | DefKind :: Enum
1644- | DefKind :: TyAlias
1645- | DefKind :: Trait ,
1646- def_id,
1647- ) if depth == 0 => Some ( def_id) ,
1661+ // Figure out if this is an "eligible generic container" that brings along ambient object
1662+ // lifetime defaults for trait object types contained in any of the type arguments passed to
1663+ // it (any inner generic containers will of course end up shadowing that the default).
1664+ let depth = path. segments . len ( ) - index - 1 ;
1665+ let container = match ( path. res , depth) {
1666+ ( Res :: Def ( DefKind :: AssocTy , def_id) , 1 ) => {
1667+ Some ( ( self . tcx . parent ( def_id) , & path. segments [ ..=index] ) )
1668+ }
1669+ ( Res :: Def ( DefKind :: Variant , def_id) , 0 ) => {
1670+ Some ( ( self . tcx . parent ( def_id) , path. segments ) )
1671+ }
1672+ // FIXME(trait_alias): Arguably, trait aliases are eligible generic containers.
1673+ (
1674+ Res :: Def (
1675+ DefKind :: Struct
1676+ | DefKind :: Union
1677+ | DefKind :: Enum
1678+ | DefKind :: TyAlias
1679+ | DefKind :: Trait
1680+ | DefKind :: AssocTy ,
1681+ def_id,
1682+ ) ,
1683+ 0 ,
1684+ ) => Some ( ( def_id, path. segments ) ) ,
1685+ // Note: We don't need to care about definition kinds that may have generics if they
1686+ // can only ever appear in positions where we can perform type inference (i.e., bodies).
1687+ // FIXME(mgca): @fmease thinks that under (m)GCA we now also need to care about e.g.,
1688+ // type-level Consts (GCI) and AssocConsts (maybe also Fns, AssocFns) here
1689+ // since they appear outside of bodies (once the feature is more complete).
16481690 _ => None ,
16491691 } ;
16501692
1651- debug ! ( ?type_def_id ) ;
1693+ debug ! ( ?container ) ;
16521694
1653- // Compute a vector of defaults, one for each type parameter,
1654- // per the rules given in RFCs 599 and 1156. Example:
1695+ // Compute a vector of ambient object lifetime defaults, one for each type parameter,
1696+ // per the rules initially given in RFCs 599 and 1156. Example:
16551697 //
16561698 // ```rust
1657- // struct Foo<'a, T: 'a, U> { }
1699+ // struct Foo<'a, T: 'a + ?Sized , U: ?Sized>(&'a T, &'a U);
16581700 // ```
16591701 //
16601702 // If you have `Foo<'x, dyn Bar, dyn Baz>`, we want to default
16611703 // `dyn Bar` to `dyn Bar + 'x` (because of the `T: 'a` bound)
16621704 // and `dyn Baz` to `dyn Baz + 'static` (because there is no
16631705 // such bound).
16641706 //
1665- // Therefore, we would compute `object_lifetime_defaults` to a
1666- // vector like `['x, 'static]`. Note that the vector only
1667- // includes type parameters.
1668- let object_lifetime_defaults = type_def_id. map_or_else ( Vec :: new, |def_id| {
1707+ // Therefore, we would compute a vector like `['x, 'static]`.
1708+ // Note that the vector only includes type parameters.
1709+ let object_lifetime_defaults = container. map_or_else ( Vec :: new, |( def_id, segments) | {
16691710 let in_body = {
16701711 let mut scope = self . scope ;
16711712 loop {
@@ -1689,9 +1730,6 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
16891730 let rbv = & self . rbv ;
16901731 let generics = self . tcx . generics_of ( def_id) ;
16911732
1692- // `type_def_id` points to an item, so there is nothing to inherit generics from.
1693- debug_assert_eq ! ( generics. parent_count, 0 ) ;
1694-
16951733 let set_to_region = |set : ObjectLifetimeDefault | match set {
16961734 ObjectLifetimeDefault :: Empty => {
16971735 if in_body {
@@ -1702,12 +1740,31 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
17021740 }
17031741 ObjectLifetimeDefault :: Static => Some ( ResolvedArg :: StaticLifetime ) ,
17041742 ObjectLifetimeDefault :: Param ( param_def_id) => {
1705- // This index can be used with `generic_args` since `parent_count == 0`.
1706- let index = generics. param_def_id_to_index [ & param_def_id] as usize ;
1707- generic_args. args . get ( index) . and_then ( |arg| match arg {
1708- GenericArg :: Lifetime ( lt) => rbv. defs . get ( & lt. hir_id . local_id ) . copied ( ) ,
1709- _ => None ,
1710- } )
1743+ fn param_to_depth_and_index (
1744+ generics : & ty:: Generics ,
1745+ tcx : TyCtxt < ' _ > ,
1746+ def_id : DefId ,
1747+ ) -> ( usize , usize ) {
1748+ if let Some ( & index) = generics. param_def_id_to_index . get ( & def_id) {
1749+ let has_self = generics. parent . is_none ( ) && generics. has_self ;
1750+ ( 0 , index as usize - generics. parent_count - has_self as usize )
1751+ } else if let Some ( parent) = generics. parent {
1752+ let parent = tcx. generics_of ( parent) ;
1753+ let ( depth, index) = param_to_depth_and_index ( parent, tcx, def_id) ;
1754+ ( depth + 1 , index)
1755+ } else {
1756+ unreachable ! ( )
1757+ }
1758+ }
1759+
1760+ let ( depth, index) = param_to_depth_and_index ( generics, self . tcx , param_def_id) ;
1761+ segments[ segments. len ( ) - depth - 1 ]
1762+ . args
1763+ . and_then ( |args| args. args . get ( index) )
1764+ . and_then ( |arg| match arg {
1765+ GenericArg :: Lifetime ( lt) => rbv. defs . get ( & lt. hir_id . local_id ) . copied ( ) ,
1766+ _ => None ,
1767+ } )
17111768 }
17121769 ObjectLifetimeDefault :: Ambiguous => None ,
17131770 } ;
@@ -1737,6 +1794,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
17371794 let mut i = 0 ;
17381795 for arg in generic_args. args {
17391796 match arg {
1797+ // We've already visited all lifetime arguments at the start.
17401798 GenericArg :: Lifetime ( _) => { }
17411799 GenericArg :: Type ( ty) => {
17421800 if let Some ( & lt) = object_lifetime_defaults. get ( i) {
@@ -1811,11 +1869,11 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
18111869 // `for<'a> for<'r> <T as Trait<'a>>::x::<'r, T>::{opaque#0}: for<'b> Other<'b>`.
18121870 if constraint. gen_args . parenthesized == hir:: GenericArgsParentheses :: ReturnTypeNotation
18131871 {
1814- let bound_vars = if let Some ( type_def_id ) = type_def_id
1815- && self . tcx . def_kind ( type_def_id ) == DefKind :: Trait
1872+ let bound_vars = if let Some ( ( container_def_id , _ ) ) = container
1873+ && self . tcx . def_kind ( container_def_id ) == DefKind :: Trait
18161874 && let Some ( ( mut bound_vars, assoc_fn) ) = BoundVarContext :: supertrait_hrtb_vars (
18171875 self . tcx ,
1818- type_def_id ,
1876+ container_def_id ,
18191877 constraint. ident ,
18201878 ty:: AssocTag :: Fn ,
18211879 ) {
@@ -1844,10 +1902,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
18441902 this. visit_assoc_item_constraint ( constraint)
18451903 } ) ;
18461904 } ) ;
1847- } else if let Some ( type_def_id ) = type_def_id {
1905+ } else if let Some ( ( container_def_id , _ ) ) = container {
18481906 let bound_vars = BoundVarContext :: supertrait_hrtb_vars (
18491907 self . tcx ,
1850- type_def_id ,
1908+ container_def_id ,
18511909 constraint. ident ,
18521910 ty:: AssocTag :: Type ,
18531911 )
0 commit comments