55//! used between functions, and they operate in a purely top-down
66//! way. Therefore, we break lifetime name resolution into a separate pass.
77
8+ // ignore-tidy-filelength
9+
810use crate :: hir:: def:: { Res , DefKind } ;
911use crate :: hir:: def_id:: { CrateNum , DefId , LocalDefId , LOCAL_CRATE } ;
1012use crate :: hir:: map:: Map ;
@@ -556,6 +558,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
556558
557559 fn visit_ty ( & mut self , ty : & ' tcx hir:: Ty ) {
558560 debug ! ( "visit_ty: id={:?} ty={:?}" , ty. hir_id, ty) ;
561+ debug ! ( "visit_ty: ty.node={:?}" , ty. node) ;
559562 match ty. node {
560563 hir:: TyKind :: BareFn ( ref c) => {
561564 let next_early_index = self . next_early_index ( ) ;
@@ -585,11 +588,20 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
585588 self . is_in_fn_syntax = was_in_fn_syntax;
586589 }
587590 hir:: TyKind :: TraitObject ( ref bounds, ref lifetime) => {
591+ debug ! ( "visit_ty: TraitObject(bounds={:?}, lifetime={:?})" , bounds, lifetime) ;
588592 for bound in bounds {
589593 self . visit_poly_trait_ref ( bound, hir:: TraitBoundModifier :: None ) ;
590594 }
591595 match lifetime. name {
592596 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 => {
593605 // If the user does not write *anything*, we
594606 // use the object lifetime defaulting
595607 // rules. So e.g., `Box<dyn Debug>` becomes
@@ -897,6 +909,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
897909 }
898910
899911 fn visit_lifetime ( & mut self , lifetime_ref : & ' tcx hir:: Lifetime ) {
912+ debug ! ( "visit_lifetime(lifetime_ref={:?})" , lifetime_ref) ;
900913 if lifetime_ref. is_elided ( ) {
901914 self . resolve_elided_lifetimes ( vec ! [ lifetime_ref] ) ;
902915 return ;
@@ -1911,6 +1924,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
19111924 }
19121925
19131926 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+
19141934 if generic_args. parenthesized {
19151935 let was_in_fn_syntax = self . is_in_fn_syntax ;
19161936 self . is_in_fn_syntax = true ;
@@ -1964,6 +1984,23 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
19641984 _ => None ,
19651985 } ;
19661986
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.
19672004 let object_lifetime_defaults = type_def_id. map_or ( vec ! [ ] , |def_id| {
19682005 let in_body = {
19692006 let mut scope = self . scope ;
@@ -2003,6 +2040,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
20032040 . collect ( )
20042041 } )
20052042 } ;
2043+ debug ! ( "visit_segment_args: unsubst={:?}" , unsubst) ;
20062044 unsubst
20072045 . iter ( )
20082046 . map ( |set| match * set {
@@ -2023,6 +2061,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
20232061 . collect ( )
20242062 } ) ;
20252063
2064+ debug ! ( "visit_segment_args: object_lifetime_defaults={:?}" , object_lifetime_defaults) ;
2065+
20262066 let mut i = 0 ;
20272067 for arg in & generic_args. args {
20282068 match arg {
@@ -2045,8 +2085,49 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
20452085 }
20462086 }
20472087
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.
20482121 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) ) ;
20502131 }
20512132 }
20522133
@@ -2347,6 +2428,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
23472428 }
23482429
23492430 fn resolve_elided_lifetimes ( & mut self , lifetime_refs : Vec < & ' tcx hir:: Lifetime > ) {
2431+ debug ! ( "resolve_elided_lifetimes(lifetime_refs={:?})" , lifetime_refs) ;
2432+
23502433 if lifetime_refs. is_empty ( ) {
23512434 return ;
23522435 }
@@ -2539,6 +2622,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
25392622 }
25402623
25412624 fn resolve_object_lifetime_default ( & mut self , lifetime_ref : & ' tcx hir:: Lifetime ) {
2625+ debug ! ( "resolve_object_lifetime_default(lifetime_ref={:?})" , lifetime_ref) ;
25422626 let mut late_depth = 0 ;
25432627 let mut scope = self . scope ;
25442628 let lifetime = loop {
@@ -2638,6 +2722,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
26382722 hir:: LifetimeName :: Param ( _) | hir:: LifetimeName :: Implicit => {
26392723 self . resolve_lifetime_ref ( lt) ;
26402724 }
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+ }
26412732 hir:: LifetimeName :: Error => {
26422733 // No need to do anything, error already reported.
26432734 }
0 commit comments