@@ -780,7 +780,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
780780 // use the object lifetime defaulting
781781 // rules. So e.g., `Box<dyn Debug>` becomes
782782 // `Box<dyn Debug + 'static>`.
783- self . resolve_object_lifetime_default ( & * lifetime)
783+ self . resolve_object_lifetime_default ( & * lifetime) ;
784784 }
785785 LifetimeKind :: Infer => {
786786 // If the user writes `'_`, we use the *ordinary* elision
@@ -799,7 +799,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
799799 hir:: TyKind :: Ref ( lifetime_ref, ref mt) => {
800800 self . visit_lifetime ( lifetime_ref) ;
801801 let scope = Scope :: ObjectLifetimeDefault {
802- lifetime : self . rbv . defs . get ( & lifetime_ref. hir_id . local_id ) . cloned ( ) ,
802+ lifetime : self . rbv . defs . get ( & lifetime_ref. hir_id . local_id ) . copied ( ) ,
803803 s : self . scope ,
804804 } ;
805805 self . with ( scope, |this| this. visit_ty_unambig ( mt. ty ) ) ;
@@ -887,11 +887,36 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
887887 }
888888 }
889889
890+ fn visit_qpath ( & mut self , qpath : & ' tcx hir:: QPath < ' tcx > , id : HirId , _: Span ) {
891+ match qpath {
892+ hir:: QPath :: Resolved ( maybe_qself, path) => {
893+ if let Some ( qself) = maybe_qself {
894+ // FIXME: Actually determine the ambient object lifetime defaults for the self ty!
895+ let scope = Scope :: ObjectLifetimeDefault { lifetime : None , s : self . scope } ;
896+ self . with ( scope, |this| this. visit_ty_unambig ( qself) ) ;
897+ }
898+ self . visit_path ( path, id) ;
899+ }
900+ hir:: QPath :: TypeRelative ( qself, segment) => {
901+ // Resolving object lifetime defaults for type-relative paths requires full
902+ // type-dependent resolution as performed by HIR ty lowering whose results
903+ // we don't have access to (and we'd results for both FnCtxts and ItemCtxts).
904+ // FIXME: Figure out if there's a feasible way to obtain the map of
905+ // type-dependent definitions.
906+ let scope = Scope :: ObjectLifetimeDefault { lifetime : None , s : self . scope } ;
907+ self . with ( scope, |this| {
908+ this. visit_ty_unambig ( qself) ;
909+ this. visit_path_segment ( segment)
910+ } ) ;
911+ }
912+ hir:: QPath :: LangItem ( ..) => { }
913+ }
914+ }
915+
890916 fn visit_path ( & mut self , path : & hir:: Path < ' tcx > , hir_id : HirId ) {
891- for ( i, segment) in path. segments . iter ( ) . enumerate ( ) {
892- let depth = path. segments . len ( ) - i - 1 ;
917+ for ( index, segment) in path. segments . iter ( ) . enumerate ( ) {
893918 if let Some ( args) = segment. args {
894- self . visit_segment_args ( path. res , depth , args) ;
919+ self . visit_segment_args ( path, index , args) ;
895920 }
896921 }
897922 if let Res :: Def ( DefKind :: TyParam | DefKind :: ConstParam , param_def_id) = path. res {
@@ -1611,55 +1636,72 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
16111636 #[ instrument( level = "debug" , skip( self ) ) ]
16121637 fn visit_segment_args (
16131638 & mut self ,
1614- res : Res ,
1615- depth : usize ,
1639+ path : & hir :: Path < ' tcx > ,
1640+ index : usize ,
16161641 generic_args : & ' tcx hir:: GenericArgs < ' tcx > ,
16171642 ) {
16181643 if let Some ( ( inputs, output) ) = generic_args. paren_sugar_inputs_output ( ) {
16191644 self . visit_fn_like_elision ( inputs, Some ( output) , false ) ;
16201645 return ;
16211646 }
16221647
1648+ // Let's first resolve all lifetime arguments because we need their resolution
1649+ // for computing the ambient object lifetime defaults.
16231650 for arg in generic_args. args {
16241651 if let hir:: GenericArg :: Lifetime ( lt) = arg {
16251652 self . visit_lifetime ( lt) ;
16261653 }
16271654 }
16281655
1629- // Figure out if this is a type/trait segment,
1630- // which requires object lifetime defaults.
1631- let type_def_id = match res {
1632- Res :: Def ( DefKind :: AssocTy , def_id) if depth == 1 => Some ( self . tcx . parent ( def_id) ) ,
1633- Res :: Def ( DefKind :: Variant , def_id) if depth == 0 => Some ( self . tcx . parent ( def_id) ) ,
1634- Res :: Def (
1635- DefKind :: Struct
1636- | DefKind :: Union
1637- | DefKind :: Enum
1638- | DefKind :: TyAlias
1639- | DefKind :: Trait ,
1640- def_id,
1641- ) if depth == 0 => Some ( def_id) ,
1656+ // Figure out if this is an "eligible generic container" that brings along ambient object
1657+ // lifetime defaults for trait object types contained in any of the type arguments passed to
1658+ // it (any inner generic containers will of course end up shadowing that the default).
1659+ let depth = path. segments . len ( ) - index - 1 ;
1660+ let container = match ( path. res , depth) {
1661+ ( Res :: Def ( DefKind :: AssocTy , def_id) , 1 ) => {
1662+ Some ( ( self . tcx . parent ( def_id) , & path. segments [ ..=index] ) )
1663+ }
1664+ ( Res :: Def ( DefKind :: Variant , def_id) , 0 ) => {
1665+ Some ( ( self . tcx . parent ( def_id) , path. segments ) )
1666+ }
1667+ // FIXME(trait_alias): Arguably, trait aliases are eligible generic containers.
1668+ (
1669+ Res :: Def (
1670+ DefKind :: Struct
1671+ | DefKind :: Union
1672+ | DefKind :: Enum
1673+ | DefKind :: TyAlias
1674+ | DefKind :: Trait
1675+ | DefKind :: AssocTy ,
1676+ def_id,
1677+ ) ,
1678+ 0 ,
1679+ ) => Some ( ( def_id, path. segments ) ) ,
1680+ // Note: We don't need to care about definition kinds that may have generics if they
1681+ // can only ever appear in positions where we can perform type inference (i.e., bodies).
1682+ // FIXME(mgca): @fmease thinks that under (m)GCA we now also need to care about e.g.,
1683+ // type-level Consts (GCI) and AssocConsts (maybe also Fns, AssocFns) here
1684+ // since they appear outside of bodies (once the feature is more complete).
16421685 _ => None ,
16431686 } ;
16441687
1645- debug ! ( ?type_def_id ) ;
1688+ debug ! ( ?container ) ;
16461689
1647- // Compute a vector of defaults, one for each type parameter,
1648- // per the rules given in RFCs 599 and 1156. Example:
1690+ // Compute a vector of ambient object lifetime defaults, one for each type parameter,
1691+ // per the rules initially given in RFCs 599 and 1156. Example:
16491692 //
16501693 // ```rust
1651- // struct Foo<'a, T: 'a, U> { }
1694+ // struct Foo<'a, T: 'a + ?Sized , U: ?Sized>(&'a T, &'a U);
16521695 // ```
16531696 //
16541697 // If you have `Foo<'x, dyn Bar, dyn Baz>`, we want to default
16551698 // `dyn Bar` to `dyn Bar + 'x` (because of the `T: 'a` bound)
16561699 // and `dyn Baz` to `dyn Baz + 'static` (because there is no
16571700 // such bound).
16581701 //
1659- // Therefore, we would compute `object_lifetime_defaults` to a
1660- // vector like `['x, 'static]`. Note that the vector only
1661- // includes type parameters.
1662- let object_lifetime_defaults = type_def_id. map_or_else ( Vec :: new, |def_id| {
1702+ // Therefore, we would compute a vector like `['x, 'static]`.
1703+ // Note that the vector only includes type parameters.
1704+ let object_lifetime_defaults = container. map_or_else ( Vec :: new, |( def_id, segments) | {
16631705 let in_body = {
16641706 let mut scope = self . scope ;
16651707 loop {
@@ -1683,9 +1725,6 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
16831725 let rbv = & self . rbv ;
16841726 let generics = self . tcx . generics_of ( def_id) ;
16851727
1686- // `type_def_id` points to an item, so there is nothing to inherit generics from.
1687- debug_assert_eq ! ( generics. parent_count, 0 ) ;
1688-
16891728 let set_to_region = |set : ObjectLifetimeDefault | match set {
16901729 ObjectLifetimeDefault :: Empty => {
16911730 if in_body {
@@ -1696,12 +1735,31 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
16961735 }
16971736 ObjectLifetimeDefault :: Static => Some ( ResolvedArg :: StaticLifetime ) ,
16981737 ObjectLifetimeDefault :: Param ( param_def_id) => {
1699- // This index can be used with `generic_args` since `parent_count == 0`.
1700- let index = generics. param_def_id_to_index [ & param_def_id] as usize ;
1701- generic_args. args . get ( index) . and_then ( |arg| match arg {
1702- GenericArg :: Lifetime ( lt) => rbv. defs . get ( & lt. hir_id . local_id ) . copied ( ) ,
1703- _ => None ,
1704- } )
1738+ fn param_to_depth_and_index (
1739+ generics : & ty:: Generics ,
1740+ tcx : TyCtxt < ' _ > ,
1741+ def_id : DefId ,
1742+ ) -> ( usize , usize ) {
1743+ if let Some ( & index) = generics. param_def_id_to_index . get ( & def_id) {
1744+ let has_self = generics. parent . is_none ( ) && generics. has_self ;
1745+ ( 0 , index as usize - generics. parent_count - has_self as usize )
1746+ } else if let Some ( parent) = generics. parent {
1747+ let parent = tcx. generics_of ( parent) ;
1748+ let ( depth, index) = param_to_depth_and_index ( parent, tcx, def_id) ;
1749+ ( depth + 1 , index)
1750+ } else {
1751+ unreachable ! ( )
1752+ }
1753+ }
1754+
1755+ let ( depth, index) = param_to_depth_and_index ( generics, self . tcx , param_def_id) ;
1756+ segments[ segments. len ( ) - depth - 1 ]
1757+ . args
1758+ . and_then ( |args| args. args . get ( index) )
1759+ . and_then ( |arg| match arg {
1760+ GenericArg :: Lifetime ( lt) => rbv. defs . get ( & lt. hir_id . local_id ) . copied ( ) ,
1761+ _ => None ,
1762+ } )
17051763 }
17061764 ObjectLifetimeDefault :: Ambiguous => None ,
17071765 } ;
@@ -1731,6 +1789,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
17311789 let mut i = 0 ;
17321790 for arg in generic_args. args {
17331791 match arg {
1792+ // We've already visited all lifetime arguments at the start.
17341793 GenericArg :: Lifetime ( _) => { }
17351794 GenericArg :: Type ( ty) => {
17361795 if let Some ( & lt) = object_lifetime_defaults. get ( i) {
@@ -1805,11 +1864,11 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
18051864 // `for<'a> for<'r> <T as Trait<'a>>::x::<'r, T>::{opaque#0}: for<'b> Other<'b>`.
18061865 if constraint. gen_args . parenthesized == hir:: GenericArgsParentheses :: ReturnTypeNotation
18071866 {
1808- let bound_vars = if let Some ( type_def_id ) = type_def_id
1809- && self . tcx . def_kind ( type_def_id ) == DefKind :: Trait
1867+ let bound_vars = if let Some ( ( container_def_id , _ ) ) = container
1868+ && self . tcx . def_kind ( container_def_id ) == DefKind :: Trait
18101869 && let Some ( ( mut bound_vars, assoc_fn) ) = BoundVarContext :: supertrait_hrtb_vars (
18111870 self . tcx ,
1812- type_def_id ,
1871+ container_def_id ,
18131872 constraint. ident ,
18141873 ty:: AssocTag :: Fn ,
18151874 ) {
@@ -1838,10 +1897,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
18381897 this. visit_assoc_item_constraint ( constraint)
18391898 } ) ;
18401899 } ) ;
1841- } else if let Some ( type_def_id ) = type_def_id {
1900+ } else if let Some ( ( container_def_id , _ ) ) = container {
18421901 let bound_vars = BoundVarContext :: supertrait_hrtb_vars (
18431902 self . tcx ,
1844- type_def_id ,
1903+ container_def_id ,
18451904 constraint. ident ,
18461905 ty:: AssocTag :: Type ,
18471906 )
0 commit comments