@@ -174,7 +174,10 @@ crate struct LifetimeContext<'a, 'tcx> {
174174
175175 is_in_const_generic : bool ,
176176
177- definition_only : bool ,
177+ /// Indicates that we only care about the definition of a trait. This should
178+ /// be false if the `Item` we are resolving lifetimes for is not a trait or
179+ /// we eventually need lifetimes resolve for trait items.
180+ trait_definition_only : bool ,
178181
179182 /// List of labels in the function/method currently under analysis.
180183 labels_in_fn : Vec < Ident > ,
@@ -319,7 +322,7 @@ const ROOT_SCOPE: ScopeRef<'static> = &Scope::Root;
319322
320323pub fn provide ( providers : & mut ty:: query:: Providers ) {
321324 * providers = ty:: query:: Providers {
322- resolve_lifetimes_definition ,
325+ resolve_lifetimes_trait_definition ,
323326 resolve_lifetimes,
324327
325328 named_region_map : |tcx, id| resolve_lifetimes_for ( tcx, id) . defs . get ( & id) ,
@@ -339,14 +342,16 @@ pub fn provide(providers: &mut ty::query::Providers) {
339342/// Like `resolve_lifetimes`, but does not resolve lifetimes for trait items.
340343/// Also does not generate any diagnostics.
341344#[ tracing:: instrument( level = "debug" , skip( tcx) ) ]
342- fn resolve_lifetimes_definition ( tcx : TyCtxt < ' _ > , local_def_id : LocalDefId ) -> ResolveLifetimes {
345+ fn resolve_lifetimes_trait_definition (
346+ tcx : TyCtxt < ' _ > ,
347+ local_def_id : LocalDefId ,
348+ ) -> ResolveLifetimes {
343349 do_resolve ( tcx, local_def_id, true )
344350}
345351
346- /// Computes the `ResolveLifetimes` map that contains data for the
347- /// entire crate. You should not read the result of this query
348- /// directly, but rather use `named_region_map`, `is_late_bound_map`,
349- /// etc.
352+ /// Computes the `ResolveLifetimes` map that contains data for an entire `Item`.
353+ /// You should not read the result of this query directly, but rather use
354+ /// `named_region_map`, `is_late_bound_map`, etc.
350355#[ tracing:: instrument( level = "debug" , skip( tcx) ) ]
351356fn resolve_lifetimes ( tcx : TyCtxt < ' _ > , local_def_id : LocalDefId ) -> ResolveLifetimes {
352357 do_resolve ( tcx, local_def_id, false )
@@ -355,7 +360,7 @@ fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> ResolveLifeti
355360fn do_resolve (
356361 tcx : TyCtxt < ' _ > ,
357362 local_def_id : LocalDefId ,
358- definition_only : bool ,
363+ trait_definition_only : bool ,
359364) -> ResolveLifetimes {
360365 let item = tcx. hir ( ) . expect_item ( tcx. hir ( ) . local_def_id_to_hir_id ( local_def_id) ) ;
361366 let mut named_region_map =
@@ -367,7 +372,7 @@ fn do_resolve(
367372 trait_ref_hack : false ,
368373 is_in_fn_syntax : false ,
369374 is_in_const_generic : false ,
370- definition_only ,
375+ trait_definition_only ,
371376 labels_in_fn : vec ! [ ] ,
372377 xcrate_object_lifetime_defaults : Default :: default ( ) ,
373378 lifetime_uses : & mut Default :: default ( ) ,
@@ -390,19 +395,30 @@ fn do_resolve(
390395 rl
391396}
392397
398+ /// Given `any` owner (structs, traits, trait methods, etc.), does lifetime resolution.
399+ /// There are two important things this does.
400+ /// First, we have to resolve lifetimes for
401+ /// the entire *`Item`* that contains this owner, because that's the largest "scope"
402+ /// where we can have relevant lifetimes.
403+ /// Second, if we are asking for lifetimes in a trait *definition*, we use `resolve_lifetimes_trait_definition`
404+ /// instead of `resolve_lifetimes`, which does not descend into the trait items and does not emit diagnostics.
405+ /// This allows us to avoid cycles. Importantly, if we ask for lifetimes for lifetimes that have an owner
406+ /// other than the trait itself (like the trait methods or associated types), then we just use the regular
407+ /// `resolve_lifetimes`.
393408fn resolve_lifetimes_for < ' tcx > ( tcx : TyCtxt < ' tcx > , def_id : LocalDefId ) -> & ' tcx ResolveLifetimes {
394409 let item_id = item_for ( tcx, def_id) ;
395410 if item_id == def_id {
396411 let item = tcx. hir ( ) . item ( hir:: ItemId { def_id : item_id } ) ;
397412 match item. kind {
398- hir:: ItemKind :: Trait ( ..) => tcx. resolve_lifetimes_definition ( item_id) ,
413+ hir:: ItemKind :: Trait ( ..) => tcx. resolve_lifetimes_trait_definition ( item_id) ,
399414 _ => tcx. resolve_lifetimes ( item_id) ,
400415 }
401416 } else {
402417 tcx. resolve_lifetimes ( item_id)
403418 }
404419}
405420
421+ /// Finds the `Item` that contains the given `LocalDefId`
406422fn item_for ( tcx : TyCtxt < ' _ > , local_def_id : LocalDefId ) -> LocalDefId {
407423 let hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( local_def_id) ;
408424 match tcx. hir ( ) . find ( hir_id) {
@@ -470,7 +486,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
470486 fn visit_nested_item ( & mut self , _: hir:: ItemId ) { }
471487
472488 fn visit_trait_item_ref ( & mut self , ii : & ' tcx hir:: TraitItemRef ) {
473- if !self . definition_only {
489+ if !self . trait_definition_only {
474490 intravisit:: walk_trait_item_ref ( self , ii)
475491 }
476492 }
@@ -513,6 +529,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
513529 // Opaque types are visited when we visit the
514530 // `TyKind::OpaqueDef`, so that they have the lifetimes from
515531 // their parent opaque_ty in scope.
532+ //
533+ // The core idea here is that since OpaqueTys are generated with the impl Trait as
534+ // their owner, we can keep going until we find the Item that owns that. We then
535+ // conservatively add all resolved lifetimes. Otherwise we run into problems in
536+ // cases like `type Foo<'a> = impl Bar<As = impl Baz + 'a>`.
516537 for ( _hir_id, node) in
517538 self . tcx . hir ( ) . parent_iter ( self . tcx . hir ( ) . local_def_id_to_hir_id ( item. def_id ) )
518539 {
@@ -760,7 +781,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
760781 } ;
761782
762783 if !parent_is_item {
763- if !self . definition_only {
784+ if !self . trait_definition_only {
764785 struct_span_err ! (
765786 self . tcx. sess,
766787 lifetime. span,
@@ -1007,7 +1028,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
10071028 }
10081029
10091030 fn visit_generics ( & mut self , generics : & ' tcx hir:: Generics < ' tcx > ) {
1010- if !self . definition_only {
1031+ if !self . trait_definition_only {
10111032 check_mixed_explicit_and_in_band_defs ( self . tcx , & generics. params ) ;
10121033 }
10131034 for param in generics. params {
@@ -1501,7 +1522,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
15011522 trait_ref_hack : self . trait_ref_hack ,
15021523 is_in_fn_syntax : self . is_in_fn_syntax ,
15031524 is_in_const_generic : self . is_in_const_generic ,
1504- definition_only : self . definition_only ,
1525+ trait_definition_only : self . trait_definition_only ,
15051526 labels_in_fn,
15061527 xcrate_object_lifetime_defaults,
15071528 lifetime_uses,
@@ -1511,7 +1532,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
15111532 {
15121533 let _enter = span. enter ( ) ;
15131534 f ( self . scope , & mut this) ;
1514- if !self . definition_only {
1535+ if !self . trait_definition_only {
15151536 this. check_uses_for_lifetimes_defined_by_scope ( ) ;
15161537 }
15171538 }
@@ -1973,7 +1994,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
19731994 }
19741995
19751996 // Check for fn-syntax conflicts with in-band lifetime definitions
1976- if !self . definition_only && self . is_in_fn_syntax {
1997+ if !self . trait_definition_only && self . is_in_fn_syntax {
19771998 match def {
19781999 Region :: EarlyBound ( _, _, LifetimeDefOrigin :: InBand )
19792000 | Region :: LateBound ( _, _, LifetimeDefOrigin :: InBand ) => {
0 commit comments