diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index 599e3ec871a83..cefca1b61e0ea 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -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, } 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), diff --git a/src/librustc_const_eval/diagnostics.rs b/src/librustc_const_eval/diagnostics.rs index 9cdc76f25a63f..ff77ece973bbe 100644 --- a/src/librustc_const_eval/diagnostics.rs +++ b/src/librustc_const_eval/diagnostics.rs @@ -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) { - 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) diff --git a/src/test/compile-fail/E0002.rs b/src/test/compile-fail/E0002.rs deleted file mode 100644 index 0e94c9595d82c..0000000000000 --- a/src/test/compile-fail/E0002.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn main() { - let x = Some(1); - - match x { } //~ ERROR E0002 -} diff --git a/src/test/compile-fail/associated-const-type-parameter-arms.rs b/src/test/compile-fail/E0158.rs similarity index 80% rename from src/test/compile-fail/associated-const-type-parameter-arms.rs rename to src/test/compile-fail/E0158.rs index f564157b49814..5ce35cb8206d3 100644 --- a/src/test/compile-fail/associated-const-type-parameter-arms.rs +++ b/src/test/compile-fail/E0158.rs @@ -28,8 +28,10 @@ impl Foo for Def { pub fn test(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 _ => (), } } diff --git a/src/test/compile-fail/E0162.rs b/src/test/compile-fail/E0162.rs index e13b0af6f7977..aba0c5658429c 100644 --- a/src/test/compile-fail/E0162.rs +++ b/src/test/compile-fail/E0162.rs @@ -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); } } diff --git a/src/test/compile-fail/issue-14221.rs b/src/test/compile-fail/E0170.rs similarity index 92% rename from src/test/compile-fail/issue-14221.rs rename to src/test/compile-fail/E0170.rs index e79be99a346fa..676b4a41829ce 100644 --- a/src/test/compile-fail/issue-14221.rs +++ b/src/test/compile-fail/E0170.rs @@ -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] } } } diff --git a/src/test/compile-fail/E0297.rs b/src/test/compile-fail/E0297.rs index 43166c1a9e83e..3303b625ccc1b 100644 --- a/src/test/compile-fail/E0297.rs +++ b/src/test/compile-fail/E0297.rs @@ -9,7 +9,12 @@ // except according to those terms. fn main() { - let xs : Vec> = 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 + } } diff --git a/src/test/compile-fail/E0301.rs b/src/test/compile-fail/E0301.rs index 06e98289b0d57..6441bcef16643 100644 --- a/src/test/compile-fail/E0301.rs +++ b/src/test/compile-fail/E0301.rs @@ -8,10 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +fn mangle(x: &mut Option) -> 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(_) => {} } } diff --git a/src/test/compile-fail/E0302.rs b/src/test/compile-fail/E0302.rs index 6a5ad40b10907..1dd3c7703b0e2 100644 --- a/src/test/compile-fail/E0302.rs +++ b/src/test/compile-fail/E0302.rs @@ -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(_) => {} } } diff --git a/src/test/compile-fail/E0303.rs b/src/test/compile-fail/E0303.rs index 67947fd087c05..a1a7b0cdd461a 100644 --- a/src/test/compile-fail/E0303.rs +++ b/src/test/compile-fail/E0303.rs @@ -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 + => {} } } diff --git a/src/test/compile-fail/bind-by-move-neither-can-live-while-the-other-survives-2.rs b/src/test/compile-fail/bind-by-move-neither-can-live-while-the-other-survives-2.rs index 2a5c7136dc377..ec966837003f6 100644 --- a/src/test/compile-fail/bind-by-move-neither-can-live-while-the-other-survives-2.rs +++ b/src/test/compile-fail/bind-by-move-neither-can-live-while-the-other-survives-2.rs @@ -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!() } } diff --git a/src/test/compile-fail/bind-by-move-neither-can-live-while-the-other-survives-3.rs b/src/test/compile-fail/bind-by-move-neither-can-live-while-the-other-survives-3.rs index 3d3ccb606bfbb..3ec0439166ddd 100644 --- a/src/test/compile-fail/bind-by-move-neither-can-live-while-the-other-survives-3.rs +++ b/src/test/compile-fail/bind-by-move-neither-can-live-while-the-other-survives-3.rs @@ -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!() } } diff --git a/src/test/compile-fail/bind-by-move-neither-can-live-while-the-other-survives-4.rs b/src/test/compile-fail/bind-by-move-neither-can-live-while-the-other-survives-4.rs index 8c7542fbe6b3d..79a015dda887a 100644 --- a/src/test/compile-fail/bind-by-move-neither-can-live-while-the-other-survives-4.rs +++ b/src/test/compile-fail/bind-by-move-neither-can-live-while-the-other-survives-4.rs @@ -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!() } } diff --git a/src/test/compile-fail/bind-by-move-no-guards.rs b/src/test/compile-fail/bind-by-move-no-guards.rs index bb6060f2543e2..2176d1237d2ef 100644 --- a/src/test/compile-fail/bind-by-move-no-guards.rs +++ b/src/test/compile-fail/bind-by-move-no-guards.rs @@ -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!() } diff --git a/src/test/compile-fail/for-loop-refutable-pattern-error-message.rs b/src/test/compile-fail/for-loop-refutable-pattern-error-message.rs deleted file mode 100644 index 81c4db68628d4..0000000000000 --- a/src/test/compile-fail/for-loop-refutable-pattern-error-message.rs +++ /dev/null @@ -1,13 +0,0 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn main() { - for &1 in [1].iter() {} //~ ERROR refutable pattern in `for` loop binding -} diff --git a/src/test/compile-fail/issue-15129.rs b/src/test/compile-fail/issue-15129.rs index 7a7ba46de74f3..bd5f13cfbc9c1 100644 --- a/src/test/compile-fail/issue-15129.rs +++ b/src/test/compile-fail/issue-15129.rs @@ -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)) => () } diff --git a/src/test/compile-fail/issue-15381.rs b/src/test/compile-fail/issue-15381.rs index d0964d2aabea7..a5f57c720094a 100644 --- a/src/test/compile-fail/issue-15381.rs +++ b/src/test/compile-fail/issue-15381.rs @@ -14,7 +14,8 @@ fn main() { let values: Vec = 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); } } diff --git a/src/test/compile-fail/issue-2111.rs b/src/test/compile-fail/issue-2111.rs index 8180ce52bdbc1..3b9f2a8a4f3ae 100644 --- a/src/test/compile-fail/issue-2111.rs +++ b/src/test/compile-fail/issue-2111.rs @@ -10,7 +10,8 @@ fn foo(a: Option, b: Option) { 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(_)) => { } diff --git a/src/test/compile-fail/issue-30240.rs b/src/test/compile-fail/issue-30240.rs index 9b105e7ec159d..46a88cfcb8f1d 100644 --- a/src/test/compile-fail/issue-30240.rs +++ b/src/test/compile-fail/issue-30240.rs @@ -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 diff --git a/src/test/compile-fail/issue-31221.rs b/src/test/compile-fail/issue-31221.rs index 4997a6fee195b..6ad9ebe3525a5 100644 --- a/src/test/compile-fail/issue-31221.rs +++ b/src/test/compile-fail/issue-31221.rs @@ -22,7 +22,7 @@ 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 => (), @@ -30,7 +30,7 @@ fn main() { //~^ 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 }; } diff --git a/src/test/compile-fail/issue-31561.rs b/src/test/compile-fail/issue-31561.rs index f8645c4d3a7e8..90f43558dc71c 100644 --- a/src/test/compile-fail/issue-31561.rs +++ b/src/test/compile-fail/issue-31561.rs @@ -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 } diff --git a/src/test/compile-fail/issue-4321.rs b/src/test/compile-fail/issue-4321.rs index d589680b0ecda..50cff48b8592a 100644 --- a/src/test/compile-fail/issue-4321.rs +++ b/src/test/compile-fail/issue-4321.rs @@ -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" diff --git a/src/test/compile-fail/match-arm-statics.rs b/src/test/compile-fail/match-arm-statics.rs index 9b313f248fcbb..5a3fde4db0407 100644 --- a/src/test/compile-fail/match-arm-statics.rs +++ b/src/test/compile-fail/match-arm-statics.rs @@ -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) } => (), diff --git a/src/test/compile-fail/non-exhaustive-match-nested.rs b/src/test/compile-fail/non-exhaustive-match-nested.rs index 1d524217a12a2..fed1d589c39f3 100644 --- a/src/test/compile-fail/non-exhaustive-match-nested.rs +++ b/src/test/compile-fail/non-exhaustive-match-nested.rs @@ -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"); } } diff --git a/src/test/compile-fail/non-exhaustive-match.rs b/src/test/compile-fail/non-exhaustive-match.rs index 017baacc9d329..e747faca2a80d 100644 --- a/src/test/compile-fail/non-exhaustive-match.rs +++ b/src/test/compile-fail/non-exhaustive-match.rs @@ -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] = &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] => (), diff --git a/src/test/compile-fail/non-exhaustive-pattern-witness.rs b/src/test/compile-fail/non-exhaustive-pattern-witness.rs index eba61ede8cb20..e05ab3d4eec7c 100644 --- a/src/test/compile-fail/non-exhaustive-pattern-witness.rs +++ b/src/test/compile-fail/non-exhaustive-pattern-witness.rs @@ -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,8 +60,8 @@ 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 => () } @@ -69,8 +69,8 @@ fn enum_with_excessive_missing_variants() { 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) => () } } diff --git a/src/test/compile-fail/pattern-bindings-after-at.rs b/src/test/compile-fail/pattern-bindings-after-at.rs index da2a97b0ca8ab..6fe3738e23dc0 100644 --- a/src/test/compile-fail/pattern-bindings-after-at.rs +++ b/src/test/compile-fail/pattern-bindings-after-at.rs @@ -15,8 +15,11 @@ enum Option { 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); } diff --git a/src/test/compile-fail/refutable-pattern-errors.rs b/src/test/compile-fail/refutable-pattern-errors.rs index ce93e1875ae5a..0a6d85e77c767 100644 --- a/src/test/compile-fail/refutable-pattern-errors.rs +++ b/src/test/compile-fail/refutable-pattern-errors.rs @@ -10,9 +10,11 @@ fn func((1, (Some(1), 2...3)): (isize, (Option, 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 } diff --git a/src/test/compile-fail/refutable-pattern-in-fn-arg.rs b/src/test/compile-fail/refutable-pattern-in-fn-arg.rs index be42f0f0ed883..6b4a6c258f025 100644 --- a/src/test/compile-fail/refutable-pattern-in-fn-arg.rs +++ b/src/test/compile-fail/refutable-pattern-in-fn-arg.rs @@ -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); }