Make is_useful handle empty types properly
This commit is contained in:
parent
9ad20442e8
commit
bcdbe942e1
@ -70,6 +70,12 @@ declare_lint! {
|
||||
"detects unreachable code paths"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub UNREACHABLE_PATTERNS,
|
||||
Warn,
|
||||
"detects unreachable patterns"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub WARNINGS,
|
||||
Warn,
|
||||
@ -239,6 +245,7 @@ impl LintPass for HardwiredLints {
|
||||
UNUSED_ASSIGNMENTS,
|
||||
DEAD_CODE,
|
||||
UNREACHABLE_CODE,
|
||||
UNREACHABLE_PATTERNS,
|
||||
WARNINGS,
|
||||
UNUSED_FEATURES,
|
||||
STABLE_FEATURES,
|
||||
|
@ -17,7 +17,7 @@ use eval::{compare_const_vals};
|
||||
|
||||
use rustc_const_math::ConstInt;
|
||||
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
|
||||
use pattern::{FieldPattern, Pattern, PatternKind};
|
||||
@ -29,6 +29,7 @@ use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc::mir::Field;
|
||||
use rustc::util::common::ErrorReported;
|
||||
|
||||
use syntax::ast::NodeId;
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
|
||||
use arena::TypedArena;
|
||||
@ -144,6 +145,14 @@ impl<'a, 'tcx> FromIterator<Vec<&'a Pattern<'tcx>>> for Matrix<'a, 'tcx> {
|
||||
//NOTE: appears to be the only place other then InferCtxt to contain a ParamEnv
|
||||
pub struct MatchCheckCtxt<'a, 'tcx: 'a> {
|
||||
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
/// (roughly) where in the code the match occurs. This is necessary for
|
||||
/// checking inhabited-ness of types because whether a type is (visibly)
|
||||
/// inhabited can depend on whether it was defined in the current module or
|
||||
/// not. eg.
|
||||
/// struct Foo { _private: ! }
|
||||
/// can not be seen to be empty outside it's module and should not
|
||||
/// be matchable with an empty match statement.
|
||||
pub node: NodeId,
|
||||
/// A wild pattern with an error type - it exists to avoid having to normalize
|
||||
/// associated types to get field types.
|
||||
pub wild_pattern: &'a Pattern<'tcx>,
|
||||
@ -154,6 +163,7 @@ pub struct MatchCheckCtxt<'a, 'tcx: 'a> {
|
||||
impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
|
||||
pub fn create_and_enter<F, R>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
node: NodeId,
|
||||
f: F) -> R
|
||||
where F: for<'b> FnOnce(MatchCheckCtxt<'b, 'tcx>) -> R
|
||||
{
|
||||
@ -167,6 +177,7 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
|
||||
|
||||
f(MatchCheckCtxt {
|
||||
tcx: tcx,
|
||||
node: node,
|
||||
wild_pattern: &wild_pattern,
|
||||
pattern_arena: &pattern_arena,
|
||||
byte_array_map: FxHashMap(),
|
||||
@ -362,9 +373,9 @@ impl<'tcx> Witness<'tcx> {
|
||||
/// Therefore, if there is some pattern that is unmatched by `matrix`, it will
|
||||
/// still be unmatched if the first constructor is replaced by any of the constructors
|
||||
/// in the return value.
|
||||
fn missing_constructors(cx: &mut MatchCheckCtxt,
|
||||
matrix: &Matrix,
|
||||
pcx: PatternContext) -> Vec<Constructor> {
|
||||
fn missing_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
|
||||
matrix: &Matrix,
|
||||
pcx: PatternContext<'tcx>) -> Vec<Constructor> {
|
||||
let used_constructors: Vec<Constructor> =
|
||||
matrix.0.iter()
|
||||
.flat_map(|row| pat_constructors(cx, row[0], pcx).unwrap_or(vec![]))
|
||||
@ -384,16 +395,46 @@ fn missing_constructors(cx: &mut MatchCheckCtxt,
|
||||
///
|
||||
/// but is instead bounded by the maximum fixed length of slice patterns in
|
||||
/// the column of patterns being analyzed.
|
||||
fn all_constructors(_cx: &mut MatchCheckCtxt, pcx: PatternContext) -> Vec<Constructor> {
|
||||
///
|
||||
/// We make sure to omit constructors that are statically impossible. eg for
|
||||
/// Option<!> we do not include Some(_) in the returned list of constructors.
|
||||
fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
|
||||
pcx: PatternContext<'tcx>) -> Vec<Constructor>
|
||||
{
|
||||
match pcx.ty.sty {
|
||||
ty::TyBool =>
|
||||
[true, false].iter().map(|b| ConstantValue(ConstVal::Bool(*b))).collect(),
|
||||
ty::TySlice(_) =>
|
||||
(0..pcx.max_slice_length+1).map(|length| Slice(length)).collect(),
|
||||
ty::TyArray(_, length) => vec![Slice(length)],
|
||||
ty::TyAdt(def, _) if def.is_enum() && def.variants.len() > 1 =>
|
||||
def.variants.iter().map(|v| Variant(v.did)).collect(),
|
||||
_ => vec![Single]
|
||||
ty::TySlice(ref sub_ty) => {
|
||||
if sub_ty.is_uninhabited(Some(cx.node), cx.tcx) {
|
||||
vec![Slice(0)]
|
||||
} else {
|
||||
(0..pcx.max_slice_length+1).map(|length| Slice(length)).collect()
|
||||
}
|
||||
}
|
||||
ty::TyArray(ref sub_ty, length) => {
|
||||
if length == 0 || !sub_ty.is_uninhabited(Some(cx.node), cx.tcx) {
|
||||
vec![Slice(length)]
|
||||
} else {
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
ty::TyAdt(def, substs) if def.is_enum() && def.variants.len() != 1 => {
|
||||
def.variants.iter().filter_map(|v| {
|
||||
let mut visited = FxHashSet::default();
|
||||
if v.is_uninhabited_recurse(&mut visited, Some(cx.node), cx.tcx, substs, false) {
|
||||
None
|
||||
} else {
|
||||
Some(Variant(v.did))
|
||||
}
|
||||
}).collect()
|
||||
}
|
||||
_ => {
|
||||
if pcx.ty.is_uninhabited(Some(cx.node), cx.tcx) {
|
||||
vec![]
|
||||
} else {
|
||||
vec![Single]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,7 @@ use rustc::middle::mem_categorization::{cmt};
|
||||
use rustc::session::Session;
|
||||
use rustc::traits::Reveal;
|
||||
use rustc::ty::{self, TyCtxt};
|
||||
use rustc::lint;
|
||||
use rustc_errors::DiagnosticBuilder;
|
||||
|
||||
use rustc::hir::def::*;
|
||||
@ -150,7 +151,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
MatchCheckCtxt::create_and_enter(self.tcx, |ref mut cx| {
|
||||
MatchCheckCtxt::create_and_enter(self.tcx, scrut.id, |ref mut cx| {
|
||||
let mut have_errors = false;
|
||||
|
||||
let inlined_arms : Vec<(Vec<_>, _)> = arms.iter().map(|arm| (
|
||||
@ -210,7 +211,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
|
||||
"local binding"
|
||||
};
|
||||
|
||||
MatchCheckCtxt::create_and_enter(self.tcx, |ref mut cx| {
|
||||
MatchCheckCtxt::create_and_enter(self.tcx, pat.id, |ref mut cx| {
|
||||
let mut patcx = PatternContext::new(self.tcx);
|
||||
let pats : Matrix = vec![vec![
|
||||
expand_pattern(cx, patcx.lower_pattern(pat))
|
||||
@ -324,14 +325,19 @@ fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
|
||||
},
|
||||
|
||||
hir::MatchSource::Normal => {
|
||||
let mut err = struct_span_err!(cx.tcx.sess, pat.span, E0001,
|
||||
"unreachable pattern");
|
||||
err.span_label(pat.span, &"this is an unreachable pattern");
|
||||
// if we had a catchall pattern, hint at that
|
||||
// if we had a catchall pattern, raise an error.
|
||||
// Otherwise an unreachable pattern raises a warning.
|
||||
if let Some(catchall) = catchall {
|
||||
let mut err = struct_span_err!(cx.tcx.sess, pat.span, E0001,
|
||||
"unreachable pattern");
|
||||
err.span_label(pat.span, &"this is an unreachable pattern");
|
||||
err.span_note(catchall, "this pattern matches any value");
|
||||
err.emit();
|
||||
} else {
|
||||
cx.tcx.sess.add_lint(lint::builtin::UNREACHABLE_PATTERNS,
|
||||
hir_pat.id, pat.span,
|
||||
String::from("unreachable pattern"));
|
||||
}
|
||||
err.emit();
|
||||
},
|
||||
|
||||
hir::MatchSource::TryDesugar => {
|
||||
|
@ -28,7 +28,7 @@ For example, the following `match` block has too many arms:
|
||||
```compile_fail,E0001
|
||||
match Some(0) {
|
||||
Some(bar) => {/* ... */}
|
||||
None => {/* ... */}
|
||||
x => {/* ... */} // This handles the `None` case
|
||||
_ => {/* ... */} // All possible cases have already been handled
|
||||
}
|
||||
```
|
||||
|
@ -165,6 +165,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
|
||||
DEAD_CODE,
|
||||
UNUSED_MUT,
|
||||
UNREACHABLE_CODE,
|
||||
UNREACHABLE_PATTERNS,
|
||||
UNUSED_MUST_USE,
|
||||
UNUSED_UNSAFE,
|
||||
PATH_STATEMENTS,
|
||||
|
@ -399,7 +399,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
self.check_pat(&p, discrim_ty);
|
||||
all_pats_diverge &= self.diverges.get();
|
||||
}
|
||||
all_pats_diverge
|
||||
// As discussed with @eddyb, this is for disabling unreachable_code
|
||||
// warnings on patterns (they're now subsumed by unreachable_patterns
|
||||
// warnings).
|
||||
match all_pats_diverge {
|
||||
Diverges::Maybe => Diverges::Maybe,
|
||||
Diverges::Always | Diverges::WarnedAlways => Diverges::WarnedAlways,
|
||||
}
|
||||
}).collect();
|
||||
|
||||
// Now typecheck the blocks.
|
||||
|
@ -8,11 +8,13 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![deny(unreachable_patterns)]
|
||||
|
||||
fn main() {
|
||||
let foo = Some(1);
|
||||
match foo {
|
||||
Some(bar) => {/* ... */}
|
||||
Some(_) => {/* ... */}
|
||||
None => {/* ... */}
|
||||
_ => {/* ... */} //~ ERROR E0001
|
||||
_ => {/* ... */} //~ ERROR unreachable pattern
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ fn tail(source_list: &IntList) -> IntList {
|
||||
match source_list {
|
||||
&IntList::Cons(val, box ref next_list) => tail(next_list),
|
||||
&IntList::Cons(val, box Nil) => IntList::Cons(val, box Nil),
|
||||
//~^ ERROR unreachable pattern
|
||||
//~^ ERROR cannot move out of borrowed content
|
||||
//~^^ WARN pattern binding `Nil` is named the same as one of the variants of the type `IntList`
|
||||
_ => panic!()
|
||||
}
|
||||
|
@ -9,6 +9,8 @@
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(slice_patterns)]
|
||||
#![allow(unused_variables)]
|
||||
#![deny(unreachable_patterns)]
|
||||
|
||||
fn main() {
|
||||
let sl = vec![1,2,3];
|
||||
|
@ -8,6 +8,9 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![allow(overflowing_literals)]
|
||||
#![deny(unreachable_patterns)]
|
||||
|
||||
fn test(val: u8) {
|
||||
match val {
|
||||
256 => print!("0b1110\n"),
|
||||
|
26
src/test/compile-fail/issue-30240-b.rs
Normal file
26
src/test/compile-fail/issue-30240-b.rs
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright 2016 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(unreachable_patterns)]
|
||||
|
||||
fn main() {
|
||||
match "world" {
|
||||
"hello" => {}
|
||||
_ => {},
|
||||
}
|
||||
|
||||
match "world" {
|
||||
ref _x if false => {}
|
||||
"hello" => {}
|
||||
"hello" => {} //~ ERROR unreachable pattern
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,5 @@ fn main() {
|
||||
match "world" { //~ ERROR non-exhaustive patterns: `&_`
|
||||
ref _x if false => {}
|
||||
"hello" => {}
|
||||
"hello" => {} //~ ERROR unreachable pattern
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![deny(unreachable_patterns)]
|
||||
|
||||
enum Enum {
|
||||
Var1,
|
||||
Var2,
|
||||
@ -41,13 +43,4 @@ fn main() {
|
||||
//~^ ERROR unreachable pattern
|
||||
//~^^ NOTE this is an unreachable pattern
|
||||
};
|
||||
// `_` need not emit a note, it is pretty obvious already.
|
||||
let t = (Var1, Var1);
|
||||
match t {
|
||||
(Var1, b) => (),
|
||||
_ => (),
|
||||
anything => ()
|
||||
//~^ ERROR unreachable pattern
|
||||
//~^^ NOTE this is an unreachable pattern
|
||||
};
|
||||
}
|
||||
|
@ -40,6 +40,5 @@ fn main() {
|
||||
box NodeKind::Element(ed) => match ed.kind { //~ ERROR non-exhaustive patterns
|
||||
box ElementKind::HTMLImageElement(ref d) if d.image.is_some() => { true }
|
||||
},
|
||||
_ => panic!("WAT") //~ ERROR unreachable pattern
|
||||
};
|
||||
}
|
||||
|
71
src/test/compile-fail/match-argm-statics-2.rs
Normal file
71
src/test/compile-fail/match-argm-statics-2.rs
Normal file
@ -0,0 +1,71 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
use self::Direction::{North, East, South, West};
|
||||
|
||||
struct NewBool(bool);
|
||||
|
||||
enum Direction {
|
||||
North,
|
||||
East,
|
||||
South,
|
||||
West
|
||||
}
|
||||
|
||||
const TRUE_TRUE: (bool, bool) = (true, true);
|
||||
|
||||
fn nonexhaustive_1() {
|
||||
match (true, false) {
|
||||
//~^ ERROR non-exhaustive patterns: `(true, false)` not covered
|
||||
TRUE_TRUE => (),
|
||||
(false, false) => (),
|
||||
(false, true) => ()
|
||||
}
|
||||
}
|
||||
|
||||
const NONE: Option<Direction> = None;
|
||||
const EAST: Direction = East;
|
||||
|
||||
fn nonexhaustive_2() {
|
||||
match Some(Some(North)) {
|
||||
//~^ ERROR non-exhaustive patterns: `Some(Some(West))` not covered
|
||||
Some(NONE) => (),
|
||||
Some(Some(North)) => (),
|
||||
Some(Some(EAST)) => (),
|
||||
Some(Some(South)) => (),
|
||||
None => ()
|
||||
}
|
||||
}
|
||||
|
||||
const NEW_FALSE: NewBool = NewBool(false);
|
||||
struct Foo {
|
||||
bar: Option<Direction>,
|
||||
baz: NewBool
|
||||
}
|
||||
|
||||
const STATIC_FOO: Foo = Foo { bar: None, baz: NEW_FALSE };
|
||||
|
||||
fn nonexhaustive_3() {
|
||||
match (Foo { bar: Some(North), baz: NewBool(true) }) {
|
||||
//~^ ERROR non-exhaustive patterns: `Foo { bar: Some(North), baz: NewBool(true) }`
|
||||
Foo { bar: None, baz: NewBool(true) } => (),
|
||||
Foo { bar: _, baz: NEW_FALSE } => (),
|
||||
Foo { bar: Some(West), baz: NewBool(true) } => (),
|
||||
Foo { bar: Some(South), .. } => (),
|
||||
Foo { bar: Some(EAST), .. } => ()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
nonexhaustive_1();
|
||||
nonexhaustive_2();
|
||||
nonexhaustive_3();
|
||||
}
|
||||
|
@ -7,10 +7,16 @@
|
||||
// <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.
|
||||
|
||||
#![allow(dead_code)]
|
||||
#![deny(unreachable_patterns)]
|
||||
|
||||
use self::Direction::{North, East, South, West};
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
struct NewBool(bool);
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
enum Direction {
|
||||
North,
|
||||
East,
|
||||
@ -20,15 +26,6 @@ enum Direction {
|
||||
|
||||
const TRUE_TRUE: (bool, bool) = (true, true);
|
||||
|
||||
fn nonexhaustive_1() {
|
||||
match (true, false) {
|
||||
//~^ ERROR non-exhaustive patterns: `(true, false)` not covered
|
||||
TRUE_TRUE => (),
|
||||
(false, false) => (),
|
||||
(false, true) => ()
|
||||
}
|
||||
}
|
||||
|
||||
fn unreachable_1() {
|
||||
match (true, false) {
|
||||
TRUE_TRUE => (),
|
||||
@ -43,17 +40,6 @@ fn unreachable_1() {
|
||||
const NONE: Option<Direction> = None;
|
||||
const EAST: Direction = East;
|
||||
|
||||
fn nonexhaustive_2() {
|
||||
match Some(Some(North)) {
|
||||
//~^ ERROR non-exhaustive patterns: `Some(Some(West))` not covered
|
||||
Some(NONE) => (),
|
||||
Some(Some(North)) => (),
|
||||
Some(Some(EAST)) => (),
|
||||
Some(Some(South)) => (),
|
||||
None => ()
|
||||
}
|
||||
}
|
||||
|
||||
fn unreachable_2() {
|
||||
match Some(Some(North)) {
|
||||
Some(NONE) => (),
|
||||
@ -73,19 +59,6 @@ struct Foo {
|
||||
baz: NewBool
|
||||
}
|
||||
|
||||
const STATIC_FOO: Foo = Foo { bar: None, baz: NEW_FALSE };
|
||||
|
||||
fn nonexhaustive_3() {
|
||||
match (Foo { bar: Some(North), baz: NewBool(true) }) {
|
||||
//~^ ERROR non-exhaustive patterns: `Foo { bar: Some(North), baz: NewBool(true) }`
|
||||
Foo { bar: None, baz: NewBool(true) } => (),
|
||||
Foo { bar: _, baz: NEW_FALSE } => (),
|
||||
Foo { bar: Some(West), baz: NewBool(true) } => (),
|
||||
Foo { bar: Some(South), .. } => (),
|
||||
Foo { bar: Some(EAST), .. } => ()
|
||||
}
|
||||
}
|
||||
|
||||
fn unreachable_3() {
|
||||
match (Foo { bar: Some(EAST), baz: NewBool(true) }) {
|
||||
Foo { bar: None, baz: NewBool(true) } => (),
|
||||
@ -100,9 +73,6 @@ fn unreachable_3() {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
nonexhaustive_1();
|
||||
nonexhaustive_2();
|
||||
nonexhaustive_3();
|
||||
unreachable_1();
|
||||
unreachable_2();
|
||||
unreachable_3();
|
||||
|
26
src/test/compile-fail/match-byte-array-patterns-2.rs
Normal file
26
src/test/compile-fail/match-byte-array-patterns-2.rs
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
#![feature(advanced_slice_patterns, slice_patterns)]
|
||||
|
||||
fn main() {
|
||||
let buf = &[0, 1, 2, 3];
|
||||
|
||||
match buf { //~ ERROR non-exhaustive
|
||||
b"AAAA" => {}
|
||||
}
|
||||
|
||||
let buf: &[u8] = buf;
|
||||
|
||||
match buf { //~ ERROR non-exhaustive
|
||||
b"AAAA" => {}
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(advanced_slice_patterns, slice_patterns)]
|
||||
#![deny(unreachable_patterns)]
|
||||
|
||||
fn main() {
|
||||
let buf = &[0, 1, 2, 3];
|
||||
@ -37,10 +38,6 @@ fn main() {
|
||||
_ => {}
|
||||
}
|
||||
|
||||
match buf { //~ ERROR non-exhaustive
|
||||
b"AAAA" => {}
|
||||
}
|
||||
|
||||
let buf: &[u8] = buf;
|
||||
|
||||
match buf {
|
||||
@ -66,8 +63,4 @@ fn main() {
|
||||
b"AAAA" => {}, //~ ERROR unreachable pattern
|
||||
_ => {}
|
||||
}
|
||||
|
||||
match buf { //~ ERROR non-exhaustive
|
||||
b"AAAA" => {}
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,8 @@
|
||||
//error-pattern: unreachable
|
||||
//error-pattern: unreachable
|
||||
|
||||
#![deny(unreachable_patterns)]
|
||||
|
||||
fn main() {
|
||||
match 5 {
|
||||
1 ... 10 => { }
|
||||
|
@ -9,6 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(slice_patterns)]
|
||||
#![deny(unreachable_patterns)]
|
||||
|
||||
// The arity of `ref x` is always 1. If the pattern is compared to some non-structural type whose
|
||||
// arity is always 0, an ICE occurs.
|
||||
@ -19,7 +20,7 @@ fn main() {
|
||||
let homura = [1, 2, 3];
|
||||
|
||||
match homura {
|
||||
[1, ref madoka, 3] => (),
|
||||
[1, ref _madoka, 3] => (),
|
||||
[1, 2, 3] => (), //~ ERROR unreachable pattern
|
||||
[_, _, _] => (),
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(slice_patterns)]
|
||||
#![deny(unreachable_patterns)]
|
||||
|
||||
fn a() {
|
||||
let v = [1, 2, 3];
|
||||
|
@ -9,13 +9,14 @@
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(slice_patterns)]
|
||||
#![deny(unreachable_patterns)]
|
||||
|
||||
fn main() {
|
||||
let x: Vec<(isize, isize)> = Vec::new();
|
||||
let x: &[(isize, isize)] = &x;
|
||||
match *x {
|
||||
[a, (2, 3), _] => (),
|
||||
[(1, 2), (2, 3), b] => (), //~ ERROR unreachable pattern
|
||||
[_, (2, 3), _] => (),
|
||||
[(1, 2), (2, 3), _] => (), //~ ERROR unreachable pattern
|
||||
_ => ()
|
||||
}
|
||||
|
||||
@ -24,7 +25,7 @@ fn main() {
|
||||
"baz".to_string()];
|
||||
let x: &[String] = &x;
|
||||
match *x {
|
||||
[a, _, _, ..] => { println!("{}", a); }
|
||||
[ref a, _, _, ..] => { println!("{}", a); }
|
||||
[_, _, _, _, _] => { } //~ ERROR unreachable pattern
|
||||
_ => { }
|
||||
}
|
||||
|
@ -8,6 +8,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![deny(unreachable_patterns)]
|
||||
|
||||
struct Foo {
|
||||
x: isize,
|
||||
y: isize,
|
||||
@ -16,7 +18,7 @@ struct Foo {
|
||||
pub fn main() {
|
||||
let a = Foo { x: 1, y: 2 };
|
||||
match a {
|
||||
Foo { x: x, y: y } => (),
|
||||
Foo { x: _x, y: _y } => (),
|
||||
Foo { .. } => () //~ ERROR unreachable pattern
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,16 @@
|
||||
|
||||
#![feature(box_patterns)]
|
||||
#![feature(box_syntax)]
|
||||
#![allow(dead_code)]
|
||||
#![deny(unreachable_patterns)]
|
||||
|
||||
enum foo { a(Box<foo>, isize), b(usize), }
|
||||
enum Foo { A(Box<Foo>, isize), B(usize), }
|
||||
|
||||
fn main() {
|
||||
match Foo::B(1) {
|
||||
Foo::B(_) | Foo::A(box _, 1) => { }
|
||||
Foo::A(_, 1) => { }
|
||||
_ => { }
|
||||
}
|
||||
}
|
||||
|
||||
fn main() { match foo::b(1) { foo::b(_) | foo::a(box _, 1) => { } foo::a(_, 1) => { } } }
|
||||
|
Loading…
x
Reference in New Issue
Block a user