Skip to content

Commit e7a5a1c

Browse files
committed
Auto merge of #25961 - sanxiyn:dead-variant-2, r=huonw
Rebase of #21468. Fix #25960.
2 parents d24dd31 + ae0716d commit e7a5a1c

File tree

5 files changed

+95
-7
lines changed

5 files changed

+95
-7
lines changed

src/librustc/middle/dead.rs

+27-1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ struct MarkSymbolVisitor<'a, 'tcx: 'a> {
4848
struct_has_extern_repr: bool,
4949
ignore_non_const_paths: bool,
5050
inherited_pub_visibility: bool,
51+
ignore_variant_stack: Vec<ast::NodeId>,
5152
}
5253

5354
impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
@@ -60,6 +61,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
6061
struct_has_extern_repr: false,
6162
ignore_non_const_paths: false,
6263
inherited_pub_visibility: false,
64+
ignore_variant_stack: vec![],
6365
}
6466
}
6567

@@ -80,7 +82,9 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
8082
def::DefPrimTy(_) => (),
8183
def::DefVariant(enum_id, variant_id, _) => {
8284
self.check_def_id(enum_id);
83-
self.check_def_id(variant_id);
85+
if !self.ignore_variant_stack.contains(&variant_id.node) {
86+
self.check_def_id(variant_id);
87+
}
8488
}
8589
_ => {
8690
self.check_def_id(def.def_id());
@@ -272,6 +276,23 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> {
272276
visit::walk_expr(self, expr);
273277
}
274278

279+
fn visit_arm(&mut self, arm: &ast::Arm) {
280+
if arm.pats.len() == 1 {
281+
let pat = &*arm.pats[0];
282+
let variants = pat_util::necessary_variants(&self.tcx.def_map, pat);
283+
284+
// Inside the body, ignore constructions of variants
285+
// necessary for the pattern to match. Those construction sites
286+
// can't be reached unless the variant is constructed elsewhere.
287+
let len = self.ignore_variant_stack.len();
288+
self.ignore_variant_stack.push_all(&*variants);
289+
visit::walk_arm(self, arm);
290+
self.ignore_variant_stack.truncate(len);
291+
} else {
292+
visit::walk_arm(self, arm);
293+
}
294+
}
295+
275296
fn visit_pat(&mut self, pat: &ast::Pat) {
276297
let def_map = &self.tcx.def_map;
277298
match pat.node {
@@ -393,6 +414,11 @@ fn create_and_seed_worklist(tcx: &ty::ctxt,
393414
worklist.push(*id);
394415
}
395416
for id in reachable_symbols {
417+
// Reachable variants can be dead, because we warn about
418+
// variants never constructed, not variants never used.
419+
if let Some(ast_map::NodeVariant(..)) = tcx.map.find(*id) {
420+
continue;
421+
}
396422
worklist.push(*id);
397423
}
398424

src/librustc/middle/pat_util.rs

+24
Original file line numberDiff line numberDiff line change
@@ -201,3 +201,27 @@ pub fn def_to_path(tcx: &ty::ctxt, id: ast::DefId) -> ast::Path {
201201
span: DUMMY_SP,
202202
})
203203
}
204+
205+
/// Return variants that are necessary to exist for the pattern to match.
206+
pub fn necessary_variants(dm: &DefMap, pat: &ast::Pat) -> Vec<ast::NodeId> {
207+
let mut variants = vec![];
208+
walk_pat(pat, |p| {
209+
match p.node {
210+
ast::PatEnum(_, _) |
211+
ast::PatIdent(_, _, None) |
212+
ast::PatStruct(..) => {
213+
match dm.borrow().get(&p.id) {
214+
Some(&PathResolution { base_def: DefVariant(_, id, _), .. }) => {
215+
variants.push(id.node);
216+
}
217+
_ => ()
218+
}
219+
}
220+
_ => ()
221+
}
222+
true
223+
});
224+
variants.sort();
225+
variants.dedup();
226+
variants
227+
}

src/librustc_typeck/check/cast.rs

-6
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,6 @@ enum CastError {
9999
NeedViaInt,
100100
NeedViaUsize,
101101
NonScalar,
102-
RefToMutPtr
103102
}
104103

105104
impl<'tcx> CastCheck<'tcx> {
@@ -161,11 +160,6 @@ impl<'tcx> CastCheck<'tcx> {
161160
fcx.infcx().ty_to_string(self.cast_ty))
162161
}, self.expr_ty, None);
163162
}
164-
CastError::RefToMutPtr => {
165-
span_err!(fcx.tcx().sess, self.span, E0188,
166-
"cannot cast an immutable reference to a \
167-
mutable pointer");
168-
}
169163
}
170164
}
171165

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![deny(dead_code)]
12+
13+
#[derive(Clone)]
14+
enum Enum {
15+
Variant1, //~ ERROR: variant is never used
16+
Variant2,
17+
}
18+
19+
fn main() {
20+
let e = Enum::Variant2;
21+
e.clone();
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![deny(dead_code)]
12+
13+
enum Foo {
14+
A,
15+
B,
16+
}
17+
18+
pub fn main() {
19+
match Foo::A {
20+
Foo::A | Foo::B => Foo::B
21+
};
22+
}

0 commit comments

Comments
 (0)