5
5
//! used between functions, and they operate in a purely top-down
6
6
//! way. Therefore, we break lifetime name resolution into a separate pass.
7
7
8
+ // ignore-tidy-filelength
9
+
8
10
use crate :: hir:: def:: { Res , DefKind } ;
9
11
use crate :: hir:: def_id:: { CrateNum , DefId , LocalDefId , LOCAL_CRATE } ;
10
12
use crate :: hir:: map:: Map ;
@@ -556,6 +558,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
556
558
557
559
fn visit_ty ( & mut self , ty : & ' tcx hir:: Ty ) {
558
560
debug ! ( "visit_ty: id={:?} ty={:?}" , ty. hir_id, ty) ;
561
+ debug ! ( "visit_ty: ty.node={:?}" , ty. node) ;
559
562
match ty. node {
560
563
hir:: TyKind :: BareFn ( ref c) => {
561
564
let next_early_index = self . next_early_index ( ) ;
@@ -585,11 +588,20 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
585
588
self . is_in_fn_syntax = was_in_fn_syntax;
586
589
}
587
590
hir:: TyKind :: TraitObject ( ref bounds, ref lifetime) => {
591
+ debug ! ( "visit_ty: TraitObject(bounds={:?}, lifetime={:?})" , bounds, lifetime) ;
588
592
for bound in bounds {
589
593
self . visit_poly_trait_ref ( bound, hir:: TraitBoundModifier :: None ) ;
590
594
}
591
595
match lifetime. name {
592
596
LifetimeName :: Implicit => {
597
+ // For types like `dyn Foo`, we should
598
+ // generate a special form of elided.
599
+ span_bug ! (
600
+ ty. span,
601
+ "object-lifetime-default expected, not implict" ,
602
+ ) ;
603
+ }
604
+ LifetimeName :: ImplicitObjectLifetimeDefault => {
593
605
// If the user does not write *anything*, we
594
606
// use the object lifetime defaulting
595
607
// rules. So e.g., `Box<dyn Debug>` becomes
@@ -897,6 +909,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
897
909
}
898
910
899
911
fn visit_lifetime ( & mut self , lifetime_ref : & ' tcx hir:: Lifetime ) {
912
+ debug ! ( "visit_lifetime(lifetime_ref={:?})" , lifetime_ref) ;
900
913
if lifetime_ref. is_elided ( ) {
901
914
self . resolve_elided_lifetimes ( vec ! [ lifetime_ref] ) ;
902
915
return ;
@@ -1911,6 +1924,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
1911
1924
}
1912
1925
1913
1926
fn visit_segment_args ( & mut self , res : Res , depth : usize , generic_args : & ' tcx hir:: GenericArgs ) {
1927
+ debug ! (
1928
+ "visit_segment_args(res={:?}, depth={:?}, generic_args={:?})" ,
1929
+ res,
1930
+ depth,
1931
+ generic_args,
1932
+ ) ;
1933
+
1914
1934
if generic_args. parenthesized {
1915
1935
let was_in_fn_syntax = self . is_in_fn_syntax ;
1916
1936
self . is_in_fn_syntax = true ;
@@ -1964,6 +1984,23 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
1964
1984
_ => None ,
1965
1985
} ;
1966
1986
1987
+ debug ! ( "visit_segment_args: type_def_id={:?}" , type_def_id) ;
1988
+
1989
+ // Compute a vector of defaults, one for each type parameter,
1990
+ // per the rules given in RFCs 599 and 1156. Example:
1991
+ //
1992
+ // ```rust
1993
+ // struct Foo<'a, T: 'a, U> { }
1994
+ // ```
1995
+ //
1996
+ // If you have `Foo<'x, dyn Bar, dyn Baz>`, we want to default
1997
+ // `dyn Bar` to `dyn Bar + 'x` (because of the `T: 'a` bound)
1998
+ // and `dyn Baz` to `dyn Baz + 'static` (because there is no
1999
+ // such bound).
2000
+ //
2001
+ // Therefore, we would compute `object_lifetime_defaults` to a
2002
+ // vector like `['x, 'static]`. Note that the vector only
2003
+ // includes type parameters.
1967
2004
let object_lifetime_defaults = type_def_id. map_or ( vec ! [ ] , |def_id| {
1968
2005
let in_body = {
1969
2006
let mut scope = self . scope ;
@@ -2003,6 +2040,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
2003
2040
. collect ( )
2004
2041
} )
2005
2042
} ;
2043
+ debug ! ( "visit_segment_args: unsubst={:?}" , unsubst) ;
2006
2044
unsubst
2007
2045
. iter ( )
2008
2046
. map ( |set| match * set {
@@ -2023,6 +2061,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
2023
2061
. collect ( )
2024
2062
} ) ;
2025
2063
2064
+ debug ! ( "visit_segment_args: object_lifetime_defaults={:?}" , object_lifetime_defaults) ;
2065
+
2026
2066
let mut i = 0 ;
2027
2067
for arg in & generic_args. args {
2028
2068
match arg {
@@ -2045,8 +2085,49 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
2045
2085
}
2046
2086
}
2047
2087
2088
+ // Hack: when resolving the type `XX` in binding like `dyn
2089
+ // Foo<'b, Item = XX>`, the current object-lifetime default
2090
+ // would be to examine the trait `Foo` to check whether it has
2091
+ // a lifetime bound declared on `Item`. e.g., if `Foo` is
2092
+ // declared like so, then the default object lifetime bound in
2093
+ // `XX` should be `'b`:
2094
+ //
2095
+ // ```rust
2096
+ // trait Foo<'a> {
2097
+ // type Item: 'a;
2098
+ // }
2099
+ // ```
2100
+ //
2101
+ // but if we just have `type Item;`, then it would be
2102
+ // `'static`. However, we don't get all of this logic correct.
2103
+ //
2104
+ // Instead, we do something hacky: if there are no lifetime parameters
2105
+ // to the trait, then we simply use a default object lifetime
2106
+ // bound of `'static`, because there is no other possibility. On the other hand,
2107
+ // if there ARE lifetime parameters, then we require the user to give an
2108
+ // explicit bound for now.
2109
+ //
2110
+ // This is intended to leave room for us to implement the
2111
+ // correct behavior in the future.
2112
+ let has_lifetime_parameter = generic_args
2113
+ . args
2114
+ . iter ( )
2115
+ . any ( |arg| match arg {
2116
+ GenericArg :: Lifetime ( _) => true ,
2117
+ _ => false ,
2118
+ } ) ;
2119
+
2120
+ // Resolve lifetimes found in the type `XX` from `Item = XX` bindings.
2048
2121
for b in & generic_args. bindings {
2049
- self . visit_assoc_type_binding ( b) ;
2122
+ let scope = Scope :: ObjectLifetimeDefault {
2123
+ lifetime : if has_lifetime_parameter {
2124
+ None
2125
+ } else {
2126
+ Some ( Region :: Static )
2127
+ } ,
2128
+ s : self . scope ,
2129
+ } ;
2130
+ self . with ( scope, |_, this| this. visit_assoc_type_binding ( b) ) ;
2050
2131
}
2051
2132
}
2052
2133
@@ -2347,6 +2428,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
2347
2428
}
2348
2429
2349
2430
fn resolve_elided_lifetimes ( & mut self , lifetime_refs : Vec < & ' tcx hir:: Lifetime > ) {
2431
+ debug ! ( "resolve_elided_lifetimes(lifetime_refs={:?})" , lifetime_refs) ;
2432
+
2350
2433
if lifetime_refs. is_empty ( ) {
2351
2434
return ;
2352
2435
}
@@ -2539,6 +2622,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
2539
2622
}
2540
2623
2541
2624
fn resolve_object_lifetime_default ( & mut self , lifetime_ref : & ' tcx hir:: Lifetime ) {
2625
+ debug ! ( "resolve_object_lifetime_default(lifetime_ref={:?})" , lifetime_ref) ;
2542
2626
let mut late_depth = 0 ;
2543
2627
let mut scope = self . scope ;
2544
2628
let lifetime = loop {
@@ -2638,6 +2722,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
2638
2722
hir:: LifetimeName :: Param ( _) | hir:: LifetimeName :: Implicit => {
2639
2723
self . resolve_lifetime_ref ( lt) ;
2640
2724
}
2725
+ hir:: LifetimeName :: ImplicitObjectLifetimeDefault => {
2726
+ self . tcx . sess . delay_span_bug (
2727
+ lt. span ,
2728
+ "lowering generated `ImplicitObjectLifetimeDefault` \
2729
+ outside of an object type",
2730
+ )
2731
+ }
2641
2732
hir:: LifetimeName :: Error => {
2642
2733
// No need to do anything, error already reported.
2643
2734
}
0 commit comments