@@ -24,7 +24,6 @@ use middle::region;
24
24
use middle:: subst;
25
25
use middle:: ty;
26
26
use std:: fmt;
27
- use std:: mem:: replace;
28
27
use syntax:: ast;
29
28
use syntax:: codemap:: Span ;
30
29
use syntax:: parse:: token:: special_idents;
@@ -71,9 +70,6 @@ struct LifetimeContext<'a> {
71
70
72
71
// I'm sorry.
73
72
trait_ref_hack : bool ,
74
-
75
- // List of labels in the function/method currently under analysis.
76
- labels_in_fn : Vec < ( ast:: Ident , Span ) > ,
77
73
}
78
74
79
75
enum ScopeChain < ' a > {
@@ -101,18 +97,13 @@ pub fn krate(sess: &Session, krate: &ast::Crate, def_map: &DefMap) -> NamedRegio
101
97
scope : & ROOT_SCOPE ,
102
98
def_map : def_map,
103
99
trait_ref_hack : false ,
104
- labels_in_fn : vec ! [ ] ,
105
100
} , krate) ;
106
101
sess. abort_if_errors ( ) ;
107
102
named_region_map
108
103
}
109
104
110
105
impl < ' a , ' v > Visitor < ' v > for LifetimeContext < ' a > {
111
106
fn visit_item ( & mut self , item : & ast:: Item ) {
112
- // Items save/restore the set of labels. This way innner items
113
- // can freely reuse names, be they loop labels or lifetimes.
114
- let saved = replace ( & mut self . labels_in_fn , vec ! [ ] ) ;
115
-
116
107
// Items always introduce a new root scope
117
108
self . with ( RootScope , |_, this| {
118
109
match item. node {
@@ -146,26 +137,23 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
146
137
}
147
138
}
148
139
} ) ;
149
-
150
- // Done traversing the item; restore saved set of labels.
151
- replace ( & mut self . labels_in_fn , saved) ;
152
140
}
153
141
154
142
fn visit_fn ( & mut self , fk : visit:: FnKind < ' v > , fd : & ' v ast:: FnDecl ,
155
143
b : & ' v ast:: Block , s : Span , _: ast:: NodeId ) {
156
144
match fk {
157
145
visit:: FkItemFn ( _, generics, _, _, _) => {
158
146
self . visit_early_late ( subst:: FnSpace , generics, |this| {
159
- this . walk_fn ( fk, fd, b, s)
147
+ visit :: walk_fn ( this , fk, fd, b, s)
160
148
} )
161
149
}
162
150
visit:: FkMethod ( _, sig, _) => {
163
151
self . visit_early_late ( subst:: FnSpace , & sig. generics , |this| {
164
- this . walk_fn ( fk, fd, b, s)
152
+ visit :: walk_fn ( this , fk, fd, b, s)
165
153
} )
166
154
}
167
155
visit:: FkFnBlock ( ..) => {
168
- self . walk_fn ( fk, fd, b, s)
156
+ visit :: walk_fn ( self , fk, fd, b, s)
169
157
}
170
158
}
171
159
}
@@ -202,19 +190,13 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
202
190
}
203
191
204
192
fn visit_trait_item ( & mut self , trait_item : & ast:: TraitItem ) {
205
- // We reset the labels on every trait item, so that different
206
- // methods in an impl can reuse label names.
207
- let saved = replace ( & mut self . labels_in_fn , vec ! [ ] ) ;
208
-
209
193
if let ast:: MethodTraitItem ( ref sig, None ) = trait_item. node {
210
194
self . visit_early_late (
211
195
subst:: FnSpace , & sig. generics ,
212
196
|this| visit:: walk_trait_item ( this, trait_item) )
213
197
} else {
214
198
visit:: walk_trait_item ( self , trait_item) ;
215
199
}
216
-
217
- replace ( & mut self . labels_in_fn , saved) ;
218
200
}
219
201
220
202
fn visit_block ( & mut self , b : & ast:: Block ) {
@@ -304,170 +286,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
304
286
}
305
287
}
306
288
307
- #[ derive( Copy , Clone , PartialEq ) ]
308
- enum ShadowKind { Label , Lifetime }
309
- struct Original { kind : ShadowKind , span : Span }
310
- struct Shadower { kind : ShadowKind , span : Span }
311
-
312
- fn original_label ( span : Span ) -> Original {
313
- Original { kind : ShadowKind :: Label , span : span }
314
- }
315
- fn shadower_label ( span : Span ) -> Shadower {
316
- Shadower { kind : ShadowKind :: Label , span : span }
317
- }
318
- fn original_lifetime ( l : & ast:: Lifetime ) -> Original {
319
- Original { kind : ShadowKind :: Lifetime , span : l. span }
320
- }
321
- fn shadower_lifetime ( l : & ast:: Lifetime ) -> Shadower {
322
- Shadower { kind : ShadowKind :: Lifetime , span : l. span }
323
- }
324
-
325
- impl ShadowKind {
326
- fn desc ( & self ) -> & ' static str {
327
- match * self {
328
- ShadowKind :: Label => "label" ,
329
- ShadowKind :: Lifetime => "lifetime" ,
330
- }
331
- }
332
- }
333
-
334
- fn signal_shadowing_problem (
335
- sess : & Session , name : ast:: Name , orig : Original , shadower : Shadower ) {
336
- if let ( ShadowKind :: Lifetime , ShadowKind :: Lifetime ) = ( orig. kind , shadower. kind ) {
337
- // lifetime/lifetime shadowing is an error
338
- sess. span_err ( shadower. span ,
339
- & format ! ( "{} name `{}` shadows a \
340
- {} name that is already in scope",
341
- shadower. kind. desc( ) , name, orig. kind. desc( ) ) ) ;
342
- } else {
343
- // shadowing involving a label is only a warning, due to issues with
344
- // labels and lifetimes not being macro-hygienic.
345
- sess. span_warn ( shadower. span ,
346
- & format ! ( "{} name `{}` shadows a \
347
- {} name that is already in scope",
348
- shadower. kind. desc( ) , name, orig. kind. desc( ) ) ) ;
349
- }
350
- sess. span_note ( orig. span ,
351
- & format ! ( "shadowed {} `{}` declared here" ,
352
- orig. kind. desc( ) , name) ) ;
353
- }
354
-
355
- // Adds all labels in `b` to `ctxt.labels_in_fn`, signalling a warning
356
- // if one of the label shadows a lifetime or another label.
357
- fn extract_labels < ' v , ' a > ( ctxt : & mut LifetimeContext < ' a > , b : & ' v ast:: Block ) {
358
-
359
- struct GatherLabels < ' a > {
360
- sess : & ' a Session ,
361
- scope : Scope < ' a > ,
362
- labels_in_fn : & ' a mut Vec < ( ast:: Ident , Span ) > ,
363
- }
364
-
365
- let mut gather = GatherLabels {
366
- sess : ctxt. sess ,
367
- scope : ctxt. scope ,
368
- labels_in_fn : & mut ctxt. labels_in_fn ,
369
- } ;
370
- gather. visit_block ( b) ;
371
- return ;
372
-
373
- impl < ' v , ' a > Visitor < ' v > for GatherLabels < ' a > {
374
- fn visit_expr ( & mut self , ex : & ' v ast:: Expr ) {
375
- if let Some ( label) = expression_label ( ex) {
376
- for & ( prior, prior_span) in & self . labels_in_fn [ ..] {
377
- // FIXME (#24278): non-hygienic comparision
378
- if label. name == prior. name {
379
- signal_shadowing_problem ( self . sess ,
380
- label. name ,
381
- original_label ( prior_span) ,
382
- shadower_label ( ex. span ) ) ;
383
- }
384
- }
385
-
386
- check_if_label_shadows_lifetime ( self . sess ,
387
- self . scope ,
388
- label,
389
- ex. span ) ;
390
-
391
- self . labels_in_fn . push ( ( label, ex. span ) ) ;
392
- }
393
- visit:: walk_expr ( self , ex)
394
- }
395
-
396
- fn visit_item ( & mut self , _: & ast:: Item ) {
397
- // do not recurse into items defined in the block
398
- }
399
- }
400
-
401
- fn expression_label ( ex : & ast:: Expr ) -> Option < ast:: Ident > {
402
- match ex. node {
403
- ast:: ExprWhile ( _, _, Some ( label) ) |
404
- ast:: ExprWhileLet ( _, _, _, Some ( label) ) |
405
- ast:: ExprForLoop ( _, _, _, Some ( label) ) |
406
- ast:: ExprLoop ( _, Some ( label) ) => Some ( label) ,
407
- _ => None ,
408
- }
409
- }
410
-
411
- fn check_if_label_shadows_lifetime < ' a > ( sess : & ' a Session ,
412
- mut scope : Scope < ' a > ,
413
- label : ast:: Ident ,
414
- label_span : Span ) {
415
- loop {
416
- match * scope {
417
- BlockScope ( _, s) => { scope = s; }
418
- RootScope => { return ; }
419
-
420
- EarlyScope ( _, lifetimes, s) |
421
- LateScope ( lifetimes, s) => {
422
- for lifetime_def in lifetimes {
423
- // FIXME (#24278): non-hygienic comparision
424
- if label. name == lifetime_def. lifetime . name {
425
- signal_shadowing_problem (
426
- sess,
427
- label. name ,
428
- original_lifetime ( & lifetime_def. lifetime ) ,
429
- shadower_label ( label_span) ) ;
430
- return ;
431
- }
432
- }
433
- scope = s;
434
- }
435
- }
436
- }
437
- }
438
- }
439
-
440
289
impl < ' a > LifetimeContext < ' a > {
441
- // This is just like visit::walk_fn, except that it extracts the
442
- // labels of the function body and swaps them in before visiting
443
- // the function body itself.
444
- fn walk_fn < ' b > ( & mut self ,
445
- fk : visit:: FnKind ,
446
- fd : & ast:: FnDecl ,
447
- fb : & ' b ast:: Block ,
448
- _span : Span ) {
449
- match fk {
450
- visit:: FkItemFn ( _, generics, _, _, _) => {
451
- visit:: walk_fn_decl ( self , fd) ;
452
- self . visit_generics ( generics) ;
453
- }
454
- visit:: FkMethod ( _, sig, _) => {
455
- visit:: walk_fn_decl ( self , fd) ;
456
- self . visit_generics ( & sig. generics ) ;
457
- self . visit_explicit_self ( & sig. explicit_self ) ;
458
- }
459
- visit:: FkFnBlock ( ..) => {
460
- visit:: walk_fn_decl ( self , fd) ;
461
- }
462
- }
463
-
464
- // After inpsecting the decl, add all labels from the body to
465
- // `self.labels_in_fn`.
466
- extract_labels ( self , fb) ;
467
-
468
- self . visit_block ( fb) ;
469
- }
470
-
471
290
fn with < F > ( & mut self , wrap_scope : ScopeChain , f : F ) where
472
291
F : FnOnce ( Scope , & mut LifetimeContext ) ,
473
292
{
@@ -478,7 +297,6 @@ impl<'a> LifetimeContext<'a> {
478
297
scope : & wrap_scope,
479
298
def_map : self . def_map ,
480
299
trait_ref_hack : self . trait_ref_hack ,
481
- labels_in_fn : self . labels_in_fn . clone ( ) ,
482
300
} ;
483
301
debug ! ( "entering scope {:?}" , this. scope) ;
484
302
f ( self . scope , & mut this) ;
@@ -676,17 +494,6 @@ impl<'a> LifetimeContext<'a> {
676
494
mut old_scope : Scope ,
677
495
lifetime : & ast:: Lifetime )
678
496
{
679
- for & ( label, label_span) in & self . labels_in_fn {
680
- // FIXME (#24278): non-hygienic comparision
681
- if lifetime. name == label. name {
682
- signal_shadowing_problem ( self . sess ,
683
- lifetime. name ,
684
- original_label ( label_span) ,
685
- shadower_lifetime ( & lifetime) ) ;
686
- return ;
687
- }
688
- }
689
-
690
497
loop {
691
498
match * old_scope {
692
499
BlockScope ( _, s) => {
@@ -700,11 +507,15 @@ impl<'a> LifetimeContext<'a> {
700
507
EarlyScope ( _, lifetimes, s) |
701
508
LateScope ( lifetimes, s) => {
702
509
if let Some ( ( _, lifetime_def) ) = search_lifetimes ( lifetimes, lifetime) {
703
- signal_shadowing_problem (
704
- self . sess ,
705
- lifetime. name ,
706
- original_lifetime ( & lifetime_def) ,
707
- shadower_lifetime ( & lifetime) ) ;
510
+ self . sess . span_err (
511
+ lifetime. span ,
512
+ & format ! ( "lifetime name `{}` shadows another \
513
+ lifetime name that is already in scope",
514
+ token:: get_name( lifetime. name) ) ) ;
515
+ self . sess . span_note (
516
+ lifetime_def. span ,
517
+ & format ! ( "shadowed lifetime `{}` declared here" ,
518
+ token:: get_name( lifetime. name) ) ) ;
708
519
return ;
709
520
}
710
521
0 commit comments