15
15
//! used between functions, and they operate in a purely top-down
16
16
//! way. Therefore we break lifetime name resolution into a separate pass.
17
17
18
- pub use self :: DefRegion :: * ;
19
- use self :: ScopeChain :: * ;
20
-
21
18
use dep_graph:: DepNode ;
22
19
use hir:: map:: Map ;
23
20
use session:: Session ;
@@ -36,22 +33,19 @@ use hir;
36
33
use hir:: intravisit:: { self , Visitor , FnKind , NestedVisitorMap } ;
37
34
38
35
#[ derive( Clone , Copy , PartialEq , Eq , Hash , RustcEncodable , RustcDecodable , Debug ) ]
39
- pub enum DefRegion {
40
- DefStaticRegion ,
41
- DefEarlyBoundRegion ( /* index */ u32 ,
42
- /* lifetime decl */ ast:: NodeId ) ,
43
- DefLateBoundRegion ( ty:: DebruijnIndex ,
44
- /* lifetime decl */ ast:: NodeId ) ,
45
- DefFreeRegion ( region:: CallSiteScopeData ,
46
- /* lifetime decl */ ast:: NodeId ) ,
36
+ pub enum Region {
37
+ Static ,
38
+ EarlyBound ( /* index */ u32 , /* lifetime decl */ ast:: NodeId ) ,
39
+ LateBound ( ty:: DebruijnIndex , /* lifetime decl */ ast:: NodeId ) ,
40
+ Free ( region:: CallSiteScopeData , /* lifetime decl */ ast:: NodeId ) ,
47
41
}
48
42
49
43
// Maps the id of each lifetime reference to the lifetime decl
50
44
// that it corresponds to.
51
45
pub struct NamedRegionMap {
52
46
// maps from every use of a named (not anonymous) lifetime to a
53
- // `DefRegion ` describing how that region is bound
54
- pub defs : NodeMap < DefRegion > ,
47
+ // `Region ` describing how that region is bound
48
+ pub defs : NodeMap < Region > ,
55
49
56
50
// the set of lifetime def ids that are late-bound; late-bound ids
57
51
// are named regions appearing in fn arguments that do not appear
@@ -63,7 +57,7 @@ struct LifetimeContext<'a, 'tcx: 'a> {
63
57
sess : & ' a Session ,
64
58
hir_map : & ' a Map < ' tcx > ,
65
59
map : & ' a mut NamedRegionMap ,
66
- scope : Scope < ' a > ,
60
+ scope : ScopeRef < ' a > ,
67
61
// Deep breath. Our representation for poly trait refs contains a single
68
62
// binder and thus we only allow a single level of quantification. However,
69
63
// the syntax of Rust permits quantification in two places, e.g., `T: for <'a> Foo<'a>`
@@ -86,25 +80,36 @@ struct LifetimeContext<'a, 'tcx: 'a> {
86
80
}
87
81
88
82
#[ derive( PartialEq , Debug ) ]
89
- enum ScopeChain < ' a > {
90
- /// EarlyScope(['a, 'b, ...], start, s) extends s with early-bound
91
- /// lifetimes, with consecutive parameter indices from `start`.
92
- /// That is, 'a has index `start`, 'b has index `start + 1`, etc.
83
+ enum Scope < ' a > {
84
+ /// Extends `s` with early-bound `lifetimes`, having consecutive parameter
85
+ /// indices from `start`, i.e. `lifetimes[i]` has index `start + i`.
93
86
/// Indices before `start` correspond to other generic parameters
94
87
/// of a parent item (trait/impl of a method), or `Self` in traits.
95
- EarlyScope ( & ' a [ hir:: LifetimeDef ] , u32 , Scope < ' a > ) ,
96
- /// LateScope(['a, 'b, ...], s) extends s with late-bound
97
- /// lifetimes introduced by the declaration binder_id.
98
- LateScope ( & ' a [ hir:: LifetimeDef ] , Scope < ' a > ) ,
99
-
100
- /// lifetimes introduced by a fn are scoped to the call-site for that fn.
101
- FnScope { fn_id : ast:: NodeId , body_id : ast:: NodeId , s : Scope < ' a > } ,
102
- RootScope
88
+ Early {
89
+ lifetimes : & ' a [ hir:: LifetimeDef ] ,
90
+ start : u32 ,
91
+ s : ScopeRef < ' a >
92
+ } ,
93
+
94
+ /// Extends `s` with late-bound `lifetimes`.
95
+ Late {
96
+ lifetimes : & ' a [ hir:: LifetimeDef ] ,
97
+ s : ScopeRef < ' a >
98
+ } ,
99
+
100
+ /// Lifetimes introduced by a fn are scoped to the call-site for that fn.
101
+ Fn {
102
+ fn_id : ast:: NodeId ,
103
+ body_id : ast:: NodeId ,
104
+ s : ScopeRef < ' a >
105
+ } ,
106
+
107
+ Root
103
108
}
104
109
105
- type Scope < ' a > = & ' a ScopeChain < ' a > ;
110
+ type ScopeRef < ' a > = & ' a Scope < ' a > ;
106
111
107
- static ROOT_SCOPE : ScopeChain < ' static > = RootScope ;
112
+ const ROOT_SCOPE : ScopeRef < ' static > = & Scope :: Root ;
108
113
109
114
pub fn krate ( sess : & Session ,
110
115
hir_map : & Map )
@@ -120,7 +125,7 @@ pub fn krate(sess: &Session,
120
125
sess : sess,
121
126
hir_map : hir_map,
122
127
map : & mut map,
123
- scope : & ROOT_SCOPE ,
128
+ scope : ROOT_SCOPE ,
124
129
trait_ref_hack : false ,
125
130
labels_in_fn : vec ! [ ] ,
126
131
} , krate) ;
@@ -140,7 +145,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
140
145
let saved_labels_in_fn = replace ( & mut self . labels_in_fn , vec ! [ ] ) ;
141
146
142
147
// Items always introduce a new root scope
143
- self . with ( RootScope , |_, this| {
148
+ self . with ( Scope :: Root , |_, this| {
144
149
match item. node {
145
150
hir:: ItemFn ( ..) => {
146
151
// Fn lifetimes get added in visit_fn below:
@@ -169,7 +174,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
169
174
} else {
170
175
0
171
176
} ;
172
- this. with ( EarlyScope ( lifetimes, start, & ROOT_SCOPE ) , |old_scope, this| {
177
+ let early = Scope :: Early {
178
+ lifetimes : lifetimes,
179
+ start : start,
180
+ s : ROOT_SCOPE
181
+ } ;
182
+ this. with ( early, |old_scope, this| {
173
183
this. check_lifetime_defs ( old_scope, lifetimes) ;
174
184
intravisit:: walk_item ( this, item) ;
175
185
} ) ;
@@ -187,7 +197,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
187
197
let saved = replace ( & mut self . labels_in_fn , vec ! [ ] ) ;
188
198
189
199
// Items always introduce a new root scope
190
- self . with ( RootScope , |_, this| {
200
+ self . with ( Scope :: Root , |_, this| {
191
201
match item. node {
192
202
hir:: ForeignItemFn ( ref decl, _, ref generics) => {
193
203
this. visit_early_late ( item. id , decl, generics, |this| {
@@ -233,7 +243,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
233
243
fn visit_ty ( & mut self , ty : & ' tcx hir:: Ty ) {
234
244
match ty. node {
235
245
hir:: TyBareFn ( ref c) => {
236
- self . with ( LateScope ( & c. lifetimes , self . scope ) , |old_scope, this| {
246
+ let late = Scope :: Late {
247
+ lifetimes : & c. lifetimes ,
248
+ s : self . scope
249
+ } ;
250
+ self . with ( late, |old_scope, this| {
237
251
// a bare fn has no bounds, so everything
238
252
// contained within is scoped within its binder.
239
253
this. check_lifetime_defs ( old_scope, & c. lifetimes ) ;
@@ -245,7 +259,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
245
259
// a trait ref, which introduces a binding scope.
246
260
match path. def {
247
261
Def :: Trait ( ..) => {
248
- self . with ( LateScope ( & [ ] , self . scope ) , |_, this| {
262
+ self . with ( Scope :: Late { lifetimes : & [ ] , s : self . scope } , |_, this| {
249
263
this. visit_path ( path, ty. id ) ;
250
264
} ) ;
251
265
}
@@ -283,7 +297,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
283
297
return ;
284
298
}
285
299
if lifetime_ref. name == keywords:: StaticLifetime . name ( ) {
286
- self . insert_lifetime ( lifetime_ref, DefStaticRegion ) ;
300
+ self . insert_lifetime ( lifetime_ref, Region :: Static ) ;
287
301
return ;
288
302
}
289
303
self . resolve_lifetime_ref ( lifetime_ref) ;
@@ -304,8 +318,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
304
318
.. } ) => {
305
319
if !bound_lifetimes. is_empty ( ) {
306
320
self . trait_ref_hack = true ;
307
- let result = self . with ( LateScope ( bound_lifetimes, self . scope ) ,
308
- |old_scope, this| {
321
+ let late = Scope :: Late {
322
+ lifetimes : bound_lifetimes,
323
+ s : self . scope
324
+ } ;
325
+ let result = self . with ( late, |old_scope, this| {
309
326
this. check_lifetime_defs ( old_scope, bound_lifetimes) ;
310
327
this. visit_ty ( & bounded_ty) ;
311
328
walk_list ! ( this, visit_ty_param_bound, bounds) ;
@@ -346,7 +363,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
346
363
span_err ! ( self . sess, trait_ref. span, E0316 ,
347
364
"nested quantification of lifetimes" ) ;
348
365
}
349
- self . with ( LateScope ( & trait_ref. bound_lifetimes , self . scope ) , |old_scope, this| {
366
+ let late = Scope :: Late {
367
+ lifetimes : & trait_ref. bound_lifetimes ,
368
+ s : self . scope
369
+ } ;
370
+ self . with ( late, |old_scope, this| {
350
371
this. check_lifetime_defs ( old_scope, & trait_ref. bound_lifetimes ) ;
351
372
for lifetime in & trait_ref. bound_lifetimes {
352
373
this. visit_lifetime_def ( lifetime) ;
@@ -412,7 +433,7 @@ fn signal_shadowing_problem(sess: &Session, name: ast::Name, orig: Original, sha
412
433
fn extract_labels ( ctxt : & mut LifetimeContext , b : hir:: BodyId ) {
413
434
struct GatherLabels < ' a > {
414
435
sess : & ' a Session ,
415
- scope : Scope < ' a > ,
436
+ scope : ScopeRef < ' a > ,
416
437
labels_in_fn : & ' a mut Vec < ( ast:: Name , Span ) > ,
417
438
}
418
439
@@ -471,16 +492,16 @@ fn extract_labels(ctxt: &mut LifetimeContext, b: hir::BodyId) {
471
492
}
472
493
473
494
fn check_if_label_shadows_lifetime < ' a > ( sess : & ' a Session ,
474
- mut scope : Scope < ' a > ,
495
+ mut scope : ScopeRef < ' a > ,
475
496
label : ast:: Name ,
476
497
label_span : Span ) {
477
498
loop {
478
499
match * scope {
479
- FnScope { s, .. } => { scope = s; }
480
- RootScope => { return ; }
500
+ Scope :: Fn { s, .. } => { scope = s; }
501
+ Scope :: Root => { return ; }
481
502
482
- EarlyScope ( lifetimes, _ , s ) |
483
- LateScope ( lifetimes, s) => {
503
+ Scope :: Early { lifetimes, s , .. } |
504
+ Scope :: Late { lifetimes, s } => {
484
505
for lifetime_def in lifetimes {
485
506
// FIXME (#24278): non-hygienic comparison
486
507
if label == lifetime_def. lifetime . name {
@@ -524,7 +545,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
524
545
// `self.labels_in_fn`.
525
546
extract_labels ( self , fb) ;
526
547
527
- self . with ( FnScope { fn_id : fn_id, body_id : fb. node_id , s : self . scope } ,
548
+ self . with ( Scope :: Fn { fn_id : fn_id, body_id : fb. node_id , s : self . scope } ,
528
549
|_old_scope, this| this. visit_nested_body ( fb) )
529
550
}
530
551
@@ -535,8 +556,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
535
556
f ( self )
536
557
}
537
558
538
- fn with < F > ( & mut self , wrap_scope : ScopeChain , f : F ) where
539
- F : for < ' b > FnOnce ( Scope , & mut LifetimeContext < ' b , ' tcx > ) ,
559
+ fn with < F > ( & mut self , wrap_scope : Scope , f : F ) where
560
+ F : for < ' b > FnOnce ( ScopeRef , & mut LifetimeContext < ' b , ' tcx > ) ,
540
561
{
541
562
let LifetimeContext { sess, hir_map, ref mut map, ..} = * self ;
542
563
let mut this = LifetimeContext {
@@ -591,7 +612,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
591
612
592
613
// Find the start of nested early scopes, e.g. in methods.
593
614
let mut start = 0 ;
594
- if let EarlyScope ( .. ) = * self . scope {
615
+ if let Scope :: Early { .. } = * self . scope {
595
616
let parent = self . hir_map . expect_item ( self . hir_map . get_parent ( fn_id) ) ;
596
617
if let hir:: ItemTrait ( ..) = parent. node {
597
618
start += 1 ; // Self comes first.
@@ -605,8 +626,17 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
605
626
}
606
627
}
607
628
608
- self . with ( EarlyScope ( & early, start as u32 , self . scope ) , move |old_scope, this| {
609
- this. with ( LateScope ( & late, this. scope ) , move |_, this| {
629
+ let early = Scope :: Early {
630
+ lifetimes : & early,
631
+ start : start as u32 ,
632
+ s : self . scope
633
+ } ;
634
+ self . with ( early, move |old_scope, this| {
635
+ let late = Scope :: Late {
636
+ lifetimes : & late,
637
+ s : this. scope
638
+ } ;
639
+ this. with ( late, move |_, this| {
610
640
this. check_lifetime_defs ( old_scope, & generics. lifetimes ) ;
611
641
this. hack ( walk) ; // FIXME(#37666) workaround in place of `walk(this)`
612
642
} ) ;
@@ -624,22 +654,22 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
624
654
let mut scope = self . scope ;
625
655
loop {
626
656
match * scope {
627
- FnScope { fn_id, body_id, s } => {
657
+ Scope :: Fn { fn_id, body_id, s } => {
628
658
return self . resolve_free_lifetime_ref (
629
659
region:: CallSiteScopeData { fn_id : fn_id, body_id : body_id } ,
630
660
lifetime_ref,
631
661
s) ;
632
662
}
633
663
634
- RootScope => {
664
+ Scope :: Root => {
635
665
break ;
636
666
}
637
667
638
- EarlyScope ( lifetimes, start, s) => {
668
+ Scope :: Early { lifetimes, start, s } => {
639
669
match search_lifetimes ( lifetimes, lifetime_ref) {
640
670
Some ( ( index, lifetime_def) ) => {
641
671
let decl_id = lifetime_def. id ;
642
- let def = DefEarlyBoundRegion ( start + index, decl_id) ;
672
+ let def = Region :: EarlyBound ( start + index, decl_id) ;
643
673
self . insert_lifetime ( lifetime_ref, def) ;
644
674
return ;
645
675
}
@@ -649,12 +679,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
649
679
}
650
680
}
651
681
652
- LateScope ( lifetimes, s) => {
682
+ Scope :: Late { lifetimes, s } => {
653
683
match search_lifetimes ( lifetimes, lifetime_ref) {
654
684
Some ( ( _index, lifetime_def) ) => {
655
685
let decl_id = lifetime_def. id ;
656
686
let debruijn = ty:: DebruijnIndex :: new ( late_depth + 1 ) ;
657
- let def = DefLateBoundRegion ( debruijn, decl_id) ;
687
+ let def = Region :: LateBound ( debruijn, decl_id) ;
658
688
self . insert_lifetime ( lifetime_ref, def) ;
659
689
return ;
660
690
}
@@ -674,7 +704,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
674
704
fn resolve_free_lifetime_ref ( & mut self ,
675
705
scope_data : region:: CallSiteScopeData ,
676
706
lifetime_ref : & hir:: Lifetime ,
677
- scope : Scope ) {
707
+ scope : ScopeRef ) {
678
708
debug ! ( "resolve_free_lifetime_ref \
679
709
scope_data: {:?} lifetime_ref: {:?} scope: {:?}",
680
710
scope_data, lifetime_ref, scope) ;
@@ -690,19 +720,19 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
690
720
scope_data: {:?} scope: {:?} search_result: {:?}",
691
721
scope_data, scope, search_result) ;
692
722
match * scope {
693
- FnScope { fn_id, body_id, s } => {
723
+ Scope :: Fn { fn_id, body_id, s } => {
694
724
scope_data = region:: CallSiteScopeData {
695
725
fn_id : fn_id, body_id : body_id
696
726
} ;
697
727
scope = s;
698
728
}
699
729
700
- RootScope => {
730
+ Scope :: Root => {
701
731
break ;
702
732
}
703
733
704
- EarlyScope ( lifetimes, _ , s ) |
705
- LateScope ( lifetimes, s) => {
734
+ Scope :: Early { lifetimes, s , .. } |
735
+ Scope :: Late { lifetimes, s } => {
706
736
search_result = search_lifetimes ( lifetimes, lifetime_ref) ;
707
737
if search_result. is_some ( ) {
708
738
break ;
@@ -714,7 +744,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
714
744
715
745
match search_result {
716
746
Some ( ( _depth, lifetime) ) => {
717
- let def = DefFreeRegion ( scope_data, lifetime. id ) ;
747
+ let def = Region :: Free ( scope_data, lifetime. id ) ;
718
748
self . insert_lifetime ( lifetime_ref, def) ;
719
749
}
720
750
@@ -732,7 +762,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
732
762
. emit ( ) ;
733
763
}
734
764
735
- fn check_lifetime_defs ( & mut self , old_scope : Scope , lifetimes : & [ hir:: LifetimeDef ] ) {
765
+ fn check_lifetime_defs ( & mut self , old_scope : ScopeRef , lifetimes : & [ hir:: LifetimeDef ] ) {
736
766
for i in 0 ..lifetimes. len ( ) {
737
767
let lifetime_i = & lifetimes[ i] ;
738
768
@@ -773,7 +803,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
773
803
}
774
804
775
805
fn check_lifetime_def_for_shadowing ( & self ,
776
- mut old_scope : Scope ,
806
+ mut old_scope : ScopeRef ,
777
807
lifetime : & hir:: Lifetime )
778
808
{
779
809
for & ( label, label_span) in & self . labels_in_fn {
@@ -789,16 +819,16 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
789
819
790
820
loop {
791
821
match * old_scope {
792
- FnScope { s, .. } => {
822
+ Scope :: Fn { s, .. } => {
793
823
old_scope = s;
794
824
}
795
825
796
- RootScope => {
826
+ Scope :: Root => {
797
827
return ;
798
828
}
799
829
800
- EarlyScope ( lifetimes, _ , s ) |
801
- LateScope ( lifetimes, s) => {
830
+ Scope :: Early { lifetimes, s , .. } |
831
+ Scope :: Late { lifetimes, s } => {
802
832
if let Some ( ( _, lifetime_def) ) = search_lifetimes ( lifetimes, lifetime) {
803
833
signal_shadowing_problem (
804
834
self . sess ,
@@ -816,7 +846,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
816
846
817
847
fn insert_lifetime ( & mut self ,
818
848
lifetime_ref : & hir:: Lifetime ,
819
- def : DefRegion ) {
849
+ def : Region ) {
820
850
if lifetime_ref. id == ast:: DUMMY_NODE_ID {
821
851
span_bug ! ( lifetime_ref. span,
822
852
"lifetime reference not renumbered, \
0 commit comments