mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-24 04:46:58 +00:00
Improve union unused field detection
This commit is contained in:
parent
59fcac6fa9
commit
90f54d00d3
src
@ -877,7 +877,7 @@ pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, impl_item_ref: &'
|
|||||||
|
|
||||||
pub fn walk_struct_def<'v, V: Visitor<'v>>(visitor: &mut V, struct_definition: &'v VariantData) {
|
pub fn walk_struct_def<'v, V: Visitor<'v>>(visitor: &mut V, struct_definition: &'v VariantData) {
|
||||||
visitor.visit_id(struct_definition.id());
|
visitor.visit_id(struct_definition.id());
|
||||||
walk_list!(visitor, visit_struct_field, struct_definition.fields().iter().rev());
|
walk_list!(visitor, visit_struct_field, struct_definition.fields());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn walk_struct_field<'v, V: Visitor<'v>>(visitor: &mut V, struct_field: &'v StructField) {
|
pub fn walk_struct_field<'v, V: Visitor<'v>>(visitor: &mut V, struct_field: &'v StructField) {
|
||||||
|
@ -189,6 +189,24 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
|
|||||||
self.struct_has_extern_repr = had_extern_repr;
|
self.struct_has_extern_repr = had_extern_repr;
|
||||||
self.inherited_pub_visibility = had_inherited_pub_visibility;
|
self.inherited_pub_visibility = had_inherited_pub_visibility;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn mark_as_used_if_union(&mut self, did: DefId) {
|
||||||
|
if let Some(node_id) = self.tcx.hir.as_local_node_id(did) {
|
||||||
|
match self.tcx.hir.find(node_id) {
|
||||||
|
Some(hir_map::NodeItem(item)) => match item.node {
|
||||||
|
Item_::ItemUnion(ref variant, _) => {
|
||||||
|
if variant.fields().len() > 1 {
|
||||||
|
for field in variant.fields() {
|
||||||
|
self.live_symbols.insert(field.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> {
|
impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> {
|
||||||
@ -221,6 +239,11 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> {
|
|||||||
hir::ExprPath(ref qpath @ hir::QPath::TypeRelative(..)) => {
|
hir::ExprPath(ref qpath @ hir::QPath::TypeRelative(..)) => {
|
||||||
let def = self.tables.qpath_def(qpath, expr.id);
|
let def = self.tables.qpath_def(qpath, expr.id);
|
||||||
self.handle_definition(def);
|
self.handle_definition(def);
|
||||||
|
self.mark_as_used_if_union(def.def_id());
|
||||||
|
}
|
||||||
|
hir::ExprPath(ref qpath @ hir::QPath::Resolved(..)) => {
|
||||||
|
let def = self.tables.qpath_def(qpath, expr.id);
|
||||||
|
self.mark_as_used_if_union(def.def_id());
|
||||||
}
|
}
|
||||||
hir::ExprMethodCall(..) => {
|
hir::ExprMethodCall(..) => {
|
||||||
self.lookup_and_handle_method(expr.id);
|
self.lookup_and_handle_method(expr.id);
|
||||||
@ -422,7 +445,6 @@ fn get_struct_ctor_id(item: &hir::Item) -> Option<ast::NodeId> {
|
|||||||
struct DeadVisitor<'a, 'tcx: 'a> {
|
struct DeadVisitor<'a, 'tcx: 'a> {
|
||||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
live_symbols: Box<FxHashSet<ast::NodeId>>,
|
live_symbols: Box<FxHashSet<ast::NodeId>>,
|
||||||
need_check_next_union_field: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
|
impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
|
||||||
@ -538,16 +560,6 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_variant_data(&mut self,
|
|
||||||
s: &'tcx hir::VariantData,
|
|
||||||
_: ast::Name,
|
|
||||||
_: &'tcx hir::Generics,
|
|
||||||
_parent_id: ast::NodeId,
|
|
||||||
_: syntax_pos::Span) {
|
|
||||||
self.need_check_next_union_field = true;
|
|
||||||
intravisit::walk_struct_def(self, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_variant(&mut self,
|
fn visit_variant(&mut self,
|
||||||
variant: &'tcx hir::Variant,
|
variant: &'tcx hir::Variant,
|
||||||
g: &'tcx hir::Generics,
|
g: &'tcx hir::Generics,
|
||||||
@ -568,23 +580,9 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn visit_struct_field(&mut self, field: &'tcx hir::StructField) {
|
fn visit_struct_field(&mut self, field: &'tcx hir::StructField) {
|
||||||
if self.need_check_next_union_field {
|
if self.should_warn_about_field(&field) {
|
||||||
if self.should_warn_about_field(&field) {
|
self.warn_dead_code(field.id, field.span,
|
||||||
self.warn_dead_code(field.id, field.span, field.name, "field");
|
field.name, "field");
|
||||||
} else {
|
|
||||||
let did = self.tcx.hir.get_parent_did(field.id);
|
|
||||||
if let Some(node_id) = self.tcx.hir.as_local_node_id(did) {
|
|
||||||
match self.tcx.hir.find(node_id) {
|
|
||||||
Some(hir_map::NodeItem(item)) => match item.node {
|
|
||||||
// If this is an union's field, it means all previous fields
|
|
||||||
// have been used as well so no need to check further.
|
|
||||||
Item_::ItemUnion(_, _) => self.need_check_next_union_field = false,
|
|
||||||
_ => {}
|
|
||||||
},
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
intravisit::walk_struct_field(self, field);
|
intravisit::walk_struct_field(self, field);
|
||||||
}
|
}
|
||||||
@ -630,7 +628,6 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|
|||||||
let mut visitor = DeadVisitor {
|
let mut visitor = DeadVisitor {
|
||||||
tcx: tcx,
|
tcx: tcx,
|
||||||
live_symbols: live_symbols,
|
live_symbols: live_symbols,
|
||||||
need_check_next_union_field: true,
|
|
||||||
};
|
};
|
||||||
intravisit::walk_crate(&mut visitor, krate);
|
intravisit::walk_crate(&mut visitor, krate);
|
||||||
}
|
}
|
||||||
|
@ -10,20 +10,24 @@
|
|||||||
|
|
||||||
#![deny(dead_code)]
|
#![deny(dead_code)]
|
||||||
|
|
||||||
union U {
|
union U1 {
|
||||||
x: u32,
|
a: u8, // should not be reported
|
||||||
y: f32,
|
b: u8, // should not be reported
|
||||||
|
c: u8, // should be reported
|
||||||
}
|
}
|
||||||
|
union U2 {
|
||||||
struct V {
|
a: u8, // should be reported
|
||||||
x: u32,
|
b: u8, // should not be reported
|
||||||
y: u32,
|
c: u8, // should not be reported
|
||||||
}
|
}
|
||||||
|
union NoDropLike { a: u8 } // should be reported as unused
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let u = U { x: 0x3f800000 };
|
let u = U1 { a: 0 };
|
||||||
let _f = unsafe { u.y };
|
let _a = unsafe { u.b };
|
||||||
let v = V { x: 0, y: 0 };
|
|
||||||
println!("{}", v.x);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
let u = U2 { c: 0 };
|
||||||
|
let _b = unsafe { u.b };
|
||||||
|
|
||||||
|
let _u = NoDropLike { a: 10 };
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user