@@ -174,7 +174,10 @@ crate struct LifetimeContext<'a, 'tcx> {
174
174
175
175
is_in_const_generic : bool ,
176
176
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 ,
178
181
179
182
/// List of labels in the function/method currently under analysis.
180
183
labels_in_fn : Vec < Ident > ,
@@ -319,7 +322,7 @@ const ROOT_SCOPE: ScopeRef<'static> = &Scope::Root;
319
322
320
323
pub fn provide ( providers : & mut ty:: query:: Providers ) {
321
324
* providers = ty:: query:: Providers {
322
- resolve_lifetimes_definition ,
325
+ resolve_lifetimes_trait_definition ,
323
326
resolve_lifetimes,
324
327
325
328
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) {
339
342
/// Like `resolve_lifetimes`, but does not resolve lifetimes for trait items.
340
343
/// Also does not generate any diagnostics.
341
344
#[ 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 {
343
349
do_resolve ( tcx, local_def_id, true )
344
350
}
345
351
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.
350
355
#[ tracing:: instrument( level = "debug" , skip( tcx) ) ]
351
356
fn resolve_lifetimes ( tcx : TyCtxt < ' _ > , local_def_id : LocalDefId ) -> ResolveLifetimes {
352
357
do_resolve ( tcx, local_def_id, false )
@@ -355,7 +360,7 @@ fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> ResolveLifeti
355
360
fn do_resolve (
356
361
tcx : TyCtxt < ' _ > ,
357
362
local_def_id : LocalDefId ,
358
- definition_only : bool ,
363
+ trait_definition_only : bool ,
359
364
) -> ResolveLifetimes {
360
365
let item = tcx. hir ( ) . expect_item ( tcx. hir ( ) . local_def_id_to_hir_id ( local_def_id) ) ;
361
366
let mut named_region_map =
@@ -367,7 +372,7 @@ fn do_resolve(
367
372
trait_ref_hack : false ,
368
373
is_in_fn_syntax : false ,
369
374
is_in_const_generic : false ,
370
- definition_only ,
375
+ trait_definition_only ,
371
376
labels_in_fn : vec ! [ ] ,
372
377
xcrate_object_lifetime_defaults : Default :: default ( ) ,
373
378
lifetime_uses : & mut Default :: default ( ) ,
@@ -390,19 +395,30 @@ fn do_resolve(
390
395
rl
391
396
}
392
397
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`.
393
408
fn resolve_lifetimes_for < ' tcx > ( tcx : TyCtxt < ' tcx > , def_id : LocalDefId ) -> & ' tcx ResolveLifetimes {
394
409
let item_id = item_for ( tcx, def_id) ;
395
410
if item_id == def_id {
396
411
let item = tcx. hir ( ) . item ( hir:: ItemId { def_id : item_id } ) ;
397
412
match item. kind {
398
- hir:: ItemKind :: Trait ( ..) => tcx. resolve_lifetimes_definition ( item_id) ,
413
+ hir:: ItemKind :: Trait ( ..) => tcx. resolve_lifetimes_trait_definition ( item_id) ,
399
414
_ => tcx. resolve_lifetimes ( item_id) ,
400
415
}
401
416
} else {
402
417
tcx. resolve_lifetimes ( item_id)
403
418
}
404
419
}
405
420
421
+ /// Finds the `Item` that contains the given `LocalDefId`
406
422
fn item_for ( tcx : TyCtxt < ' _ > , local_def_id : LocalDefId ) -> LocalDefId {
407
423
let hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( local_def_id) ;
408
424
match tcx. hir ( ) . find ( hir_id) {
@@ -470,7 +486,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
470
486
fn visit_nested_item ( & mut self , _: hir:: ItemId ) { }
471
487
472
488
fn visit_trait_item_ref ( & mut self , ii : & ' tcx hir:: TraitItemRef ) {
473
- if !self . definition_only {
489
+ if !self . trait_definition_only {
474
490
intravisit:: walk_trait_item_ref ( self , ii)
475
491
}
476
492
}
@@ -513,6 +529,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
513
529
// Opaque types are visited when we visit the
514
530
// `TyKind::OpaqueDef`, so that they have the lifetimes from
515
531
// 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>`.
516
537
for ( _hir_id, node) in
517
538
self . tcx . hir ( ) . parent_iter ( self . tcx . hir ( ) . local_def_id_to_hir_id ( item. def_id ) )
518
539
{
@@ -760,7 +781,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
760
781
} ;
761
782
762
783
if !parent_is_item {
763
- if !self . definition_only {
784
+ if !self . trait_definition_only {
764
785
struct_span_err ! (
765
786
self . tcx. sess,
766
787
lifetime. span,
@@ -1007,7 +1028,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
1007
1028
}
1008
1029
1009
1030
fn visit_generics ( & mut self , generics : & ' tcx hir:: Generics < ' tcx > ) {
1010
- if !self . definition_only {
1031
+ if !self . trait_definition_only {
1011
1032
check_mixed_explicit_and_in_band_defs ( self . tcx , & generics. params ) ;
1012
1033
}
1013
1034
for param in generics. params {
@@ -1501,7 +1522,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
1501
1522
trait_ref_hack : self . trait_ref_hack ,
1502
1523
is_in_fn_syntax : self . is_in_fn_syntax ,
1503
1524
is_in_const_generic : self . is_in_const_generic ,
1504
- definition_only : self . definition_only ,
1525
+ trait_definition_only : self . trait_definition_only ,
1505
1526
labels_in_fn,
1506
1527
xcrate_object_lifetime_defaults,
1507
1528
lifetime_uses,
@@ -1511,7 +1532,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
1511
1532
{
1512
1533
let _enter = span. enter ( ) ;
1513
1534
f ( self . scope , & mut this) ;
1514
- if !self . definition_only {
1535
+ if !self . trait_definition_only {
1515
1536
this. check_uses_for_lifetimes_defined_by_scope ( ) ;
1516
1537
}
1517
1538
}
@@ -1973,7 +1994,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
1973
1994
}
1974
1995
1975
1996
// 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 {
1977
1998
match def {
1978
1999
Region :: EarlyBound ( _, _, LifetimeDefOrigin :: InBand )
1979
2000
| Region :: LateBound ( _, _, LifetimeDefOrigin :: InBand ) => {
0 commit comments