Auto merge of #25961 - sanxiyn:dead-variant-2, r=huonw
Rebase of #21468. Fix #25960.
This commit is contained in:
commit
e7a5a1c33a
5 changed files with 95 additions and 7 deletions
|
@ -48,6 +48,7 @@ struct MarkSymbolVisitor<'a, 'tcx: 'a> {
|
||||||
struct_has_extern_repr: bool,
|
struct_has_extern_repr: bool,
|
||||||
ignore_non_const_paths: bool,
|
ignore_non_const_paths: bool,
|
||||||
inherited_pub_visibility: bool,
|
inherited_pub_visibility: bool,
|
||||||
|
ignore_variant_stack: Vec<ast::NodeId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
|
impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
|
||||||
|
@ -60,6 +61,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
|
||||||
struct_has_extern_repr: false,
|
struct_has_extern_repr: false,
|
||||||
ignore_non_const_paths: false,
|
ignore_non_const_paths: false,
|
||||||
inherited_pub_visibility: false,
|
inherited_pub_visibility: false,
|
||||||
|
ignore_variant_stack: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +82,9 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
|
||||||
def::DefPrimTy(_) => (),
|
def::DefPrimTy(_) => (),
|
||||||
def::DefVariant(enum_id, variant_id, _) => {
|
def::DefVariant(enum_id, variant_id, _) => {
|
||||||
self.check_def_id(enum_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());
|
self.check_def_id(def.def_id());
|
||||||
|
@ -272,6 +276,23 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> {
|
||||||
visit::walk_expr(self, expr);
|
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) {
|
fn visit_pat(&mut self, pat: &ast::Pat) {
|
||||||
let def_map = &self.tcx.def_map;
|
let def_map = &self.tcx.def_map;
|
||||||
match pat.node {
|
match pat.node {
|
||||||
|
@ -393,6 +414,11 @@ fn create_and_seed_worklist(tcx: &ty::ctxt,
|
||||||
worklist.push(*id);
|
worklist.push(*id);
|
||||||
}
|
}
|
||||||
for id in reachable_symbols {
|
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);
|
worklist.push(*id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -201,3 +201,27 @@ pub fn def_to_path(tcx: &ty::ctxt, id: ast::DefId) -> ast::Path {
|
||||||
span: DUMMY_SP,
|
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(&PathResolution { base_def: DefVariant(_, id, _), .. }) => {
|
||||||
|
variants.push(id.node);
|
||||||
|
}
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
true
|
||||||
|
});
|
||||||
|
variants.sort();
|
||||||
|
variants.dedup();
|
||||||
|
variants
|
||||||
|
}
|
||||||
|
|
|
@ -99,7 +99,6 @@ enum CastError {
|
||||||
NeedViaInt,
|
NeedViaInt,
|
||||||
NeedViaUsize,
|
NeedViaUsize,
|
||||||
NonScalar,
|
NonScalar,
|
||||||
RefToMutPtr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> CastCheck<'tcx> {
|
impl<'tcx> CastCheck<'tcx> {
|
||||||
|
@ -161,11 +160,6 @@ impl<'tcx> CastCheck<'tcx> {
|
||||||
fcx.infcx().ty_to_string(self.cast_ty))
|
fcx.infcx().ty_to_string(self.cast_ty))
|
||||||
}, self.expr_ty, None);
|
}, self.expr_ty, None);
|
||||||
}
|
}
|
||||||
CastError::RefToMutPtr => {
|
|
||||||
span_err!(fcx.tcx().sess, self.span, E0188,
|
|
||||||
"cannot cast an immutable reference to a \
|
|
||||||
mutable pointer");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
22
src/test/compile-fail/lint-dead-code-variant.rs
Normal file
22
src/test/compile-fail/lint-dead-code-variant.rs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
// 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(Clone)]
|
||||||
|
enum Enum {
|
||||||
|
Variant1, //~ ERROR: variant is never used
|
||||||
|
Variant2,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let e = Enum::Variant2;
|
||||||
|
e.clone();
|
||||||
|
}
|
22
src/test/run-pass/lint-dead-code-variant.rs
Normal file
22
src/test/run-pass/lint-dead-code-variant.rs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
// 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)]
|
||||||
|
|
||||||
|
enum Foo {
|
||||||
|
A,
|
||||||
|
B,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
match Foo::A {
|
||||||
|
Foo::A | Foo::B => Foo::B
|
||||||
|
};
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue