Skip to content

Commit 59fcac6

Browse files
Improve dead code detection for unions
1 parent 46fe8e9 commit 59fcac6

File tree

2 files changed

+32
-16
lines changed

2 files changed

+32
-16
lines changed

src/librustc/hir/intravisit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -877,7 +877,7 @@ pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, impl_item_ref: &'
877877

878878
pub fn walk_struct_def<'v, V: Visitor<'v>>(visitor: &mut V, struct_definition: &'v VariantData) {
879879
visitor.visit_id(struct_definition.id());
880-
walk_list!(visitor, visit_struct_field, struct_definition.fields());
880+
walk_list!(visitor, visit_struct_field, struct_definition.fields().iter().rev());
881881
}
882882

883883
pub fn walk_struct_field<'v, V: Visitor<'v>>(visitor: &mut V, struct_field: &'v StructField) {

src/librustc/middle/dead.rs

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,7 @@ fn get_struct_ctor_id(item: &hir::Item) -> Option<ast::NodeId> {
422422
struct DeadVisitor<'a, 'tcx: 'a> {
423423
tcx: TyCtxt<'a, 'tcx, 'tcx>,
424424
live_symbols: Box<FxHashSet<ast::NodeId>>,
425+
need_check_next_union_field: bool,
425426
}
426427

427428
impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
@@ -537,6 +538,16 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> {
537538
}
538539
}
539540

541+
fn visit_variant_data(&mut self,
542+
s: &'tcx hir::VariantData,
543+
_: ast::Name,
544+
_: &'tcx hir::Generics,
545+
_parent_id: ast::NodeId,
546+
_: syntax_pos::Span) {
547+
self.need_check_next_union_field = true;
548+
intravisit::walk_struct_def(self, s)
549+
}
550+
540551
fn visit_variant(&mut self,
541552
variant: &'tcx hir::Variant,
542553
g: &'tcx hir::Generics,
@@ -557,23 +568,24 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> {
557568
}
558569

559570
fn visit_struct_field(&mut self, field: &'tcx hir::StructField) {
560-
if self.should_warn_about_field(&field) {
561-
let did = self.tcx.hir.get_parent_did(field.id);
562-
if if let Some(node_id) = self.tcx.hir.as_local_node_id(did) {
563-
match self.tcx.hir.find(node_id) {
564-
Some(hir_map::NodeItem(item)) => match item.node {
565-
Item_::ItemUnion(_, _) => false,
566-
_ => true,
567-
},
568-
_ => true,
569-
}
570-
} else {
571-
true
572-
} {
571+
if self.need_check_next_union_field {
572+
if self.should_warn_about_field(&field) {
573573
self.warn_dead_code(field.id, field.span, field.name, "field");
574+
} else {
575+
let did = self.tcx.hir.get_parent_did(field.id);
576+
if let Some(node_id) = self.tcx.hir.as_local_node_id(did) {
577+
match self.tcx.hir.find(node_id) {
578+
Some(hir_map::NodeItem(item)) => match item.node {
579+
// If this is an union's field, it means all previous fields
580+
// have been used as well so no need to check further.
581+
Item_::ItemUnion(_, _) => self.need_check_next_union_field = false,
582+
_ => {}
583+
},
584+
_ => {}
585+
}
586+
}
574587
}
575588
}
576-
577589
intravisit::walk_struct_field(self, field);
578590
}
579591

@@ -615,6 +627,10 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
615627
let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
616628
let krate = tcx.hir.krate();
617629
let live_symbols = find_live(tcx, access_levels, krate);
618-
let mut visitor = DeadVisitor { tcx: tcx, live_symbols: live_symbols };
630+
let mut visitor = DeadVisitor {
631+
tcx: tcx,
632+
live_symbols: live_symbols,
633+
need_check_next_union_field: true,
634+
};
619635
intravisit::walk_crate(&mut visitor, krate);
620636
}

0 commit comments

Comments
 (0)