@@ -47,6 +47,7 @@ struct MarkSymbolVisitor<'a, 'tcx: 'a> {
47
47
struct_has_extern_repr : bool ,
48
48
ignore_non_const_paths : bool ,
49
49
inherited_pub_visibility : bool ,
50
+ ignore_variant_stack : Vec < ast:: NodeId > ,
50
51
}
51
52
52
53
impl < ' a , ' tcx > MarkSymbolVisitor < ' a , ' tcx > {
@@ -59,6 +60,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
59
60
struct_has_extern_repr : false ,
60
61
ignore_non_const_paths : false ,
61
62
inherited_pub_visibility : false ,
63
+ ignore_variant_stack : vec ! [ ] ,
62
64
}
63
65
}
64
66
@@ -79,7 +81,9 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
79
81
& def:: DefPrimTy ( _) => ( ) ,
80
82
& def:: DefVariant ( enum_id, variant_id, _) => {
81
83
self . check_def_id ( enum_id) ;
82
- self . check_def_id ( variant_id) ;
84
+ if !self . ignore_variant_stack . contains ( & variant_id. node ) {
85
+ self . check_def_id ( variant_id) ;
86
+ }
83
87
}
84
88
_ => {
85
89
self . check_def_id ( def. def_id ( ) ) ;
@@ -283,6 +287,23 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> {
283
287
visit:: walk_expr ( self , expr) ;
284
288
}
285
289
290
+ fn visit_arm ( & mut self , arm : & ast:: Arm ) {
291
+ if arm. pats . len ( ) == 1 {
292
+ let pat = & * arm. pats [ 0 ] ;
293
+ let variants = pat_util:: necessary_variants ( & self . tcx . def_map , pat) ;
294
+
295
+ // Inside the body, ignore constructions of variants
296
+ // necessary for the pattern to match. Those construction sites
297
+ // can't be reached unless the variant is constructed elsewhere.
298
+ let len = self . ignore_variant_stack . len ( ) ;
299
+ self . ignore_variant_stack . push_all ( & * variants) ;
300
+ visit:: walk_arm ( self , arm) ;
301
+ self . ignore_variant_stack . truncate ( len) ;
302
+ } else {
303
+ visit:: walk_arm ( self , arm) ;
304
+ }
305
+ }
306
+
286
307
fn visit_pat ( & mut self , pat : & ast:: Pat ) {
287
308
let def_map = & self . tcx . def_map ;
288
309
match pat. node {
@@ -401,6 +422,11 @@ fn create_and_seed_worklist(tcx: &ty::ctxt,
401
422
worklist. push ( * id) ;
402
423
}
403
424
for id in reachable_symbols {
425
+ // Reachable variants can be dead, because we warn about
426
+ // variants never constructed, not variants never used.
427
+ if let Some ( ast_map:: NodeVariant ( ..) ) = tcx. map . find ( * id) {
428
+ continue ;
429
+ }
404
430
worklist. push ( * id) ;
405
431
}
406
432
0 commit comments