@@ -780,7 +780,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
780
780
// use the object lifetime defaulting
781
781
// rules. So e.g., `Box<dyn Debug>` becomes
782
782
// `Box<dyn Debug + 'static>`.
783
- self . resolve_object_lifetime_default ( & * lifetime)
783
+ self . resolve_object_lifetime_default ( & * lifetime) ;
784
784
}
785
785
LifetimeKind :: Infer => {
786
786
// If the user writes `'_`, we use the *ordinary* elision
@@ -799,7 +799,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
799
799
hir:: TyKind :: Ref ( lifetime_ref, ref mt) => {
800
800
self . visit_lifetime ( lifetime_ref) ;
801
801
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 ( ) ,
803
803
s : self . scope ,
804
804
} ;
805
805
self . with ( scope, |this| this. visit_ty_unambig ( mt. ty ) ) ;
@@ -887,11 +887,36 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
887
887
}
888
888
}
889
889
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
+
890
916
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 ( ) {
893
918
if let Some ( args) = segment. args {
894
- self . visit_segment_args ( path. res , depth , args) ;
919
+ self . visit_segment_args ( path, index , args) ;
895
920
}
896
921
}
897
922
if let Res :: Def ( DefKind :: TyParam | DefKind :: ConstParam , param_def_id) = path. res {
@@ -1611,55 +1636,72 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
1611
1636
#[ instrument( level = "debug" , skip( self ) ) ]
1612
1637
fn visit_segment_args (
1613
1638
& mut self ,
1614
- res : Res ,
1615
- depth : usize ,
1639
+ path : & hir :: Path < ' tcx > ,
1640
+ index : usize ,
1616
1641
generic_args : & ' tcx hir:: GenericArgs < ' tcx > ,
1617
1642
) {
1618
1643
if let Some ( ( inputs, output) ) = generic_args. paren_sugar_inputs_output ( ) {
1619
1644
self . visit_fn_like_elision ( inputs, Some ( output) , false ) ;
1620
1645
return ;
1621
1646
}
1622
1647
1648
+ // Let's first resolve all lifetime arguments because we need their resolution
1649
+ // for computing the ambient object lifetime defaults.
1623
1650
for arg in generic_args. args {
1624
1651
if let hir:: GenericArg :: Lifetime ( lt) = arg {
1625
1652
self . visit_lifetime ( lt) ;
1626
1653
}
1627
1654
}
1628
1655
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 definitions kinds that can 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).
1642
1685
_ => None ,
1643
1686
} ;
1644
1687
1645
- debug ! ( ?type_def_id ) ;
1688
+ debug ! ( ?container ) ;
1646
1689
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:
1649
1692
//
1650
1693
// ```rust
1651
- // struct Foo<'a, T: 'a, U> { }
1694
+ // struct Foo<'a, T: 'a + ?Sized , U: ?Sized>(&'a T, &'a U);
1652
1695
// ```
1653
1696
//
1654
1697
// If you have `Foo<'x, dyn Bar, dyn Baz>`, we want to default
1655
1698
// `dyn Bar` to `dyn Bar + 'x` (because of the `T: 'a` bound)
1656
1699
// and `dyn Baz` to `dyn Baz + 'static` (because there is no
1657
1700
// such bound).
1658
1701
//
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) | {
1663
1705
let in_body = {
1664
1706
let mut scope = self . scope ;
1665
1707
loop {
@@ -1683,9 +1725,6 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
1683
1725
let rbv = & self . rbv ;
1684
1726
let generics = self . tcx . generics_of ( def_id) ;
1685
1727
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
-
1689
1728
let set_to_region = |set : ObjectLifetimeDefault | match set {
1690
1729
ObjectLifetimeDefault :: Empty => {
1691
1730
if in_body {
@@ -1696,12 +1735,31 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
1696
1735
}
1697
1736
ObjectLifetimeDefault :: Static => Some ( ResolvedArg :: StaticLifetime ) ,
1698
1737
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 ( index, depth) = 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
+ } )
1705
1763
}
1706
1764
ObjectLifetimeDefault :: Ambiguous => None ,
1707
1765
} ;
@@ -1731,6 +1789,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
1731
1789
let mut i = 0 ;
1732
1790
for arg in generic_args. args {
1733
1791
match arg {
1792
+ // We've already visited all lifetime arguments at the start.
1734
1793
GenericArg :: Lifetime ( _) => { }
1735
1794
GenericArg :: Type ( ty) => {
1736
1795
if let Some ( & lt) = object_lifetime_defaults. get ( i) {
@@ -1805,11 +1864,11 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
1805
1864
// `for<'a> for<'r> <T as Trait<'a>>::x::<'r, T>::{opaque#0}: for<'b> Other<'b>`.
1806
1865
if constraint. gen_args . parenthesized == hir:: GenericArgsParentheses :: ReturnTypeNotation
1807
1866
{
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
1810
1869
&& let Some ( ( mut bound_vars, assoc_fn) ) = BoundVarContext :: supertrait_hrtb_vars (
1811
1870
self . tcx ,
1812
- type_def_id ,
1871
+ container_def_id ,
1813
1872
constraint. ident ,
1814
1873
ty:: AssocTag :: Fn ,
1815
1874
) {
@@ -1838,10 +1897,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
1838
1897
this. visit_assoc_item_constraint ( constraint)
1839
1898
} ) ;
1840
1899
} ) ;
1841
- } else if let Some ( type_def_id ) = type_def_id {
1900
+ } else if let Some ( ( container_def_id , _ ) ) = container {
1842
1901
let bound_vars = BoundVarContext :: supertrait_hrtb_vars (
1843
1902
self . tcx ,
1844
- type_def_id ,
1903
+ container_def_id ,
1845
1904
constraint. ident ,
1846
1905
ty:: AssocTag :: Type ,
1847
1906
)
0 commit comments