@@ -25,6 +25,8 @@ use middle::privacy;
25
25
use ty:: { self , TyCtxt } ;
26
26
use util:: nodemap:: FxHashSet ;
27
27
28
+ use rustc_data_structures:: fx:: FxHashMap ;
29
+
28
30
use syntax:: { ast, source_map} ;
29
31
use syntax:: attr;
30
32
use syntax_pos;
@@ -55,12 +57,15 @@ struct MarkSymbolVisitor<'a, 'tcx: 'a> {
55
57
in_pat : bool ,
56
58
inherited_pub_visibility : bool ,
57
59
ignore_variant_stack : Vec < DefId > ,
60
+ // maps from tuple struct constructors to tuple struct items
61
+ struct_constructors : FxHashMap < ast:: NodeId , ast:: NodeId > ,
58
62
}
59
63
60
64
impl < ' a , ' tcx > MarkSymbolVisitor < ' a , ' tcx > {
61
65
fn check_def_id ( & mut self , def_id : DefId ) {
62
66
if let Some ( node_id) = self . tcx . hir ( ) . as_local_node_id ( def_id) {
63
- if should_explore ( self . tcx , node_id) {
67
+ if should_explore ( self . tcx , node_id) ||
68
+ self . struct_constructors . contains_key ( & node_id) {
64
69
self . worklist . push ( node_id) ;
65
70
}
66
71
self . live_symbols . insert ( node_id) ;
@@ -137,19 +142,23 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
137
142
continue
138
143
}
139
144
140
- if let Some ( ref node) = self . tcx . hir ( ) . find ( id) {
145
+ // in the case of tuple struct constructors we want to check the item, not the generated
146
+ // tuple struct constructor function
147
+ let id = self . struct_constructors . get ( & id) . cloned ( ) . unwrap_or ( id) ;
148
+
149
+ if let Some ( node) = self . tcx . hir ( ) . find ( id) {
141
150
self . live_symbols . insert ( id) ;
142
151
self . visit_node ( node) ;
143
152
}
144
153
}
145
154
}
146
155
147
- fn visit_node ( & mut self , node : & Node < ' tcx > ) {
156
+ fn visit_node ( & mut self , node : Node < ' tcx > ) {
148
157
let had_repr_c = self . repr_has_repr_c ;
149
158
self . repr_has_repr_c = false ;
150
159
let had_inherited_pub_visibility = self . inherited_pub_visibility ;
151
160
self . inherited_pub_visibility = false ;
152
- match * node {
161
+ match node {
153
162
Node :: Item ( item) => {
154
163
match item. node {
155
164
hir:: ItemKind :: Struct ( ..) | hir:: ItemKind :: Union ( ..) => {
@@ -337,6 +346,8 @@ struct LifeSeeder<'k, 'tcx: 'k> {
337
346
worklist : Vec < ast:: NodeId > ,
338
347
krate : & ' k hir:: Crate ,
339
348
tcx : TyCtxt < ' k , ' tcx , ' tcx > ,
349
+ // see `MarkSymbolVisitor::struct_constructors`
350
+ struct_constructors : FxHashMap < ast:: NodeId , ast:: NodeId > ,
340
351
}
341
352
342
353
impl < ' v , ' k , ' tcx > ItemLikeVisitor < ' v > for LifeSeeder < ' k , ' tcx > {
@@ -379,6 +390,9 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> {
379
390
}
380
391
}
381
392
}
393
+ hir:: ItemKind :: Struct ( ref variant_data, _) => {
394
+ self . struct_constructors . insert ( variant_data. id ( ) , item. id ) ;
395
+ }
382
396
_ => ( )
383
397
}
384
398
}
@@ -392,11 +406,11 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> {
392
406
}
393
407
}
394
408
395
- fn create_and_seed_worklist < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
396
- access_levels : & privacy :: AccessLevels ,
397
- krate : & hir :: Crate )
398
- -> Vec < ast :: NodeId >
399
- {
409
+ fn create_and_seed_worklist < ' a , ' tcx > (
410
+ tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
411
+ access_levels : & privacy :: AccessLevels ,
412
+ krate : & hir :: Crate ,
413
+ ) -> ( Vec < ast :: NodeId > , FxHashMap < ast :: NodeId , ast :: NodeId > ) {
400
414
let worklist = access_levels. map . iter ( ) . filter_map ( |( & id, level) | {
401
415
if level >= & privacy:: AccessLevel :: Reachable {
402
416
Some ( id)
@@ -413,17 +427,18 @@ fn create_and_seed_worklist<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
413
427
worklist,
414
428
krate,
415
429
tcx,
430
+ struct_constructors : Default :: default ( ) ,
416
431
} ;
417
432
krate. visit_all_item_likes ( & mut life_seeder) ;
418
433
419
- return life_seeder. worklist ;
434
+ ( life_seeder. worklist , life_seeder . struct_constructors )
420
435
}
421
436
422
437
fn find_live < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
423
438
access_levels : & privacy:: AccessLevels ,
424
439
krate : & hir:: Crate )
425
440
-> FxHashSet < ast:: NodeId > {
426
- let worklist = create_and_seed_worklist ( tcx, access_levels, krate) ;
441
+ let ( worklist, struct_constructors ) = create_and_seed_worklist ( tcx, access_levels, krate) ;
427
442
let mut symbol_visitor = MarkSymbolVisitor {
428
443
worklist,
429
444
tcx,
@@ -433,20 +448,12 @@ fn find_live<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
433
448
in_pat : false ,
434
449
inherited_pub_visibility : false ,
435
450
ignore_variant_stack : vec ! [ ] ,
451
+ struct_constructors,
436
452
} ;
437
453
symbol_visitor. mark_live_symbols ( ) ;
438
454
symbol_visitor. live_symbols
439
455
}
440
456
441
- fn get_struct_ctor_id ( item : & hir:: Item ) -> Option < ast:: NodeId > {
442
- match item. node {
443
- hir:: ItemKind :: Struct ( ref struct_def, _) if !struct_def. is_struct ( ) => {
444
- Some ( struct_def. id ( ) )
445
- }
446
- _ => None
447
- }
448
- }
449
-
450
457
struct DeadVisitor < ' a , ' tcx : ' a > {
451
458
tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
452
459
live_symbols : FxHashSet < ast:: NodeId > ,
@@ -464,46 +471,35 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
464
471
| hir:: ItemKind :: Union ( ..) => true ,
465
472
_ => false
466
473
} ;
467
- let ctor_id = get_struct_ctor_id ( item) ;
468
- should_warn && !self . symbol_is_live ( item. id , ctor_id)
474
+ should_warn && !self . symbol_is_live ( item. id )
469
475
}
470
476
471
477
fn should_warn_about_field ( & mut self , field : & hir:: StructField ) -> bool {
472
478
let field_type = self . tcx . type_of ( self . tcx . hir ( ) . local_def_id ( field. id ) ) ;
473
479
!field. is_positional ( )
474
- && !self . symbol_is_live ( field. id , None )
480
+ && !self . symbol_is_live ( field. id )
475
481
&& !field_type. is_phantom_data ( )
476
482
&& !has_allow_dead_code_or_lang_attr ( self . tcx , field. id , & field. attrs )
477
483
}
478
484
479
485
fn should_warn_about_variant ( & mut self , variant : & hir:: VariantKind ) -> bool {
480
- !self . symbol_is_live ( variant. data . id ( ) , None )
486
+ !self . symbol_is_live ( variant. data . id ( ) )
481
487
&& !has_allow_dead_code_or_lang_attr ( self . tcx ,
482
488
variant. data . id ( ) ,
483
489
& variant. attrs )
484
490
}
485
491
486
492
fn should_warn_about_foreign_item ( & mut self , fi : & hir:: ForeignItem ) -> bool {
487
- !self . symbol_is_live ( fi. id , None )
493
+ !self . symbol_is_live ( fi. id )
488
494
&& !has_allow_dead_code_or_lang_attr ( self . tcx , fi. id , & fi. attrs )
489
495
}
490
496
491
497
// id := node id of an item's definition.
492
- // ctor_id := `Some` if the item is a struct_ctor (tuple struct),
493
- // `None` otherwise.
494
- // If the item is a struct_ctor, then either its `id` or
495
- // `ctor_id` (unwrapped) is in the live_symbols set. More specifically,
496
- // DefMap maps the ExprKind::Path of a struct_ctor to the node referred by
497
- // `ctor_id`. On the other hand, in a statement like
498
- // `type <ident> <generics> = <ty>;` where <ty> refers to a struct_ctor,
499
- // DefMap maps <ty> to `id` instead.
500
- fn symbol_is_live ( & mut self ,
501
- id : ast:: NodeId ,
502
- ctor_id : Option < ast:: NodeId > )
503
- -> bool {
504
- if self . live_symbols . contains ( & id)
505
- || ctor_id. map_or ( false , |ctor| self . live_symbols . contains ( & ctor) )
506
- {
498
+ fn symbol_is_live (
499
+ & mut self ,
500
+ id : ast:: NodeId ,
501
+ ) -> bool {
502
+ if self . live_symbols . contains ( & id) {
507
503
return true ;
508
504
}
509
505
// If it's a type whose items are live, then it's live, too.
@@ -611,7 +607,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> {
611
607
fn visit_impl_item ( & mut self , impl_item : & ' tcx hir:: ImplItem ) {
612
608
match impl_item. node {
613
609
hir:: ImplItemKind :: Const ( _, body_id) => {
614
- if !self . symbol_is_live ( impl_item. id , None ) {
610
+ if !self . symbol_is_live ( impl_item. id ) {
615
611
self . warn_dead_code ( impl_item. id ,
616
612
impl_item. span ,
617
613
impl_item. ident . name ,
@@ -621,7 +617,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> {
621
617
self . visit_nested_body ( body_id)
622
618
}
623
619
hir:: ImplItemKind :: Method ( _, body_id) => {
624
- if !self . symbol_is_live ( impl_item. id , None ) {
620
+ if !self . symbol_is_live ( impl_item. id ) {
625
621
let span = self . tcx . sess . source_map ( ) . def_span ( impl_item. span ) ;
626
622
self . warn_dead_code ( impl_item. id , span, impl_item. ident . name , "method" , "used" ) ;
627
623
}
0 commit comments