@@ -94,11 +94,6 @@ struct LifetimeContext<'a, 'tcx> {
94
94
tcx : TyCtxt < ' tcx > ,
95
95
map : & ' a mut NamedRegionMap ,
96
96
scope : ScopeRef < ' a > ,
97
-
98
- /// Indicates that we only care about the definition of a trait. This should
99
- /// be false if the `Item` we are resolving lifetimes for is not a trait or
100
- /// we eventually need lifetimes resolve for trait items.
101
- trait_definition_only : bool ,
102
97
}
103
98
104
99
#[ derive( Debug ) ]
@@ -166,7 +161,9 @@ enum Scope<'a> {
166
161
s : ScopeRef < ' a > ,
167
162
} ,
168
163
169
- Root ,
164
+ Root {
165
+ opt_parent_item : Option < LocalDefId > ,
166
+ } ,
170
167
}
171
168
172
169
#[ derive( Copy , Clone , Debug ) ]
@@ -214,95 +211,58 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
214
211
. field ( "s" , & ".." )
215
212
. finish ( ) ,
216
213
Scope :: TraitRefBoundary { s : _ } => f. debug_struct ( "TraitRefBoundary" ) . finish ( ) ,
217
- Scope :: Root => f. debug_struct ( "Root" ) . finish ( ) ,
214
+ Scope :: Root { opt_parent_item } => {
215
+ f. debug_struct ( "Root" ) . field ( "opt_parent_item" , & opt_parent_item) . finish ( )
216
+ }
218
217
}
219
218
}
220
219
}
221
220
222
221
type ScopeRef < ' a > = & ' a Scope < ' a > ;
223
222
224
- const ROOT_SCOPE : ScopeRef < ' static > = & Scope :: Root ;
225
-
226
223
pub ( crate ) fn provide ( providers : & mut ty:: query:: Providers ) {
227
224
* providers = ty:: query:: Providers {
228
- resolve_lifetimes_trait_definition,
229
225
resolve_lifetimes,
230
226
231
- named_region_map : |tcx, id| resolve_lifetimes_for ( tcx, id) . defs . get ( & id) ,
227
+ named_region_map : |tcx, id| tcx. resolve_lifetimes ( id) . defs . get ( & id) ,
232
228
is_late_bound_map,
233
229
object_lifetime_default,
234
- late_bound_vars_map : |tcx, id| resolve_lifetimes_for ( tcx, id) . late_bound_vars . get ( & id) ,
230
+ late_bound_vars_map : |tcx, id| tcx. resolve_lifetimes ( id) . late_bound_vars . get ( & id) ,
235
231
236
232
..* providers
237
233
} ;
238
234
}
239
235
240
- /// Like `resolve_lifetimes`, but does not resolve lifetimes for trait items.
241
- /// Also does not generate any diagnostics.
242
- ///
243
- /// This is ultimately a subset of the `resolve_lifetimes` work. It effectively
244
- /// resolves lifetimes only within the trait "header" -- that is, the trait
245
- /// and supertrait list. In contrast, `resolve_lifetimes` resolves all the
246
- /// lifetimes within the trait and its items. There is room to refactor this,
247
- /// for example to resolve lifetimes for each trait item in separate queries,
248
- /// but it's convenient to do the entire trait at once because the lifetimes
249
- /// from the trait definition are in scope within the trait items as well.
250
- ///
251
- /// The reason for this separate call is to resolve what would otherwise
252
- /// be a cycle. Consider this example:
253
- ///
254
- /// ```ignore UNSOLVED (maybe @jackh726 knows what lifetime parameter to give Sub)
255
- /// trait Base<'a> {
256
- /// type BaseItem;
257
- /// }
258
- /// trait Sub<'b>: for<'a> Base<'a> {
259
- /// type SubItem: Sub<BaseItem = &'b u32>;
260
- /// }
261
- /// ```
262
- ///
263
- /// When we resolve `Sub` and all its items, we also have to resolve `Sub<BaseItem = &'b u32>`.
264
- /// To figure out the index of `'b`, we have to know about the supertraits
265
- /// of `Sub` so that we can determine that the `for<'a>` will be in scope.
266
- /// (This is because we -- currently at least -- flatten all the late-bound
267
- /// lifetimes into a single binder.) This requires us to resolve the
268
- /// *trait definition* of `Sub`; basically just enough lifetime information
269
- /// to look at the supertraits.
270
- #[ instrument( level = "debug" , skip( tcx) ) ]
271
- fn resolve_lifetimes_trait_definition (
272
- tcx : TyCtxt < ' _ > ,
273
- local_def_id : LocalDefId ,
274
- ) -> ResolveLifetimes {
275
- convert_named_region_map ( do_resolve ( tcx, local_def_id, true ) )
276
- }
277
-
278
236
/// Computes the `ResolveLifetimes` map that contains data for an entire `Item`.
279
237
/// You should not read the result of this query directly, but rather use
280
238
/// `named_region_map`, `is_late_bound_map`, etc.
281
239
#[ instrument( level = "debug" , skip( tcx) ) ]
282
- fn resolve_lifetimes ( tcx : TyCtxt < ' _ > , local_def_id : LocalDefId ) -> ResolveLifetimes {
283
- convert_named_region_map ( do_resolve ( tcx, local_def_id, false ) )
284
- }
285
-
286
- fn do_resolve (
287
- tcx : TyCtxt < ' _ > ,
288
- local_def_id : LocalDefId ,
289
- trait_definition_only : bool ,
290
- ) -> NamedRegionMap {
291
- let item = tcx. hir ( ) . expect_item ( local_def_id) ;
240
+ fn resolve_lifetimes ( tcx : TyCtxt < ' _ > , local_def_id : hir:: OwnerId ) -> ResolveLifetimes {
292
241
let mut named_region_map =
293
242
NamedRegionMap { defs : Default :: default ( ) , late_bound_vars : Default :: default ( ) } ;
294
243
let mut visitor = LifetimeContext {
295
244
tcx,
296
245
map : & mut named_region_map,
297
- scope : ROOT_SCOPE ,
298
- trait_definition_only,
246
+ scope : & Scope :: Root { opt_parent_item : None } ,
299
247
} ;
300
- visitor. visit_item ( item) ;
301
-
302
- named_region_map
303
- }
248
+ match tcx. hir ( ) . owner ( local_def_id) {
249
+ hir:: OwnerNode :: Item ( item) => visitor. visit_item ( item) ,
250
+ hir:: OwnerNode :: ForeignItem ( item) => visitor. visit_foreign_item ( item) ,
251
+ hir:: OwnerNode :: TraitItem ( item) => {
252
+ let scope =
253
+ Scope :: Root { opt_parent_item : Some ( tcx. local_parent ( item. owner_id . def_id ) ) } ;
254
+ visitor. scope = & scope;
255
+ visitor. visit_trait_item ( item)
256
+ }
257
+ hir:: OwnerNode :: ImplItem ( item) => {
258
+ let scope =
259
+ Scope :: Root { opt_parent_item : Some ( tcx. local_parent ( item. owner_id . def_id ) ) } ;
260
+ visitor. scope = & scope;
261
+ visitor. visit_impl_item ( item)
262
+ }
263
+ hir:: OwnerNode :: Crate ( _) => { }
264
+ }
304
265
305
- fn convert_named_region_map ( named_region_map : NamedRegionMap ) -> ResolveLifetimes {
306
266
let mut rl = ResolveLifetimes :: default ( ) ;
307
267
308
268
for ( hir_id, v) in named_region_map. defs {
@@ -319,53 +279,6 @@ fn convert_named_region_map(named_region_map: NamedRegionMap) -> ResolveLifetime
319
279
rl
320
280
}
321
281
322
- /// Given `any` owner (structs, traits, trait methods, etc.), does lifetime resolution.
323
- /// There are two important things this does.
324
- /// First, we have to resolve lifetimes for
325
- /// the entire *`Item`* that contains this owner, because that's the largest "scope"
326
- /// where we can have relevant lifetimes.
327
- /// Second, if we are asking for lifetimes in a trait *definition*, we use `resolve_lifetimes_trait_definition`
328
- /// instead of `resolve_lifetimes`, which does not descend into the trait items and does not emit diagnostics.
329
- /// This allows us to avoid cycles. Importantly, if we ask for lifetimes for lifetimes that have an owner
330
- /// other than the trait itself (like the trait methods or associated types), then we just use the regular
331
- /// `resolve_lifetimes`.
332
- fn resolve_lifetimes_for < ' tcx > ( tcx : TyCtxt < ' tcx > , def_id : hir:: OwnerId ) -> & ' tcx ResolveLifetimes {
333
- let item_id = item_for ( tcx, def_id. def_id ) ;
334
- let local_def_id = item_id. owner_id . def_id ;
335
- if item_id. owner_id == def_id {
336
- let item = tcx. hir ( ) . item ( item_id) ;
337
- match item. kind {
338
- hir:: ItemKind :: Trait ( ..) => tcx. resolve_lifetimes_trait_definition ( local_def_id) ,
339
- _ => tcx. resolve_lifetimes ( local_def_id) ,
340
- }
341
- } else {
342
- tcx. resolve_lifetimes ( local_def_id)
343
- }
344
- }
345
-
346
- /// Finds the `Item` that contains the given `LocalDefId`
347
- fn item_for ( tcx : TyCtxt < ' _ > , local_def_id : LocalDefId ) -> hir:: ItemId {
348
- match tcx. hir ( ) . find_by_def_id ( local_def_id) {
349
- Some ( Node :: Item ( item) ) => {
350
- return item. item_id ( ) ;
351
- }
352
- _ => { }
353
- }
354
- let item = {
355
- let hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( local_def_id) ;
356
- let mut parent_iter = tcx. hir ( ) . parent_iter ( hir_id) ;
357
- loop {
358
- let node = parent_iter. next ( ) . map ( |n| n. 1 ) ;
359
- match node {
360
- Some ( hir:: Node :: Item ( item) ) => break item. item_id ( ) ,
361
- Some ( hir:: Node :: Crate ( _) ) | None => bug ! ( "Called `item_for` on an Item." ) ,
362
- _ => { }
363
- }
364
- }
365
- } ;
366
- item
367
- }
368
-
369
282
fn late_region_as_bound_region < ' tcx > ( tcx : TyCtxt < ' tcx > , region : & Region ) -> ty:: BoundVariableKind {
370
283
match region {
371
284
Region :: LateBound ( _, _, def_id) => {
@@ -383,7 +296,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
383
296
let mut supertrait_lifetimes = vec ! [ ] ;
384
297
loop {
385
298
match scope {
386
- Scope :: Body { .. } | Scope :: Root => {
299
+ Scope :: Body { .. } | Scope :: Root { .. } => {
387
300
break ( vec ! [ ] , BinderScopeType :: Normal ) ;
388
301
}
389
302
@@ -414,21 +327,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
414
327
}
415
328
}
416
329
impl < ' a , ' tcx > Visitor < ' tcx > for LifetimeContext < ' a , ' tcx > {
417
- type NestedFilter = nested_filter:: All ;
330
+ type NestedFilter = nested_filter:: OnlyBodies ;
418
331
419
332
fn nested_visit_map ( & mut self ) -> Self :: Map {
420
333
self . tcx . hir ( )
421
334
}
422
335
423
- // We want to nest trait/impl items in their parent, but nothing else.
424
- fn visit_nested_item ( & mut self , _: hir:: ItemId ) { }
425
-
426
- fn visit_trait_item_ref ( & mut self , ii : & ' tcx hir:: TraitItemRef ) {
427
- if !self . trait_definition_only {
428
- intravisit:: walk_trait_item_ref ( self , ii)
429
- }
430
- }
431
-
432
336
fn visit_nested_body ( & mut self , body : hir:: BodyId ) {
433
337
let body = self . tcx . hir ( ) . body ( body) ;
434
338
self . with ( Scope :: Body { id : body. id ( ) , s : self . scope } , |this| {
@@ -557,33 +461,21 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
557
461
// their owner, we can keep going until we find the Item that owns that. We then
558
462
// conservatively add all resolved lifetimes. Otherwise we run into problems in
559
463
// cases like `type Foo<'a> = impl Bar<As = impl Baz + 'a>`.
560
- for ( _hir_id, node) in self . tcx . hir ( ) . parent_iter ( item. owner_id . into ( ) ) {
561
- match node {
562
- hir:: Node :: Item ( parent_item) => {
563
- let resolved_lifetimes: & ResolveLifetimes = self . tcx . resolve_lifetimes (
564
- item_for ( self . tcx , parent_item. owner_id . def_id ) . owner_id . def_id ,
565
- ) ;
566
- // We need to add *all* deps, since opaque tys may want them from *us*
567
- for ( & owner, defs) in resolved_lifetimes. defs . iter ( ) {
568
- defs. iter ( ) . for_each ( |( & local_id, region) | {
569
- self . map . defs . insert ( hir:: HirId { owner, local_id } , * region) ;
570
- } ) ;
571
- }
572
- for ( & owner, late_bound_vars) in
573
- resolved_lifetimes. late_bound_vars . iter ( )
574
- {
575
- late_bound_vars. iter ( ) . for_each ( |( & local_id, late_bound_vars) | {
576
- self . record_late_bound_vars (
577
- hir:: HirId { owner, local_id } ,
578
- late_bound_vars. clone ( ) ,
579
- ) ;
580
- } ) ;
581
- }
582
- break ;
583
- }
584
- hir:: Node :: Crate ( _) => bug ! ( "No Item about an OpaqueTy" ) ,
585
- _ => { }
586
- }
464
+ let parent_item = self . tcx . hir ( ) . get_parent_item ( item. hir_id ( ) ) ;
465
+ let resolved_lifetimes: & ResolveLifetimes = self . tcx . resolve_lifetimes ( parent_item) ;
466
+ // We need to add *all* deps, since opaque tys may want them from *us*
467
+ for ( & owner, defs) in resolved_lifetimes. defs . iter ( ) {
468
+ defs. iter ( ) . for_each ( |( & local_id, region) | {
469
+ self . map . defs . insert ( hir:: HirId { owner, local_id } , * region) ;
470
+ } ) ;
471
+ }
472
+ for ( & owner, late_bound_vars) in resolved_lifetimes. late_bound_vars . iter ( ) {
473
+ late_bound_vars. iter ( ) . for_each ( |( & local_id, late_bound_vars) | {
474
+ self . record_late_bound_vars (
475
+ hir:: HirId { owner, local_id } ,
476
+ late_bound_vars. clone ( ) ,
477
+ ) ;
478
+ } ) ;
587
479
}
588
480
}
589
481
hir:: ItemKind :: TyAlias ( _, ref generics)
@@ -609,7 +501,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
609
501
hir_id : item. hir_id ( ) ,
610
502
lifetimes,
611
503
scope_type : BinderScopeType :: Normal ,
612
- s : ROOT_SCOPE ,
504
+ s : self . scope ,
613
505
where_bound_origin : None ,
614
506
} ;
615
507
self . with ( scope, |this| {
@@ -766,30 +658,26 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
766
658
// Ensure that the parent of the def is an item, not HRTB
767
659
let parent_id = self . tcx . hir ( ) . get_parent_node ( hir_id) ;
768
660
if !parent_id. is_owner ( ) {
769
- if !self . trait_definition_only {
770
- struct_span_err ! (
771
- self . tcx. sess,
772
- lifetime. span,
773
- E0657 ,
774
- "`impl Trait` can only capture lifetimes \
661
+ struct_span_err ! (
662
+ self . tcx. sess,
663
+ lifetime. span,
664
+ E0657 ,
665
+ "`impl Trait` can only capture lifetimes \
775
666
bound at the fn or impl level"
776
- )
777
- . emit ( ) ;
778
- }
667
+ )
668
+ . emit ( ) ;
779
669
self . uninsert_lifetime_on_error ( lifetime, def. unwrap ( ) ) ;
780
670
}
781
671
if let hir:: Node :: Item ( hir:: Item {
782
672
kind : hir:: ItemKind :: OpaqueTy { .. } , ..
783
673
} ) = self . tcx . hir ( ) . get ( parent_id)
784
674
{
785
- if !self . trait_definition_only {
786
- let mut err = self . tcx . sess . struct_span_err (
675
+ let mut err = self . tcx . sess . struct_span_err (
787
676
lifetime. span ,
788
677
"higher kinded lifetime bounds on nested opaque types are not supported yet" ,
789
678
) ;
790
- err. span_note ( self . tcx . def_span ( def_id) , "lifetime declared here" ) ;
791
- err. emit ( ) ;
792
- }
679
+ err. span_note ( self . tcx . def_span ( def_id) , "lifetime declared here" ) ;
680
+ err. emit ( ) ;
793
681
self . uninsert_lifetime_on_error ( lifetime, def. unwrap ( ) ) ;
794
682
}
795
683
}
@@ -1193,12 +1081,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
1193
1081
F : for < ' b > FnOnce ( & mut LifetimeContext < ' b , ' tcx > ) ,
1194
1082
{
1195
1083
let LifetimeContext { tcx, map, .. } = self ;
1196
- let mut this = LifetimeContext {
1197
- tcx : * tcx,
1198
- map,
1199
- scope : & wrap_scope,
1200
- trait_definition_only : self . trait_definition_only ,
1201
- } ;
1084
+ let mut this = LifetimeContext { tcx : * tcx, map, scope : & wrap_scope } ;
1202
1085
let span = debug_span ! ( "scope" , scope = ?TruncatedScopeDebug ( & this. scope) ) ;
1203
1086
{
1204
1087
let _enter = span. enter ( ) ;
@@ -1303,7 +1186,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
1303
1186
scope = s;
1304
1187
}
1305
1188
1306
- Scope :: Root => {
1189
+ Scope :: Root { opt_parent_item } => {
1190
+ if let Some ( parent_item) = opt_parent_item
1191
+ && let parent_generics = self . tcx . generics_of ( parent_item)
1192
+ && parent_generics. param_def_id_to_index . contains_key ( & region_def_id. to_def_id ( ) )
1193
+ {
1194
+ break Some ( Region :: EarlyBound ( region_def_id. to_def_id ( ) ) ) ;
1195
+ }
1307
1196
break None ;
1308
1197
}
1309
1198
@@ -1417,7 +1306,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
1417
1306
err. emit ( ) ;
1418
1307
return ;
1419
1308
}
1420
- Scope :: Root => break ,
1309
+ Scope :: Root { .. } => break ,
1421
1310
Scope :: Binder { s, .. }
1422
1311
| Scope :: Body { s, .. }
1423
1312
| Scope :: Elision { s, .. }
@@ -1495,7 +1384,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
1495
1384
let mut scope = self . scope ;
1496
1385
loop {
1497
1386
match * scope {
1498
- Scope :: Root => break false ,
1387
+ Scope :: Root { .. } => break false ,
1499
1388
1500
1389
Scope :: Body { .. } => break true ,
1501
1390
@@ -1732,7 +1621,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
1732
1621
scope = s;
1733
1622
}
1734
1623
1735
- Scope :: Root | Scope :: Elision { .. } => break Region :: Static ,
1624
+ Scope :: Root { .. } | Scope :: Elision { .. } => break Region :: Static ,
1736
1625
1737
1626
Scope :: Body { .. } | Scope :: ObjectLifetimeDefault { lifetime : None , .. } => return ,
1738
1627
0 commit comments