struct_has_extern_repr: bool,
ignore_non_const_paths: bool,
inherited_pub_visibility: bool,
+ ignore_variant_stack: Vec<ast::NodeId>,
}
impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
struct_has_extern_repr: false,
ignore_non_const_paths: false,
inherited_pub_visibility: false,
+ ignore_variant_stack: vec![],
}
}
&def::DefPrimTy(_) => (),
&def::DefVariant(enum_id, variant_id, _) => {
self.check_def_id(enum_id);
- self.check_def_id(variant_id);
+ if !self.ignore_variant_stack.contains(&variant_id.node) {
+ self.check_def_id(variant_id);
+ }
}
_ => {
self.check_def_id(def.def_id());
visit::walk_expr(self, expr);
}
+ fn visit_arm(&mut self, arm: &ast::Arm) {
+ if arm.pats.len() == 1 {
+ let pat = &*arm.pats[0];
+ let variants = pat_util::necessary_variants(&self.tcx.def_map, pat);
+
+ // Inside the body, ignore constructions of variants
+ // necessary for the pattern to match. Those construction sites
+ // can't be reached unless the variant is constructed elsewhere.
+ let len = self.ignore_variant_stack.len();
+ self.ignore_variant_stack.push_all(&*variants);
+ visit::walk_arm(self, arm);
+ self.ignore_variant_stack.truncate(len);
+ } else {
+ visit::walk_arm(self, arm);
+ }
+ }
+
fn visit_pat(&mut self, pat: &ast::Pat) {
let def_map = &self.tcx.def_map;
match pat.node {
worklist.push(*id);
}
for id in reachable_symbols {
+ // Reachable variants can be dead, because we warn about
+ // variants never constructed, not variants never used.
+ if let Some(ast_map::NodeVariant(..)) = tcx.map.find(*id) {
+ continue;
+ }
worklist.push(*id);
}
span: DUMMY_SP,
})
}
+
+/// Return variants that are necessary to exist for the pattern to match.
+pub fn necessary_variants(dm: &DefMap, pat: &ast::Pat) -> Vec<ast::NodeId> {
+ let mut variants = vec![];
+ walk_pat(pat, |p| {
+ match p.node {
+ ast::PatEnum(_, _) |
+ ast::PatIdent(_, _, None) |
+ ast::PatStruct(..) => {
+ match dm.borrow().get(&p.id) {
+ Some(&DefVariant(_, id, _)) => {
+ variants.push(id.node);
+ }
+ _ => ()
+ }
+ }
+ _ => ()
+ }
+ true
+ });
+ variants.sort();
+ variants.dedup();
+ variants
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![deny(dead_code)]
+
+#[derive(Copy)]
+enum Enum {
+ Variant1, //~ ERROR: variant is never used
+ Variant2,
+ Variant3,
+}
+
+fn copy(e: Enum) -> Enum {
+ use Enum::*;
+ match e {
+ Variant1 => Variant1,
+ Variant2 => Variant2,
+ Variant3 => Variant3,
+ }
+}
+
+fn max(e: Enum) -> Enum {
+ use Enum::*;
+ match e {
+ Variant1 => Variant3,
+ Variant2 => Variant3,
+ Variant3 => Variant3,
+ }
+}
+
+fn main() {
+ let e = Enum::Variant2;
+ copy(e);
+ max(e);
+}