19
19
20
20
use driver:: session:: Session ;
21
21
use middle:: subst;
22
+ use std:: fmt;
22
23
use syntax:: ast;
23
24
use syntax:: codemap:: Span ;
24
25
use syntax:: owned_slice:: OwnedSlice ;
@@ -46,18 +47,12 @@ pub enum DefRegion {
46
47
// that it corresponds to
47
48
pub type NamedRegionMap = NodeMap < DefRegion > ;
48
49
49
- // Returns an instance of some type that implements std::fmt::Show
50
- fn lifetime_show ( lt_name : & ast:: Name ) -> token:: InternedString {
51
- token:: get_name ( * lt_name)
52
- }
53
-
54
50
struct LifetimeContext < ' a > {
55
51
sess : & ' a Session ,
56
52
named_region_map : & ' a mut NamedRegionMap ,
57
53
scope : Scope < ' a >
58
54
}
59
55
60
- #[ deriving( Show ) ]
61
56
enum ScopeChain < ' a > {
62
57
/// EarlyScope(i, ['a, 'b, ...], s) extends s with early-bound
63
58
/// lifetimes, assigning indexes 'a => i, 'b => i+1, ... etc.
@@ -88,50 +83,42 @@ pub fn krate(sess: &Session, krate: &ast::Crate) -> NamedRegionMap {
88
83
89
84
impl < ' a , ' v > Visitor < ' v > for LifetimeContext < ' a > {
90
85
fn visit_item ( & mut self , item : & ast:: Item ) {
91
- let lifetimes = match item. node {
92
- ast:: ItemFn ( ..) | // fn lifetimes get added in visit_fn below
86
+ match item. node {
87
+ ast:: ItemFn ( ..) => {
88
+ // Fn lifetimes get added in visit_fn below:
89
+ self . with ( RootScope , |this| visit:: walk_item ( this, item) ) ;
90
+ }
93
91
ast:: ItemMod ( ..) |
94
92
ast:: ItemMac ( ..) |
95
93
ast:: ItemForeignMod ( ..) |
96
- ast:: ItemStatic ( ..) | ast:: ItemConst ( ..) => {
97
- self . with ( |_, f| f ( RootScope ) , |v| visit:: walk_item ( v, item) ) ;
98
- return ;
94
+ ast:: ItemStatic ( ..) |
95
+ ast:: ItemConst ( ..) => {
96
+ // These sorts of items have no lifetime parameters at all.
97
+ self . with ( RootScope , |this| visit:: walk_item ( this, item) ) ;
99
98
}
100
99
ast:: ItemTy ( _, ref generics) |
101
100
ast:: ItemEnum ( _, ref generics) |
102
101
ast:: ItemStruct ( _, ref generics) |
103
- ast:: ItemTrait ( ref generics, _, _, _) => {
104
- self . with ( |scope, f| {
105
- f ( EarlyScope ( subst:: TypeSpace ,
106
- & generics. lifetimes ,
107
- scope) )
108
- } , |v| v. check_lifetime_defs ( & generics. lifetimes ) ) ;
109
- & generics. lifetimes
110
- }
102
+ ast:: ItemTrait ( ref generics, _, _, _) |
111
103
ast:: ItemImpl ( ref generics, _, _, _) => {
112
- self . with ( |scope , f| {
113
- f ( EarlyScope ( subst :: TypeSpace ,
114
- & generics . lifetimes ,
115
- scope ) )
116
- } , |v| v . check_lifetime_defs ( & generics . lifetimes ) ) ;
117
- & generics . lifetimes
104
+ // These kinds of items have only early bound lifetime parameters.
105
+ let lifetimes = & generics . lifetimes ;
106
+ self . with ( EarlyScope ( subst :: TypeSpace , lifetimes , & ROOT_SCOPE ) , |this| {
107
+ this . check_lifetime_defs ( lifetimes ) ;
108
+ visit :: walk_item ( this , item ) ;
109
+ } ) ;
118
110
}
119
- } ;
120
-
121
- self . with ( |_, f| f ( EarlyScope ( subst:: TypeSpace , lifetimes, & ROOT_SCOPE ) ) , |v| {
122
- debug ! ( "entering scope {}" , v. scope) ;
123
- v. check_lifetime_defs ( lifetimes) ;
124
- visit:: walk_item ( v, item) ;
125
- debug ! ( "exiting scope {}" , v. scope) ;
126
- } ) ;
111
+ }
127
112
}
128
113
129
114
fn visit_fn ( & mut self , fk : visit:: FnKind < ' v > , fd : & ' v ast:: FnDecl ,
130
115
b : & ' v ast:: Block , s : Span , n : ast:: NodeId ) {
131
116
match fk {
132
117
visit:: FkItemFn ( _, generics, _, _) |
133
118
visit:: FkMethod ( _, generics, _) => {
134
- self . visit_fn_decl ( n, generics, |v| visit:: walk_fn ( v, fk, fd, b, s) )
119
+ self . visit_early_late (
120
+ subst:: FnSpace , n, generics,
121
+ |this| visit:: walk_fn ( this, fk, fd, b, s) )
135
122
}
136
123
visit:: FkFnBlock ( ..) => {
137
124
visit:: walk_fn ( self , fk, fd, b, s)
@@ -146,22 +133,20 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
146
133
_ => return visit:: walk_ty ( self , ty)
147
134
} ;
148
135
149
- self . with ( |scope, f| f ( LateScope ( ty. id , lifetimes, scope) ) , |v| {
150
- v. check_lifetime_defs ( lifetimes) ;
151
- debug ! ( "pushing fn scope id={} due to type" , ty. id) ;
152
- visit:: walk_ty ( v, ty) ;
153
- debug ! ( "popping fn scope id={} due to type" , ty. id) ;
136
+ self . with ( LateScope ( ty. id , lifetimes, self . scope ) , |this| {
137
+ this. check_lifetime_defs ( lifetimes) ;
138
+ visit:: walk_ty ( this, ty) ;
154
139
} ) ;
155
140
}
156
141
157
142
fn visit_ty_method ( & mut self , m : & ast:: TypeMethod ) {
158
- self . visit_fn_decl ( m. id , & m. generics , |v| visit:: walk_ty_method ( v, m) )
143
+ self . visit_early_late (
144
+ subst:: FnSpace , m. id , & m. generics ,
145
+ |this| visit:: walk_ty_method ( this, m) )
159
146
}
160
147
161
148
fn visit_block ( & mut self , b : & ast:: Block ) {
162
- debug ! ( "pushing block scope {}" , b. id) ;
163
- self . with ( |scope, f| f ( BlockScope ( b. id , scope) ) , |v| visit:: walk_block ( v, b) ) ;
164
- debug ! ( "popping block scope {}" , b. id) ;
149
+ self . with ( BlockScope ( b. id , self . scope ) , |this| visit:: walk_block ( this, b) ) ;
165
150
}
166
151
167
152
fn visit_lifetime_ref ( & mut self , lifetime_ref : & ast:: Lifetime ) {
@@ -188,21 +173,24 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
188
173
}
189
174
190
175
impl < ' a > LifetimeContext < ' a > {
191
- fn with ( & mut self , wrap_scope : | Scope , | ScopeChain || , f: |& mut LifetimeContext |) {
192
- let LifetimeContext { sess, ref mut named_region_map, scope } = * self ;
193
- wrap_scope ( scope , |scope1| f ( & mut LifetimeContext {
176
+ fn with ( & mut self , wrap_scope : ScopeChain , f: |& mut LifetimeContext |) {
177
+ let LifetimeContext { sess, ref mut named_region_map, .. } = * self ;
178
+ let mut this = LifetimeContext {
194
179
sess : sess,
195
180
named_region_map : * named_region_map,
196
- scope : & scope1
197
- } ) )
181
+ scope : & wrap_scope
182
+ } ;
183
+ debug ! ( "entering scope {}" , this. scope) ;
184
+ f ( & mut this) ;
185
+ debug ! ( "exiting scope {}" , this. scope) ;
198
186
}
199
187
200
188
fn visit_ty_param_bounds ( & mut self ,
201
189
bounds : & OwnedSlice < ast:: TyParamBound > ) {
202
190
for bound in bounds. iter ( ) {
203
191
match * bound {
204
192
ast:: TraitTyParamBound ( ref trait_ref) => {
205
- self . visit_trait_ref ( trait_ref) ;
193
+ self . visit_poly_trait_ref ( trait_ref) ;
206
194
}
207
195
ast:: RegionTyParamBound ( ref lifetime) => {
208
196
self . visit_lifetime_ref ( lifetime) ;
@@ -211,23 +199,27 @@ impl<'a> LifetimeContext<'a> {
211
199
}
212
200
}
213
201
214
- fn visit_trait_ref ( & mut self , trait_ref : & ast:: TraitRef ) {
215
- self . with ( |scope, f| {
216
- f ( LateScope ( trait_ref. ref_id , & trait_ref. lifetimes , scope) )
217
- } , |v| {
218
- v. check_lifetime_defs ( & trait_ref. lifetimes ) ;
219
- for lifetime in trait_ref. lifetimes . iter ( ) {
220
- v. visit_lifetime_decl ( lifetime) ;
202
+ fn visit_poly_trait_ref ( & mut self , trait_ref : & ast:: PolyTraitRef ) {
203
+ let ref_id = trait_ref. trait_ref . ref_id ;
204
+ self . with ( LateScope ( ref_id, & trait_ref. bound_lifetimes , self . scope ) , |this| {
205
+ this. check_lifetime_defs ( & trait_ref. bound_lifetimes ) ;
206
+ for lifetime in trait_ref. bound_lifetimes . iter ( ) {
207
+ this. visit_lifetime_decl ( lifetime) ;
221
208
}
222
- v . visit_path ( & trait_ref. path , trait_ref. ref_id ) ;
209
+ this . visit_trait_ref ( & trait_ref. trait_ref )
223
210
} )
224
211
}
225
212
213
+ fn visit_trait_ref ( & mut self , trait_ref : & ast:: TraitRef ) {
214
+ self . visit_path ( & trait_ref. path , trait_ref. ref_id ) ;
215
+ }
216
+
226
217
/// Visits self by adding a scope and handling recursive walk over the contents with `walk`.
227
- fn visit_fn_decl ( & mut self ,
228
- n : ast:: NodeId ,
229
- generics : & ast:: Generics ,
230
- walk: |& mut LifetimeContext |) {
218
+ fn visit_early_late ( & mut self ,
219
+ early_space : subst:: ParamSpace ,
220
+ binder_id : ast:: NodeId ,
221
+ generics : & ast:: Generics ,
222
+ walk: |& mut LifetimeContext |) {
231
223
/*!
232
224
* Handles visiting fns and methods. These are a bit
233
225
* complicated because we must distinguish early- vs late-bound
@@ -248,33 +240,25 @@ impl<'a> LifetimeContext<'a> {
248
240
* numbered sequentially, starting from the lowest index that
249
241
* is already in scope (for a fn item, that will be 0, but for
250
242
* a method it might not be). Late bound lifetimes are
251
- * resolved by name and associated with a binder id (`n `), so
243
+ * resolved by name and associated with a binder id (`binder_id `), so
252
244
* the ordering is not important there.
253
245
*/
254
246
255
247
let referenced_idents = early_bound_lifetime_names ( generics) ;
256
- debug ! ( "pushing fn scope id={} due to fn item/method\
257
- referenced_idents={}",
258
- n,
259
- referenced_idents. iter( ) . map( lifetime_show) . collect:: <Vec <token:: InternedString >>( ) ) ;
260
- let lifetimes = & generics. lifetimes ;
261
- if referenced_idents. is_empty ( ) {
262
- self . with ( |scope, f| f ( LateScope ( n, lifetimes, scope) ) , |v| {
263
- v. check_lifetime_defs ( lifetimes) ;
264
- walk ( v) ;
265
- } ) ;
266
- } else {
267
- let ( early, late) = lifetimes. clone ( ) . partition (
268
- |l| referenced_idents. iter ( ) . any ( |& i| i == l. lifetime . name ) ) ;
269
-
270
- self . with ( |scope, f| f ( EarlyScope ( subst:: FnSpace , & early, scope) ) , |v| {
271
- v. with ( |scope1, f| f ( LateScope ( n, & late, scope1) ) , |v| {
272
- v. check_lifetime_defs ( lifetimes) ;
273
- walk ( v) ;
274
- } ) ;
248
+
249
+ debug ! ( "visit_early_late: binder_id={} referenced_idents={}" ,
250
+ binder_id,
251
+ referenced_idents) ;
252
+
253
+ let ( early, late) = generics. lifetimes . clone ( ) . partition (
254
+ |l| referenced_idents. iter ( ) . any ( |& i| i == l. lifetime . name ) ) ;
255
+
256
+ self . with ( EarlyScope ( early_space, & early, self . scope ) , |this| {
257
+ this. with ( LateScope ( binder_id, & late, this. scope ) , |this| {
258
+ this. check_lifetime_defs ( & generics. lifetimes ) ;
259
+ walk ( this) ;
275
260
} ) ;
276
- }
277
- debug ! ( "popping fn scope id={} due to fn item/method" , n) ;
261
+ } ) ;
278
262
}
279
263
280
264
fn resolve_lifetime_ref ( & mut self , lifetime_ref : & ast:: Lifetime ) {
@@ -525,3 +509,14 @@ fn early_bound_lifetime_names(generics: &ast::Generics) -> Vec<ast::Name> {
525
509
}
526
510
}
527
511
}
512
+
513
+ impl < ' a > fmt:: Show for ScopeChain < ' a > {
514
+ fn fmt ( & self , fmt : & mut fmt:: Formatter ) -> fmt:: Result {
515
+ match * self {
516
+ EarlyScope ( space, defs, _) => write ! ( fmt, "EarlyScope({}, {})" , space, defs) ,
517
+ LateScope ( id, defs, _) => write ! ( fmt, "LateScope({}, {})" , id, defs) ,
518
+ BlockScope ( id, _) => write ! ( fmt, "BlockScope({})" , id) ,
519
+ RootScope => write ! ( fmt, "RootScope" ) ,
520
+ }
521
+ }
522
+ }
0 commit comments