1313// from live codes are live, and everything else is dead.
1414
1515use middle:: def;
16- use lint ;
16+ use middle :: pat_util ;
1717use middle:: privacy;
1818use middle:: ty;
1919use middle:: typeck;
20+ use lint;
2021use util:: nodemap:: NodeSet ;
2122
2223use std:: collections:: HashSet ;
2324use syntax:: ast;
2425use syntax:: ast_map;
2526use syntax:: ast_util:: { local_def, is_local, PostExpansionMethod } ;
26- use syntax:: attr:: AttrMetaMethods ;
27- use syntax:: attr;
27+ use syntax:: attr:: { mod, AttrMetaMethods } ;
2828use syntax:: codemap;
29- use syntax:: visit:: Visitor ;
30- use syntax:: visit;
29+ use syntax:: visit:: { mod, Visitor } ;
3130
3231// Any local node that may call something in its body block should be
3332// explored. For example, if it's a live NodeItem that is a
@@ -51,7 +50,8 @@ struct MarkSymbolVisitor<'a, 'tcx: 'a> {
5150 worklist : Vec < ast:: NodeId > ,
5251 tcx : & ' a ty:: ctxt < ' tcx > ,
5352 live_symbols : Box < HashSet < ast:: NodeId > > ,
54- struct_has_extern_repr : bool
53+ struct_has_extern_repr : bool ,
54+ ignore_paths : bool
5555}
5656
5757impl < ' a , ' tcx > MarkSymbolVisitor < ' a , ' tcx > {
@@ -61,7 +61,8 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
6161 worklist : worklist,
6262 tcx : tcx,
6363 live_symbols : box HashSet :: new ( ) ,
64- struct_has_extern_repr : false
64+ struct_has_extern_repr : false ,
65+ ignore_paths : false
6566 }
6667 }
6768
@@ -73,19 +74,18 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
7374 }
7475
7576 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+ } ) ;
8989 }
9090
9191 fn lookup_and_handle_method ( & mut self , id : ast:: NodeId ,
@@ -275,22 +275,27 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> {
275275 }
276276
277277 fn visit_pat ( & mut self , pat : & ast:: Pat ) {
278+ let def_map = & self . tcx . def_map ;
278279 match pat. node {
279280 ast:: PatStruct ( _, ref fields, _) => {
280281 self . handle_field_pattern_match ( pat, fields. as_slice ( ) ) ;
281282 }
282- ast :: PatIdent ( _ , _ , _ ) => {
283+ _ if pat_util :: pat_is_const ( def_map , pat ) => {
283284 // it might be the only use of a static:
284285 self . lookup_and_handle_definition ( & pat. id )
285286 }
286287 _ => ( )
287288 }
288289
290+ self . ignore_paths = true ;
289291 visit:: walk_pat ( self , pat) ;
292+ self . ignore_paths = false ;
290293 }
291294
292295 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+ }
294299 visit:: walk_path ( self , path) ;
295300 }
296301
@@ -330,15 +335,19 @@ fn has_allow_dead_code_or_lang_attr(attrs: &[ast::Attribute]) -> bool {
330335// 2) We are not sure to be live or not
331336// * Implementation of a trait method
332337struct LifeSeeder {
333- worklist : Vec < ast:: NodeId > ,
338+ worklist : Vec < ast:: NodeId >
334339}
335340
336341impl < ' v > Visitor < ' v > for LifeSeeder {
337342 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 {
339345 self . worklist . push ( item. id ) ;
340346 }
341347 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+ }
342351 ast:: ItemImpl ( _, Some ( ref _trait_ref) , _, ref impl_items) => {
343352 for impl_item in impl_items. iter ( ) {
344353 match * impl_item {
@@ -415,16 +424,6 @@ fn find_live(tcx: &ty::ctxt,
415424 symbol_visitor. live_symbols
416425}
417426
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-
428427fn get_struct_ctor_id ( item : & ast:: Item ) -> Option < ast:: NodeId > {
429428 match item. node {
430429 ast:: ItemStruct ( ref struct_def, _) => struct_def. ctor_id ,
@@ -438,6 +437,18 @@ struct DeadVisitor<'a, 'tcx: 'a> {
438437}
439438
440439impl < ' 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+
441452 fn should_warn_about_field ( & mut self , node : & ast:: StructField_ ) -> bool {
442453 let is_named = node. ident ( ) . is_some ( ) ;
443454 let field_type = ty:: node_id_to_type ( self . tcx , node. id ) ;
@@ -451,6 +462,11 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
451462 && !has_allow_dead_code_or_lang_attr ( node. attrs . as_slice ( ) )
452463 }
453464
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+
454470 // id := node id of an item's definition.
455471 // ctor_id := `Some` if the item is a struct_ctor (tuple struct),
456472 // `None` otherwise.
@@ -506,9 +522,19 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
506522
507523impl < ' a , ' tcx , ' v > Visitor < ' v > for DeadVisitor < ' a , ' tcx > {
508524 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) {
511526 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+ }
512538 }
513539 visit:: walk_item ( self , item) ;
514540 }
0 commit comments