Skip to content

labelify the check_match errors #35308

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 75 additions & 65 deletions src/librustc_const_eval/check_match.rs
Original file line number Diff line number Diff line change
@@ -31,6 +31,7 @@ use rustc::ty;
use std::cmp::Ordering;
use std::fmt;
use std::iter::{FromIterator, IntoIterator, repeat};
use std::mem;

use rustc::hir;
use rustc::hir::{Pat, PatKind};
@@ -214,19 +215,8 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &hir::Expr) {
// Finally, check if the whole match expression is exhaustive.
// Check for empty enum, because is_useful only works on inhabited types.
let pat_ty = cx.tcx.node_id_to_type(scrut.id);
if inlined_arms.is_empty() {
if !pat_ty.is_empty(cx.tcx) {
// We know the type is inhabited, so this must be wrong
let mut err = struct_span_err!(cx.tcx.sess, ex.span, E0002,
"non-exhaustive patterns: type {} is non-empty",
pat_ty);
span_help!(&mut err, ex.span,
"Please ensure that all possible cases are being handled; \
possibly adding wildcards or more match arms.");
err.emit();
}
// If the type *is* empty, it's vacuously exhaustive
return;
if inlined_arms.is_empty() && pat_ty.is_empty(cx.tcx) {
return
}

let matrix: Matrix = inlined_arms
@@ -235,12 +225,7 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &hir::Expr) {
.flat_map(|arm| &arm.0)
.map(|pat| vec![wrap_pat(cx, &pat)])
.collect();
let match_span = Span {
lo: ex.span.lo,
hi: scrut.span.hi,
expn_id: ex.span.expn_id
};
check_exhaustive(cx, match_span, &matrix, source);
check_exhaustive(cx, scrut.span, &matrix, source);
},
_ => ()
}
@@ -316,7 +301,10 @@ fn check_arms(cx: &MatchCheckCtxt,
let &(ref first_arm_pats, _) = &arms[0];
let first_pat = &first_arm_pats[0];
let span = first_pat.span;
span_err!(cx.tcx.sess, span, E0162, "irrefutable if-let pattern");
struct_span_err!(
cx.tcx.sess, span, E0162, "irrefutable if-let pattern")
.span_label(span, &"this pattern always applies")
.emit();
printed_if_let_err = true;
}
},
@@ -326,7 +314,10 @@ fn check_arms(cx: &MatchCheckCtxt,
let &(ref first_arm_pats, _) = &arms[0];
let first_pat = &first_arm_pats[0];
let span = first_pat.span;
span_err!(cx.tcx.sess, span, E0165, "irrefutable while-let pattern");
struct_span_err!(
cx.tcx.sess, span, E0165, "irrefutable while-let pattern")
.span_label(span, &"this pattern always applies")
.emit();
},

hir::MatchSource::ForLoopDesugar => {
@@ -338,17 +329,17 @@ fn check_arms(cx: &MatchCheckCtxt,
},

hir::MatchSource::Normal => {
let mut err = struct_span_err!(cx.tcx.sess, pat.span, E0001,
"unreachable pattern");
err.span_label(pat.span, &format!("this is an unreachable pattern"));
let mut diag = struct_span_err!(cx.tcx.sess, pat.span, E0001,
"unreachable pattern");
diag.span_label(pat.span, &"this pattern cannot be reached");
// if we had a catchall pattern, hint at that
for row in &seen.0 {
if pat_is_catchall(&cx.tcx.def_map.borrow(), row[0].0) {
span_note!(err, row[0].0.span,
"this pattern matches any value");
diag.span_label(row[0].0.span,
&"this pattern matches any value");
}
}
err.emit();
diag.emit();
},

hir::MatchSource::TryDesugar => {
@@ -407,10 +398,18 @@ fn check_exhaustive<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>,
},
_ => bug!(),
};
span_err!(cx.tcx.sess, sp, E0297,
"refutable pattern in `for` loop binding: \
`{}` not covered",
pat_to_string(witness));
let pat = matrix.0[0][0].0;
let span = match pat.node {
hir::PatKind::TupleStruct(_, ref subpats, _) => subpats.get(0),
_ => None
}.unwrap_or_else(|| {
span_bug!(pat.span, "bad for-loop desugaring {:?}", pat);
}).span;
struct_span_err!(cx.tcx.sess, span, E0297,
"refutable pattern in `for` loop binding")
.span_label(span, &format!("`{}` not covered",
pat_to_string(witness)))
.emit();
},
_ => {
let pattern_strings: Vec<_> = witnesses.iter().map(|w| {
@@ -429,15 +428,10 @@ fn check_exhaustive<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>,
format!("`{}` and {} more", head.join("`, `"), tail.len())
}
};

let label_text = match pattern_strings.len(){
1 => format!("pattern {} not covered", joined_patterns),
_ => format!("patterns {} not covered", joined_patterns)
};
struct_span_err!(cx.tcx.sess, sp, E0004,
"non-exhaustive patterns: {} not covered",
joined_patterns
).span_label(sp, &label_text).emit();
"non-exhaustive patterns")
.span_label(sp, &format!("{} not covered", joined_patterns))
.emit();
},
}
}
@@ -520,8 +514,11 @@ impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> {
}
} else {
self.failed = true;
span_err!(self.tcx.sess, pat.span, E0158,
"statics cannot be referenced in patterns");
struct_span_err!(
self.tcx.sess, pat.span, E0158,
"unresolvable constant in pattern")
.span_label(pat.span, &"unresolvable constant here")
.emit();
pat
}
}
@@ -1075,11 +1072,11 @@ fn check_irrefutable(cx: &MatchCheckCtxt, pat: &Pat, is_fn_arg: bool) {
};

is_refutable(cx, pat, |uncovered_pat| {
span_err!(cx.tcx.sess, pat.span, E0005,
"refutable pattern in {}: `{}` not covered",
origin,
pat_to_string(uncovered_pat),
);
struct_span_err!(cx.tcx.sess, pat.span, E0005,
"refutable pattern in {}", origin)
.span_label(pat.span, &format!(
"`{}` not covered here", pat_to_string(uncovered_pat)))
.emit();
});
}

@@ -1111,16 +1108,20 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
// check legality of moving out of the enum

// x @ Foo(..) is legal, but x @ Foo(y) isn't.
if sub.map_or(false, |p| pat_contains_bindings(&p)) {
span_err!(cx.tcx.sess, p.span, E0007, "cannot bind by-move with sub-bindings");
let mut diag = if sub.map_or(false, |p| pat_contains_bindings(&p)) {
struct_span_err!(cx.tcx.sess, p.span, E0007, "cannot bind by-move with sub-bindings")
} else if has_guard {
span_err!(cx.tcx.sess, p.span, E0008, "cannot bind by-move into a pattern guard");
struct_span_err!(cx.tcx.sess, p.span, E0008, "cannot bind by-move into a pattern guard")
} else if by_ref_span.is_some() {
let mut err = struct_span_err!(cx.tcx.sess, p.span, E0009,
"cannot bind by-move and by-ref in the same pattern");
span_note!(&mut err, by_ref_span.unwrap(), "by-ref binding occurs here");
err.emit();
}
let mut diag = struct_span_err!(cx.tcx.sess, p.span, E0009,
"cannot bind by-move and by-ref in the same pattern");
diag.span_label(by_ref_span.unwrap(), &"by-ref binding occurs here");
diag
} else {
return
};
diag.span_label(p.span, &"invalid by-move binding here");
diag.emit();
};

for pat in pats {
@@ -1171,8 +1172,10 @@ impl<'a, 'gcx, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'gcx> {
_: LoanCause) {
match kind {
MutBorrow => {
span_err!(self.cx.tcx.sess, span, E0301,
"cannot mutably borrow in a pattern guard")
struct_span_err!(self.cx.tcx.sess, span, E0301,
"cannot mutably borrow in a pattern guard")
.span_label(span, &"bad mutable borrow here")
.emit();
}
ImmBorrow | UniqueImmBorrow => {}
}
@@ -1181,7 +1184,10 @@ impl<'a, 'gcx, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'gcx> {
fn mutate(&mut self, _: NodeId, span: Span, _: cmt, mode: MutateMode) {
match mode {
MutateMode::JustWrite | MutateMode::WriteAndRead => {
span_err!(self.cx.tcx.sess, span, E0302, "cannot assign in a pattern guard")
struct_span_err!(
self.cx.tcx.sess, span, E0302, "cannot assign in a pattern guard")
.span_label(span, &"bad assignment here")
.emit();
}
MutateMode::Init => {}
}
@@ -1192,28 +1198,32 @@ impl<'a, 'gcx, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'gcx> {
/// because of the way rvalues are handled in the borrow check. (See issue
/// #14587.)
fn check_legality_of_bindings_in_at_patterns(cx: &MatchCheckCtxt, pat: &Pat) {
AtBindingPatternVisitor { cx: cx, bindings_allowed: true }.visit_pat(pat);
AtBindingPatternVisitor { cx: cx, containing_binding: None }.visit_pat(pat);
}

struct AtBindingPatternVisitor<'a, 'b:'a, 'tcx:'b> {
cx: &'a MatchCheckCtxt<'b, 'tcx>,
bindings_allowed: bool
containing_binding: Option<Span>,
}

impl<'a, 'b, 'tcx, 'v> Visitor<'v> for AtBindingPatternVisitor<'a, 'b, 'tcx> {
fn visit_pat(&mut self, pat: &Pat) {
match pat.node {
PatKind::Binding(_, _, ref subpat) => {
if !self.bindings_allowed {
span_err!(self.cx.tcx.sess, pat.span, E0303,
"pattern bindings are not allowed after an `@`");
if let Some(containing_binding) = self.containing_binding {
struct_span_err!(
self.cx.tcx.sess, pat.span, E0303,
"nested pattern bindings are invalid")
.span_label(pat.span, &"invalid nested binding here")
.span_label(containing_binding, &"within this binding")
.emit();
}

if subpat.is_some() {
let bindings_were_allowed = self.bindings_allowed;
self.bindings_allowed = false;
let containing_binding = mem::replace(
&mut self.containing_binding, Some(pat.span));
intravisit::walk_pat(self, pat);
self.bindings_allowed = bindings_were_allowed;
self.containing_binding = containing_binding;
}
}
_ => intravisit::walk_pat(self, pat),
54 changes: 2 additions & 52 deletions src/librustc_const_eval/diagnostics.rs
Original file line number Diff line number Diff line change
@@ -40,37 +40,6 @@ Ensure the ordering of the match arm is correct and remove any superfluous
arms.
"##,

E0002: r##"
This error indicates that an empty match expression is invalid because the type
it is matching on is non-empty (there exist values of this type). In safe code
it is impossible to create an instance of an empty type, so empty match
expressions are almost never desired. This error is typically fixed by adding
one or more cases to the match expression.

An example of an empty type is `enum Empty { }`. So, the following will work:

```
enum Empty {}

fn foo(x: Empty) {
match x {
// empty
}
}
```

However, this won't:

```compile_fail
fn foo(x: Option<String>) {
match x {
// empty
}
}
```
"##,


E0003: r##"
Not-a-Number (NaN) values cannot be compared for equality and hence can never
match the input to a match expression. So, the following will not compile:
@@ -325,27 +294,6 @@ match x {
```
"##,

E0158: r##"
`const` and `static` mean different things. A `const` is a compile-time
constant, an alias for a literal value. This property means you can match it
directly within a pattern.

The `static` keyword, on the other hand, guarantees a fixed location in memory.
This does not always mean that the value is constant. For example, a global
mutex can be declared `static` as well.

If you want to match against a `static`, consider using a guard instead:

```
static FORTY_TWO: i32 = 42;

match Some(42) {
Some(x) if x == FORTY_TWO => {}
_ => {}
}
```
"##,

E0162: r##"
An if-let pattern attempts to match the pattern, and enters the body if the
match was successful. If the match is irrefutable (when it cannot fail to
@@ -594,6 +542,8 @@ let x = [0i32; 2];


register_diagnostics! {
// E0002, // duplicated from E0001
E0158, // cannot resolve constant in pattern
E0298, // cannot compare constants
// E0299, // mismatched types between arms
// E0471, // constant evaluation error (in pattern)
15 changes: 0 additions & 15 deletions src/test/compile-fail/E0002.rs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -28,8 +28,10 @@ impl Foo for Def {

pub fn test<A: Foo, B: Foo>(arg: EFoo) {
match arg {
A::X => println!("A::X"), //~ error: statics cannot be referenced in patterns [E0158]
B::X => println!("B::X"), //~ error: statics cannot be referenced in patterns [E0158]
A::X => println!("A::X"), //~ ERROR E0158
//~| unresolvable constant here
B::X => println!("B::X"), //~ ERROR E0158
//~| unresolvable constant here
_ => (),
}
}
1 change: 1 addition & 0 deletions src/test/compile-fail/E0162.rs
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@ struct Irrefutable(i32);
fn main() {
let irr = Irrefutable(0);
if let Irrefutable(x) = irr { //~ ERROR E0162
//~| this pattern always applies
println!("{}", x);
}
}
Original file line number Diff line number Diff line change
@@ -17,9 +17,9 @@ pub mod b {
pub fn key(e: ::E) -> &'static str {
match e {
A => "A",
//~^ WARN pattern binding `A` is named the same as one of the variants of the type `E`
//~^ WARN pattern binding `A` is named the same as one of the variants of the type `E` [E0170]
B => "B", //~ ERROR: unreachable pattern
//~^ WARN pattern binding `B` is named the same as one of the variants of the type `E`
//~^ WARN pattern binding `B` is named the same as one of the variants of the type `E` [E0170]
}
}
}
9 changes: 7 additions & 2 deletions src/test/compile-fail/E0297.rs
Original file line number Diff line number Diff line change
@@ -9,7 +9,12 @@
// except according to those terms.

fn main() {
let xs : Vec<Option<i32>> = vec!(Some(1), None);
for
&0
//~^ ERROR refutable pattern in `for` loop binding [E0297]
//~| `&_` not covered
in [1].iter()
{

for Some(x) in xs {} //~ ERROR E0297
}
}
15 changes: 11 additions & 4 deletions src/test/compile-fail/E0301.rs
Original file line number Diff line number Diff line change
@@ -8,10 +8,17 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

fn mangle(x: &mut Option<u32>) -> bool { *x = None; false }

fn main() {
match Some(()) {
None => { },
option if option.take().is_none() => {}, //~ ERROR E0301
Some(_) => { }
let ref mut x = Some(4);
match x {
&mut None => {}
&mut Some(_) if
mangle(
x //~ ERROR E0301
)
=> {}
&mut Some(_) => {}
}
}
14 changes: 10 additions & 4 deletions src/test/compile-fail/E0302.rs
Original file line number Diff line number Diff line change
@@ -9,9 +9,15 @@
// except according to those terms.

fn main() {
match Some(()) {
None => { },
option if { option = None; false } => { }, //~ ERROR E0302
Some(_) => { }
let ref mut x = Some(4);
match x {
&mut None => {}
&mut Some(_) if
{
*x = None; //~ ERROR E0302
false
}
=> {}
&mut Some(_) => {}
}
}
7 changes: 3 additions & 4 deletions src/test/compile-fail/E0303.rs
Original file line number Diff line number Diff line change
@@ -9,9 +9,8 @@
// except according to those terms.

fn main() {
match Some("hi".to_string()) {
ref op_string_ref @ Some(s) => {}, //~ ERROR E0303
//~^ ERROR E0009
None => {},
match 0 {
ref mut x @ y //~ ERROR E0303
=> {}
}
}
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@ fn main() {
let x = Some((X { x: () }, X { x: () }));
match x {
Some((ref _y, _z)) => { }, //~ ERROR cannot bind by-move and by-ref in the same pattern
//~| invalid by-move binding here
None => panic!()
}
}
Original file line number Diff line number Diff line change
@@ -23,6 +23,7 @@ fn main() {
match x {
double_option::some2(ref _y, _z) => { },
//~^ ERROR cannot bind by-move and by-ref in the same pattern
//~| invalid by-move binding here
double_option::none2 => panic!()
}
}
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@ fn main() {
let x = Some((X { x: () }, X { x: () }));
match x {
Some((_y, ref _z)) => { }, //~ ERROR cannot bind by-move and by-ref in the same pattern
//~| invalid by-move binding here
None => panic!()
}
}
1 change: 1 addition & 0 deletions src/test/compile-fail/bind-by-move-no-guards.rs
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@ fn main() {
match x {
Some(z) if z.recv().unwrap() => { panic!() },
//~^ ERROR cannot bind by-move into a pattern guard
//~| invalid by-move binding here
Some(z) => { assert!(!z.recv().unwrap()); },
None => panic!()
}
13 changes: 0 additions & 13 deletions src/test/compile-fail/for-loop-refutable-pattern-error-message.rs

This file was deleted.

3 changes: 2 additions & 1 deletion src/test/compile-fail/issue-15129.rs
Original file line number Diff line number Diff line change
@@ -20,7 +20,8 @@ pub enum V {

fn main() {
match (T::T1(()), V::V2(true)) {
//~^ ERROR non-exhaustive patterns: `(T1(()), V2(_))` not covered
//~^ ERROR non-exhaustive patterns
//~| `(T1(()), V2(_))` not covered
(T::T1(()), V::V1(i)) => (),
(T::T2(()), V::V2(b)) => ()
}
3 changes: 2 additions & 1 deletion src/test/compile-fail/issue-15381.rs
Original file line number Diff line number Diff line change
@@ -14,7 +14,8 @@ fn main() {
let values: Vec<u8> = vec![1,2,3,4,5,6,7,8];

for &[x,y,z] in values.chunks(3).filter(|&xs| xs.len() == 3) {
//~^ ERROR refutable pattern in `for` loop binding: `&[]` not covered
//~^ ERROR refutable pattern in `for` loop binding
//~| `&[]` not covered
println!("y={}", y);
}
}
3 changes: 2 additions & 1 deletion src/test/compile-fail/issue-2111.rs
Original file line number Diff line number Diff line change
@@ -10,7 +10,8 @@

fn foo(a: Option<usize>, b: Option<usize>) {
match (a,b) {
//~^ ERROR: non-exhaustive patterns: `(None, None)` not covered
//~^ ERROR: non-exhaustive patterns
//~| `(None, None)` not covered
(Some(a), Some(b)) if a == b => { }
(Some(_), None) |
(None, Some(_)) => { }
6 changes: 4 additions & 2 deletions src/test/compile-fail/issue-30240.rs
Original file line number Diff line number Diff line change
@@ -9,11 +9,13 @@
// except according to those terms.

fn main() {
match "world" { //~ ERROR non-exhaustive patterns: `&_`
match "world" { //~ ERROR non-exhaustive patterns
//~| `&_` not covered
"hello" => {}
}

match "world" { //~ ERROR non-exhaustive patterns: `&_`
match "world" { //~ ERROR non-exhaustive patterns
//~| `&_` not covered
ref _x if false => {}
"hello" => {}
"hello" => {} //~ ERROR unreachable pattern
8 changes: 4 additions & 4 deletions src/test/compile-fail/issue-31221.rs
Original file line number Diff line number Diff line change
@@ -22,15 +22,15 @@ fn main() {
//~^ NOTE this pattern matches any value
Var2 => (),
//~^ ERROR unreachable pattern
//~^^ NOTE this is an unreachable pattern
//~| NOTE this pattern cannot be reached
};
match &s {
&Var1 => (),
&Var3 => (),
//~^ NOTE this pattern matches any value
&Var2 => (),
//~^ ERROR unreachable pattern
//~^^ NOTE this is an unreachable pattern
//~| NOTE this pattern cannot be reached
};
let t = (Var1, Var1);
match t {
@@ -39,7 +39,7 @@ fn main() {
//~^ NOTE this pattern matches any value
anything => ()
//~^ ERROR unreachable pattern
//~^^ NOTE this is an unreachable pattern
//~| NOTE this pattern cannot be reached
};
// `_` need not emit a note, it is pretty obvious already.
let t = (Var1, Var1);
@@ -48,6 +48,6 @@ fn main() {
_ => (),
anything => ()
//~^ ERROR unreachable pattern
//~^^ NOTE this is an unreachable pattern
//~| NOTE this pattern cannot be reached
};
}
3 changes: 2 additions & 1 deletion src/test/compile-fail/issue-31561.rs
Original file line number Diff line number Diff line change
@@ -16,5 +16,6 @@ enum Thing {

fn main() {
let Thing::Foo(y) = Thing::Foo(1);
//~^ ERROR refutable pattern in local binding: `Bar` not covered
//~^ ERROR refutable pattern in local binding
//~| `Bar` not covered
}
3 changes: 2 additions & 1 deletion src/test/compile-fail/issue-4321.rs
Original file line number Diff line number Diff line change
@@ -10,7 +10,8 @@

fn main() {
let tup = (true, true);
println!("foo {:}", match tup { //~ ERROR non-exhaustive patterns: `(true, false)` not covered
println!("foo {:}", match tup { //~ ERROR non-exhaustive patterns
//~| `(true, false)` not covered
(false, false) => "foo",
(false, true) => "bar",
(true, true) => "baz"
9 changes: 6 additions & 3 deletions src/test/compile-fail/match-arm-statics.rs
Original file line number Diff line number Diff line change
@@ -22,7 +22,8 @@ const TRUE_TRUE: (bool, bool) = (true, true);

fn nonexhaustive_1() {
match (true, false) {
//~^ ERROR non-exhaustive patterns: `(true, false)` not covered
//~^ ERROR non-exhaustive patterns
//~| `(true, false)` not covered
TRUE_TRUE => (),
(false, false) => (),
(false, true) => ()
@@ -45,7 +46,8 @@ const EAST: Direction = East;

fn nonexhaustive_2() {
match Some(Some(North)) {
//~^ ERROR non-exhaustive patterns: `Some(Some(West))` not covered
//~^ ERROR non-exhaustive patterns
//~| `Some(Some(West))` not covered
Some(NONE) => (),
Some(Some(North)) => (),
Some(Some(EAST)) => (),
@@ -77,7 +79,8 @@ 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) }`
//~^ 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) } => (),
6 changes: 4 additions & 2 deletions src/test/compile-fail/non-exhaustive-match-nested.rs
Original file line number Diff line number Diff line change
@@ -14,7 +14,8 @@ enum t { a(u), b }
enum u { c, d }

fn match_nested_vecs<'a, T>(l1: Option<&'a [T]>, l2: Result<&'a [T], ()>) -> &'static str {
match (l1, l2) { //~ ERROR non-exhaustive patterns: `(Some(&[]), Err(_))` not covered
match (l1, l2) { //~ ERROR non-exhaustive patterns
//~| `(Some(&[]), Err(_))` not covered
(Some(&[]), Ok(&[])) => "Some(empty), Ok(empty)",
(Some(&[_, ..]), Ok(_)) | (Some(&[_, ..]), Err(())) => "Some(non-empty), any",
(None, Ok(&[])) | (None, Err(())) | (None, Ok(&[_])) => "None, Ok(less than one element)",
@@ -24,7 +25,8 @@ fn match_nested_vecs<'a, T>(l1: Option<&'a [T]>, l2: Result<&'a [T], ()>) -> &'s

fn main() {
let x = t::a(u::c);
match x { //~ ERROR non-exhaustive patterns: `a(c)` not covered
match x { //~ ERROR non-exhaustive patterns
//~| `a(c)` not covered
t::a(u::d) => { panic!("hello"); }
t::b => { panic!("goodbye"); }
}
24 changes: 16 additions & 8 deletions src/test/compile-fail/non-exhaustive-match.rs
Original file line number Diff line number Diff line change
@@ -14,21 +14,27 @@ enum t { a, b, }

fn main() {
let x = t::a;
match x { t::b => { } } //~ ERROR non-exhaustive patterns: `a` not covered
match true { //~ ERROR non-exhaustive patterns: `false` not covered
match x { t::b => { } } //~ ERROR non-exhaustive patterns
//~| `a` not covered
match true { //~ ERROR non-exhaustive patterns
//~| `false` not covered
true => {}
}
match Some(10) { //~ ERROR non-exhaustive patterns: `Some(_)` not covered
match Some(10) { //~ ERROR non-exhaustive patterns
//~| `Some(_)` not covered
None => {}
}
match (2, 3, 4) { //~ ERROR non-exhaustive patterns: `(_, _, _)` not covered
match (2, 3, 4) { //~ ERROR non-exhaustive patterns
//~| `(_, _, _)` not covered
(_, _, 4) => {}
}
match (t::a, t::a) { //~ ERROR non-exhaustive patterns: `(a, a)` not covered
match (t::a, t::a) { //~ ERROR non-exhaustive patterns
//~| `(a, a)` not covered
(t::a, t::b) => {}
(t::b, t::a) => {}
}
match t::a { //~ ERROR non-exhaustive patterns: `b` not covered
match t::a { //~ ERROR non-exhaustive patterns
//~| `b` not covered
t::a => {}
}
// This is exhaustive, though the algorithm got it wrong at one point
@@ -39,7 +45,8 @@ fn main() {
}
let vec = vec!(Some(42), None, Some(21));
let vec: &[Option<isize>] = &vec;
match *vec { //~ ERROR non-exhaustive patterns: `[]` not covered
match *vec { //~ ERROR non-exhaustive patterns
//~| `[]` not covered
[Some(..), None, ref tail..] => {}
[Some(..), Some(..), ref tail..] => {}
[None] => {}
@@ -52,7 +59,8 @@ fn main() {
}
let vec = vec!(0.5f32);
let vec: &[f32] = &vec;
match *vec { //~ ERROR non-exhaustive patterns: `[_, _, _, _]` not covered
match *vec { //~ ERROR non-exhaustive patterns
//~| `[_, _, _, _]` not covered
[0.1, 0.2, 0.3] => (),
[0.1, 0.2] => (),
[0.1] => (),
28 changes: 14 additions & 14 deletions src/test/compile-fail/non-exhaustive-pattern-witness.rs
Original file line number Diff line number Diff line change
@@ -18,8 +18,8 @@ struct Foo {

fn struct_with_a_nested_enum_and_vector() {
match (Foo { first: true, second: None }) {
//~^ ERROR non-exhaustive patterns: `Foo { first: false, second: Some([_, _, _, _]) }` not covered
//~| NOTE pattern `Foo { first: false, second: Some([_, _, _, _]) }` not covered
//~^ ERROR non-exhaustive patterns
//~| `Foo { first: false, second: Some([_, _, _, _]) }` not covered
Foo { first: true, second: None } => (),
Foo { first: true, second: Some(_) } => (),
Foo { first: false, second: None } => (),
@@ -35,8 +35,8 @@ enum Color {

fn enum_with_single_missing_variant() {
match Color::Red {
//~^ ERROR non-exhaustive patterns: `Red` not covered
//~| NOTE pattern `Red` not covered
//~^ ERROR non-exhaustive patterns
//~| `Red` not covered
Color::CustomRGBA { .. } => (),
Color::Green => ()
}
@@ -48,8 +48,8 @@ enum Direction {

fn enum_with_multiple_missing_variants() {
match Direction::North {
//~^ ERROR non-exhaustive patterns: `East`, `South` and `West` not covered
//~| NOTE patterns `East`, `South` and `West` not covered
//~^ ERROR non-exhaustive patterns
//~| `East`, `South` and `West` not covered
Direction::North => ()
}
}
@@ -60,17 +60,17 @@ enum ExcessiveEnum {

fn enum_with_excessive_missing_variants() {
match ExcessiveEnum::First {
//~^ ERROR `Second`, `Third`, `Fourth` and 8 more not covered
//~| NOTE patterns `Second`, `Third`, `Fourth` and 8 more not covered
//~^ ERROR non-exhaustive patterns
//~| `Second`, `Third`, `Fourth` and 8 more not covered

ExcessiveEnum::First => ()
}
}

fn enum_struct_variant() {
match Color::Red {
//~^ ERROR non-exhaustive patterns: `CustomRGBA { a: true, .. }` not covered
//~| NOTE pattern `CustomRGBA { a: true, .. }` not covered
//~^ ERROR non-exhaustive patterns
//~| `CustomRGBA { a: true, .. }` not covered
Color::Red => (),
Color::Green => (),
Color::CustomRGBA { a: false, r: _, g: _, b: 0 } => (),
@@ -86,8 +86,8 @@ enum Enum {
fn vectors_with_nested_enums() {
let x: &'static [Enum] = &[Enum::First, Enum::Second(false)];
match *x {
//~^ ERROR non-exhaustive patterns: `[Second(true), Second(false)]` not covered
//~| NOTE pattern `[Second(true), Second(false)]` not covered
//~^ ERROR non-exhaustive patterns
//~| `[Second(true), Second(false)]` not covered
[] => (),
[_] => (),
[Enum::First, _] => (),
@@ -100,8 +100,8 @@ fn vectors_with_nested_enums() {

fn missing_nil() {
match ((), false) {
//~^ ERROR non-exhaustive patterns: `((), false)` not covered
//~| NOTE pattern `((), false)` not covered
//~^ ERROR non-exhaustive patterns
//~| `((), false)` not covered
((), true) => ()
}
}
7 changes: 5 additions & 2 deletions src/test/compile-fail/pattern-bindings-after-at.rs
Original file line number Diff line number Diff line change
@@ -15,8 +15,11 @@ enum Option<T> {

fn main() {
match &mut Some(1) {
ref mut z @ &mut Some(ref a) => {
//~^ ERROR pattern bindings are not allowed after an `@`
ref mut z
//~^ NOTE within this binding
@ &mut Some(ref a) => {
//~^ ERROR nested pattern bindings are invalid
//~| invalid nested binding here
**z = None;
println!("{}", *a);
}
6 changes: 4 additions & 2 deletions src/test/compile-fail/refutable-pattern-errors.rs
Original file line number Diff line number Diff line change
@@ -10,9 +10,11 @@


fn func((1, (Some(1), 2...3)): (isize, (Option<isize>, isize))) { }
//~^ ERROR refutable pattern in function argument: `(_, _)` not covered
//~^ ERROR refutable pattern in function argument
//~| `(_, _)` not covered

fn main() {
let (1, (Some(1), 2...3)) = (1, (None, 2));
//~^ ERROR refutable pattern in local binding: `(_, _)` not covered
//~^ ERROR refutable pattern in local binding
//~| `(_, _)` not covered
}
3 changes: 2 additions & 1 deletion src/test/compile-fail/refutable-pattern-in-fn-arg.rs
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@

fn main() {
let f = |3: isize| println!("hello");
//~^ ERROR refutable pattern in function argument: `_` not covered
//~^ ERROR refutable pattern in function argument
//~| `_` not covered
f(4);
}