13
13
// from live codes are live, and everything else is dead.
14
14
15
15
use middle:: def;
16
- use lint ;
16
+ use middle :: pat_util ;
17
17
use middle:: privacy;
18
18
use middle:: ty;
19
19
use middle:: typeck;
20
+ use lint;
20
21
use util:: nodemap:: NodeSet ;
21
22
22
23
use std:: collections:: HashSet ;
23
24
use syntax:: ast;
24
25
use syntax:: ast_map;
25
26
use syntax:: ast_util:: { local_def, is_local, PostExpansionMethod } ;
26
- use syntax:: attr:: AttrMetaMethods ;
27
- use syntax:: attr;
27
+ use syntax:: attr:: { mod, AttrMetaMethods } ;
28
28
use syntax:: codemap;
29
- use syntax:: visit:: Visitor ;
30
- use syntax:: visit;
29
+ use syntax:: visit:: { mod, Visitor } ;
31
30
32
31
// Any local node that may call something in its body block should be
33
32
// explored. For example, if it's a live NodeItem that is a
@@ -51,7 +50,8 @@ struct MarkSymbolVisitor<'a, 'tcx: 'a> {
51
50
worklist : Vec < ast:: NodeId > ,
52
51
tcx : & ' a ty:: ctxt < ' tcx > ,
53
52
live_symbols : Box < HashSet < ast:: NodeId > > ,
54
- struct_has_extern_repr : bool
53
+ struct_has_extern_repr : bool ,
54
+ ignore_paths : bool
55
55
}
56
56
57
57
impl < ' a , ' tcx > MarkSymbolVisitor < ' a , ' tcx > {
@@ -61,7 +61,8 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
61
61
worklist : worklist,
62
62
tcx : tcx,
63
63
live_symbols : box HashSet :: new ( ) ,
64
- struct_has_extern_repr : false
64
+ struct_has_extern_repr : false ,
65
+ ignore_paths : false
65
66
}
66
67
}
67
68
@@ -73,19 +74,18 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
73
74
}
74
75
75
76
fn lookup_and_handle_definition ( & mut self , id : & ast:: NodeId ) {
76
- let def = match self . tcx . def_map . borrow ( ) . find ( id) {
77
- Some ( & def) => def,
78
- None => return
79
- } ;
80
- let def_id = match def {
81
- def:: DefVariant ( enum_id, _, _) => Some ( enum_id) ,
82
- def:: DefPrimTy ( _) => None ,
83
- _ => Some ( def. def_id ( ) )
84
- } ;
85
- match def_id {
86
- Some ( def_id) => self . check_def_id ( def_id) ,
87
- None => ( ) ,
88
- }
77
+ self . tcx . def_map . borrow ( ) . find ( id) . map ( |def| {
78
+ match def {
79
+ & def:: DefPrimTy ( _) => ( ) ,
80
+ & def:: DefVariant ( enum_id, variant_id, _) => {
81
+ self . check_def_id ( enum_id) ;
82
+ self . check_def_id ( variant_id) ;
83
+ }
84
+ _ => {
85
+ self . check_def_id ( def. def_id ( ) ) ;
86
+ }
87
+ }
88
+ } ) ;
89
89
}
90
90
91
91
fn lookup_and_handle_method ( & mut self , id : ast:: NodeId ,
@@ -275,22 +275,27 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> {
275
275
}
276
276
277
277
fn visit_pat ( & mut self , pat : & ast:: Pat ) {
278
+ let def_map = & self . tcx . def_map ;
278
279
match pat. node {
279
280
ast:: PatStruct ( _, ref fields, _) => {
280
281
self . handle_field_pattern_match ( pat, fields. as_slice ( ) ) ;
281
282
}
282
- ast :: PatIdent ( _ , _ , _ ) => {
283
+ _ if pat_util :: pat_is_const ( def_map , pat ) => {
283
284
// it might be the only use of a static:
284
285
self . lookup_and_handle_definition ( & pat. id )
285
286
}
286
287
_ => ( )
287
288
}
288
289
290
+ self . ignore_paths = true ;
289
291
visit:: walk_pat ( self , pat) ;
292
+ self . ignore_paths = false ;
290
293
}
291
294
292
295
fn visit_path ( & mut self , path : & ast:: Path , id : ast:: NodeId ) {
293
- self . lookup_and_handle_definition ( & id) ;
296
+ if !self . ignore_paths {
297
+ self . lookup_and_handle_definition ( & id) ;
298
+ }
294
299
visit:: walk_path ( self , path) ;
295
300
}
296
301
@@ -330,15 +335,19 @@ fn has_allow_dead_code_or_lang_attr(attrs: &[ast::Attribute]) -> bool {
330
335
// 2) We are not sure to be live or not
331
336
// * Implementation of a trait method
332
337
struct LifeSeeder {
333
- worklist : Vec < ast:: NodeId > ,
338
+ worklist : Vec < ast:: NodeId >
334
339
}
335
340
336
341
impl < ' v > Visitor < ' v > for LifeSeeder {
337
342
fn visit_item ( & mut self , item : & ast:: Item ) {
338
- if has_allow_dead_code_or_lang_attr ( item. attrs . as_slice ( ) ) {
343
+ let allow_dead_code = has_allow_dead_code_or_lang_attr ( item. attrs . as_slice ( ) ) ;
344
+ if allow_dead_code {
339
345
self . worklist . push ( item. id ) ;
340
346
}
341
347
match item. node {
348
+ ast:: ItemEnum ( ref enum_def, _) if allow_dead_code => {
349
+ self . worklist . extend ( enum_def. variants . iter ( ) . map ( |variant| variant. node . id ) ) ;
350
+ }
342
351
ast:: ItemImpl ( _, Some ( ref _trait_ref) , _, ref impl_items) => {
343
352
for impl_item in impl_items. iter ( ) {
344
353
match * impl_item {
@@ -415,16 +424,6 @@ fn find_live(tcx: &ty::ctxt,
415
424
symbol_visitor. live_symbols
416
425
}
417
426
418
- fn should_warn ( item : & ast:: Item ) -> bool {
419
- match item. node {
420
- ast:: ItemStatic ( ..)
421
- | ast:: ItemFn ( ..)
422
- | ast:: ItemEnum ( ..)
423
- | ast:: ItemStruct ( ..) => true ,
424
- _ => false
425
- }
426
- }
427
-
428
427
fn get_struct_ctor_id ( item : & ast:: Item ) -> Option < ast:: NodeId > {
429
428
match item. node {
430
429
ast:: ItemStruct ( ref struct_def, _) => struct_def. ctor_id ,
@@ -438,6 +437,18 @@ struct DeadVisitor<'a, 'tcx: 'a> {
438
437
}
439
438
440
439
impl < ' a , ' tcx > DeadVisitor < ' a , ' tcx > {
440
+ fn should_warn_about_item ( & mut self , item : & ast:: Item ) -> bool {
441
+ let should_warn = match item. node {
442
+ ast:: ItemStatic ( ..)
443
+ | ast:: ItemFn ( ..)
444
+ | ast:: ItemEnum ( ..)
445
+ | ast:: ItemStruct ( ..) => true ,
446
+ _ => false
447
+ } ;
448
+ let ctor_id = get_struct_ctor_id ( item) ;
449
+ should_warn && !self . symbol_is_live ( item. id , ctor_id)
450
+ }
451
+
441
452
fn should_warn_about_field ( & mut self , node : & ast:: StructField_ ) -> bool {
442
453
let is_named = node. ident ( ) . is_some ( ) ;
443
454
let field_type = ty:: node_id_to_type ( self . tcx , node. id ) ;
@@ -451,6 +462,11 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
451
462
&& !has_allow_dead_code_or_lang_attr ( node. attrs . as_slice ( ) )
452
463
}
453
464
465
+ fn should_warn_about_variant ( & mut self , variant : & ast:: Variant_ ) -> bool {
466
+ !self . symbol_is_live ( variant. id , None )
467
+ && !has_allow_dead_code_or_lang_attr ( variant. attrs . as_slice ( ) )
468
+ }
469
+
454
470
// id := node id of an item's definition.
455
471
// ctor_id := `Some` if the item is a struct_ctor (tuple struct),
456
472
// `None` otherwise.
@@ -506,9 +522,19 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
506
522
507
523
impl < ' a , ' tcx , ' v > Visitor < ' v > for DeadVisitor < ' a , ' tcx > {
508
524
fn visit_item ( & mut self , item : & ast:: Item ) {
509
- let ctor_id = get_struct_ctor_id ( item) ;
510
- if !self . symbol_is_live ( item. id , ctor_id) && should_warn ( item) {
525
+ if self . should_warn_about_item ( item) {
511
526
self . warn_dead_code ( item. id , item. span , item. ident ) ;
527
+ } else {
528
+ match item. node {
529
+ ast:: ItemEnum ( ref enum_def, _) => {
530
+ for variant in enum_def. variants . iter ( ) {
531
+ if self . should_warn_about_variant ( & variant. node ) {
532
+ self . warn_dead_code ( variant. node . id , variant. span , variant. node . name ) ;
533
+ }
534
+ }
535
+ } ,
536
+ _ => ( )
537
+ }
512
538
}
513
539
visit:: walk_item ( self , item) ;
514
540
}
0 commit comments