diff options
Diffstat (limited to 'src/test/ui/match')
80 files changed, 1752 insertions, 0 deletions
diff --git a/src/test/ui/match/auxiliary/match_non_exhaustive_lib.rs b/src/test/ui/match/auxiliary/match_non_exhaustive_lib.rs new file mode 100644 index 000000000..3be72551e --- /dev/null +++ b/src/test/ui/match/auxiliary/match_non_exhaustive_lib.rs @@ -0,0 +1,5 @@ +#[non_exhaustive] +pub enum E1 {} + +#[non_exhaustive] +pub enum E2 { A, B } diff --git a/src/test/ui/match/const_non_normal_zst_ref_pattern.rs b/src/test/ui/match/const_non_normal_zst_ref_pattern.rs new file mode 100644 index 000000000..a114fafb6 --- /dev/null +++ b/src/test/ui/match/const_non_normal_zst_ref_pattern.rs @@ -0,0 +1,9 @@ +// check-pass + +const FOO: isize = 10; +const ZST: &() = unsafe { std::mem::transmute(FOO) }; +fn main() { + match &() { + ZST => 9, + }; +} diff --git a/src/test/ui/match/expr-match-panic-fn.rs b/src/test/ui/match/expr-match-panic-fn.rs new file mode 100644 index 000000000..ea471717e --- /dev/null +++ b/src/test/ui/match/expr-match-panic-fn.rs @@ -0,0 +1,19 @@ +// run-fail +// error-pattern:explicit panic +// ignore-emscripten no processes + +fn f() -> ! { + panic!() +} + +fn g() -> isize { + let x = match true { + true => f(), + false => 10, + }; + return x; +} + +fn main() { + g(); +} diff --git a/src/test/ui/match/expr-match-panic.rs b/src/test/ui/match/expr-match-panic.rs new file mode 100644 index 000000000..53f8a8bd3 --- /dev/null +++ b/src/test/ui/match/expr-match-panic.rs @@ -0,0 +1,10 @@ +// run-fail +// error-pattern:explicit panic +// ignore-emscripten no processes + +fn main() { + let _x = match true { + false => 0, + true => panic!(), + }; +} diff --git a/src/test/ui/match/expr_before_ident_pat.rs b/src/test/ui/match/expr_before_ident_pat.rs new file mode 100644 index 000000000..47db6c3f4 --- /dev/null +++ b/src/test/ui/match/expr_before_ident_pat.rs @@ -0,0 +1,15 @@ +#![feature(half_open_range_patterns)] + +macro_rules! funny { + ($a:expr, $b:ident) => { + match [1, 2] { + [$a, $b] => {} + } + }; +} + +fn main() { + funny!(a, a); + //~^ ERROR cannot find value `a` in this scope + //~| ERROR arbitrary expressions aren't allowed in patterns +} diff --git a/src/test/ui/match/expr_before_ident_pat.stderr b/src/test/ui/match/expr_before_ident_pat.stderr new file mode 100644 index 000000000..2bd1b3b94 --- /dev/null +++ b/src/test/ui/match/expr_before_ident_pat.stderr @@ -0,0 +1,15 @@ +error[E0425]: cannot find value `a` in this scope + --> $DIR/expr_before_ident_pat.rs:12:12 + | +LL | funny!(a, a); + | ^ not found in this scope + +error: arbitrary expressions aren't allowed in patterns + --> $DIR/expr_before_ident_pat.rs:12:12 + | +LL | funny!(a, a); + | ^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/match/guards.rs b/src/test/ui/match/guards.rs new file mode 100644 index 000000000..10a4bb673 --- /dev/null +++ b/src/test/ui/match/guards.rs @@ -0,0 +1,20 @@ +// run-pass + +#![allow(non_shorthand_field_patterns)] + +#[derive(Copy, Clone)] +struct Pair { x: isize, y: isize } + +pub fn main() { + let a: isize = + match 10 { x if x < 7 => { 1 } x if x < 11 => { 2 } 10 => { 3 } _ => { 4 } }; + assert_eq!(a, 2); + + let b: isize = + match (Pair {x: 10, y: 20}) { + x if x.x < 5 && x.y < 5 => { 1 } + Pair {x: x, y: y} if x == 10 && y == 20 => { 2 } + Pair {x: _x, y: _y} => { 3 } + }; + assert_eq!(b, 2); +} diff --git a/src/test/ui/match/issue-11319.rs b/src/test/ui/match/issue-11319.rs new file mode 100644 index 000000000..ab69ab250 --- /dev/null +++ b/src/test/ui/match/issue-11319.rs @@ -0,0 +1,13 @@ +fn main() { + match Some(10) { + //~^ NOTE `match` arms have incompatible types + Some(5) => false, + //~^ NOTE this is found to be of type `bool` + Some(2) => true, + //~^ NOTE this is found to be of type `bool` + None => (), + //~^ ERROR `match` arms have incompatible types + //~| NOTE expected `bool`, found `()` + _ => true + } +} diff --git a/src/test/ui/match/issue-11319.stderr b/src/test/ui/match/issue-11319.stderr new file mode 100644 index 000000000..fc44205e8 --- /dev/null +++ b/src/test/ui/match/issue-11319.stderr @@ -0,0 +1,21 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/issue-11319.rs:8:20 + | +LL | / match Some(10) { +LL | | +LL | | Some(5) => false, + | | ----- this is found to be of type `bool` +LL | | +LL | | Some(2) => true, + | | ---- this is found to be of type `bool` +LL | | +LL | | None => (), + | | ^^ expected `bool`, found `()` +... | +LL | | _ => true +LL | | } + | |_____- `match` arms have incompatible types + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/match/issue-11940.rs b/src/test/ui/match/issue-11940.rs new file mode 100644 index 000000000..6815c87ed --- /dev/null +++ b/src/test/ui/match/issue-11940.rs @@ -0,0 +1,11 @@ +// run-pass + +const TEST_STR: &'static str = "abcd"; + +fn main() { + let s = "abcd"; + match s { + TEST_STR => (), + _ => unreachable!() + } +} diff --git a/src/test/ui/match/issue-18060.rs b/src/test/ui/match/issue-18060.rs new file mode 100644 index 000000000..b5f3d0f74 --- /dev/null +++ b/src/test/ui/match/issue-18060.rs @@ -0,0 +1,8 @@ +// run-pass +// Regression test for #18060: match arms were matching in the wrong order. + +fn main() { + assert_eq!(2, match (1, 3) { (0, 2..=5) => 1, (1, 3) => 2, (_, 2..=5) => 3, (_, _) => 4 }); + assert_eq!(2, match (1, 3) { (1, 3) => 2, (_, 2..=5) => 3, (_, _) => 4 }); + assert_eq!(2, match (1, 7) { (0, 2..=5) => 1, (1, 7) => 2, (_, 2..=5) => 3, (_, _) => 4 }); +} diff --git a/src/test/ui/match/issue-26251.rs b/src/test/ui/match/issue-26251.rs new file mode 100644 index 000000000..a3e26a412 --- /dev/null +++ b/src/test/ui/match/issue-26251.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(overlapping_range_endpoints)] + +fn main() { + let x = 'a'; + + let y = match x { + 'a'..='b' if false => "one", + 'a' => "two", + 'a'..='b' => "three", + _ => panic!("what?"), + }; + + assert_eq!(y, "two"); +} diff --git a/src/test/ui/match/issue-26996.rs b/src/test/ui/match/issue-26996.rs new file mode 100644 index 000000000..84037b72a --- /dev/null +++ b/src/test/ui/match/issue-26996.rs @@ -0,0 +1,24 @@ +// run-pass + +// This test is bogus (i.e., should be check-fail) during the period +// where #54986 is implemented and #54987 is *not* implemented. For +// now: just ignore it +// +// ignore-test + +// This test is checking that the write to `c.0` (which has been moved out of) +// won't overwrite the state in `c2`. +// +// That's a fine thing to test when this code is accepted by the +// compiler, and this code is being transcribed accordingly into +// the ui test issue-21232-partial-init-and-use.rs + +fn main() { + let mut c = (1, "".to_owned()); + match c { + c2 => { + c.0 = 2; + assert_eq!(c2.0, 1); + } + } +} diff --git a/src/test/ui/match/issue-27021.rs b/src/test/ui/match/issue-27021.rs new file mode 100644 index 000000000..ef3b114a5 --- /dev/null +++ b/src/test/ui/match/issue-27021.rs @@ -0,0 +1,28 @@ +// run-pass + +// This test is bogus (i.e., should be check-fail) during the period +// where #54986 is implemented and #54987 is *not* implemented. For +// now: just ignore it +// +// ignore-test + +// These are variants of issue-26996.rs. In all cases we are writing +// into a record field that has been moved out of, and ensuring that +// such a write won't overwrite the state of the thing it was moved +// into. +// +// That's a fine thing to test when this code is accepted by the +// compiler, and this code is being transcribed accordingly into +// the ui test issue-21232-partial-init-and-use.rs + +fn main() { + let mut c = (1, (1, "".to_owned())); + match c { + c2 => { (c.1).0 = 2; assert_eq!((c2.1).0, 1); } + } + + let mut c = (1, (1, (1, "".to_owned()))); + match c.1 { + c2 => { ((c.1).1).0 = 3; assert_eq!((c2.1).0, 1); } + } +} diff --git a/src/test/ui/match/issue-33498.rs b/src/test/ui/match/issue-33498.rs new file mode 100644 index 000000000..9c8a97e7e --- /dev/null +++ b/src/test/ui/match/issue-33498.rs @@ -0,0 +1,11 @@ +// run-pass +#![allow(unused_variables)] +pub fn main() { + let x = (0, 2); + + match x { + (0, ref y) => {} + (y, 0) => {} + _ => (), + } +} diff --git a/src/test/ui/match/issue-41255.rs b/src/test/ui/match/issue-41255.rs new file mode 100644 index 000000000..9d7072f16 --- /dev/null +++ b/src/test/ui/match/issue-41255.rs @@ -0,0 +1,51 @@ +// Matching against float literals should result in a linter error + +#![feature(exclusive_range_pattern)] +#![feature(half_open_range_patterns)] +#![allow(unused)] +#![forbid(illegal_floating_point_literal_pattern)] + +fn main() { + let x = 42.0; + match x { + 5.0 => {}, //~ ERROR floating-point types cannot be used in patterns + //~| WARNING hard error + 5.0f32 => {}, //~ ERROR floating-point types cannot be used in patterns + //~| WARNING hard error + -5.0 => {}, //~ ERROR floating-point types cannot be used in patterns + //~| WARNING hard error + 1.0 .. 33.0 => {}, //~ ERROR floating-point types cannot be used in patterns + //~| WARNING hard error + //~| ERROR floating-point types cannot be used in patterns + //~| WARNING hard error + 39.0 ..= 70.0 => {}, //~ ERROR floating-point types cannot be used in patterns + //~| ERROR floating-point types cannot be used in patterns + //~| WARNING hard error + //~| WARNING hard error + + ..71.0 => {} + //~^ ERROR floating-point types cannot be used in patterns + //~| WARNING this was previously accepted by the compiler + ..=72.0 => {} + //~^ ERROR floating-point types cannot be used in patterns + //~| WARNING this was previously accepted by the compiler + 71.0.. => {} + //~^ ERROR floating-point types cannot be used in patterns + //~| WARNING this was previously accepted by the compiler + _ => {}, + }; + let y = 5.0; + // Same for tuples + match (x, 5) { + (3.14, 1) => {}, //~ ERROR floating-point types cannot be used + //~| WARNING hard error + _ => {}, + } + // Or structs + struct Foo { x: f32 }; + match (Foo { x }) { + Foo { x: 2.0 } => {}, //~ ERROR floating-point types cannot be used + //~| WARNING hard error + _ => {}, + } +} diff --git a/src/test/ui/match/issue-41255.stderr b/src/test/ui/match/issue-41255.stderr new file mode 100644 index 000000000..bf81c8d37 --- /dev/null +++ b/src/test/ui/match/issue-41255.stderr @@ -0,0 +1,115 @@ +error: floating-point types cannot be used in patterns + --> $DIR/issue-41255.rs:11:9 + | +LL | 5.0 => {}, + | ^^^ + | +note: the lint level is defined here + --> $DIR/issue-41255.rs:6:11 + | +LL | #![forbid(illegal_floating_point_literal_pattern)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620> + +error: floating-point types cannot be used in patterns + --> $DIR/issue-41255.rs:13:9 + | +LL | 5.0f32 => {}, + | ^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620> + +error: floating-point types cannot be used in patterns + --> $DIR/issue-41255.rs:15:10 + | +LL | -5.0 => {}, + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620> + +error: floating-point types cannot be used in patterns + --> $DIR/issue-41255.rs:17:9 + | +LL | 1.0 .. 33.0 => {}, + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620> + +error: floating-point types cannot be used in patterns + --> $DIR/issue-41255.rs:17:16 + | +LL | 1.0 .. 33.0 => {}, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620> + +error: floating-point types cannot be used in patterns + --> $DIR/issue-41255.rs:21:9 + | +LL | 39.0 ..= 70.0 => {}, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620> + +error: floating-point types cannot be used in patterns + --> $DIR/issue-41255.rs:21:18 + | +LL | 39.0 ..= 70.0 => {}, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620> + +error: floating-point types cannot be used in patterns + --> $DIR/issue-41255.rs:26:11 + | +LL | ..71.0 => {} + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620> + +error: floating-point types cannot be used in patterns + --> $DIR/issue-41255.rs:29:12 + | +LL | ..=72.0 => {} + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620> + +error: floating-point types cannot be used in patterns + --> $DIR/issue-41255.rs:32:9 + | +LL | 71.0.. => {} + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620> + +error: floating-point types cannot be used in patterns + --> $DIR/issue-41255.rs:40:10 + | +LL | (3.14, 1) => {}, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620> + +error: floating-point types cannot be used in patterns + --> $DIR/issue-41255.rs:47:18 + | +LL | Foo { x: 2.0 } => {}, + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620> + +error: aborting due to 12 previous errors + diff --git a/src/test/ui/match/issue-42679.rs b/src/test/ui/match/issue-42679.rs new file mode 100644 index 000000000..596309f25 --- /dev/null +++ b/src/test/ui/match/issue-42679.rs @@ -0,0 +1,22 @@ +// run-pass +#![feature(box_syntax)] +#![feature(box_patterns)] + +#[derive(Debug, PartialEq)] +enum Test { + Foo(usize), + Bar(isize), +} + +fn main() { + let a = box Test::Foo(10); + let b = box Test::Bar(-20); + match (a, b) { + (_, box Test::Foo(_)) => unreachable!(), + (box Test::Foo(x), b) => { + assert_eq!(x, 10); + assert_eq!(b, box Test::Bar(-20)); + }, + _ => unreachable!(), + } +} diff --git a/src/test/ui/match/issue-46920-byte-array-patterns.rs b/src/test/ui/match/issue-46920-byte-array-patterns.rs new file mode 100644 index 000000000..2a8b4bb49 --- /dev/null +++ b/src/test/ui/match/issue-46920-byte-array-patterns.rs @@ -0,0 +1,28 @@ +// run-pass +const CURSOR_PARTITION_LABEL: &'static [u8] = b"partition"; +const CURSOR_EVENT_TYPE_LABEL: &'static [u8] = b"event_type"; +const BYTE_PATTERN: &'static [u8; 5] = b"hello"; + +fn match_slice(x: &[u8]) -> u32 { + match x { + CURSOR_PARTITION_LABEL => 0, + CURSOR_EVENT_TYPE_LABEL => 1, + _ => 2, + } +} + +fn match_array(x: &[u8; 5]) -> bool { + match x { + BYTE_PATTERN => true, + _ => false + } +} + +fn main() { + assert_eq!(match_slice(b"abcde"), 2); + assert_eq!(match_slice(b"event_type"), 1); + assert_eq!(match_slice(b"partition"), 0); + + assert_eq!(match_array(b"hello"), true); + assert_eq!(match_array(b"hella"), false); +} diff --git a/src/test/ui/match/issue-56685.rs b/src/test/ui/match/issue-56685.rs new file mode 100644 index 000000000..f320c99ed --- /dev/null +++ b/src/test/ui/match/issue-56685.rs @@ -0,0 +1,44 @@ +#![allow(dead_code)] +#![deny(unused_variables)] + +// This test aims to check that unused variable suggestions update bindings in all +// match arms. + +fn main() { + enum E { + A(i32,), + B(i32,), + } + + match E::A(1) { + E::A(x) | E::B(x) => {} + //~^ ERROR unused variable: `x` + } + + enum F { + A(i32, i32,), + B(i32, i32,), + C(i32, i32,), + } + + let _ = match F::A(1, 2) { + F::A(x, y) | F::B(x, y) => { y }, + //~^ ERROR unused variable: `x` + F::C(a, b) => { 3 } + //~^ ERROR unused variable: `a` + //~^^ ERROR unused variable: `b` + }; + + let _ = if let F::A(x, y) | F::B(x, y) = F::A(1, 2) { + //~^ ERROR unused variable: `x` + y + } else { + 3 + }; + + while let F::A(x, y) | F::B(x, y) = F::A(1, 2) { + //~^ ERROR unused variable: `x` + let _ = y; + break; + } +} diff --git a/src/test/ui/match/issue-56685.stderr b/src/test/ui/match/issue-56685.stderr new file mode 100644 index 000000000..ccf357d4a --- /dev/null +++ b/src/test/ui/match/issue-56685.stderr @@ -0,0 +1,63 @@ +error: unused variable: `x` + --> $DIR/issue-56685.rs:14:14 + | +LL | E::A(x) | E::B(x) => {} + | ^ ^ + | +note: the lint level is defined here + --> $DIR/issue-56685.rs:2:9 + | +LL | #![deny(unused_variables)] + | ^^^^^^^^^^^^^^^^ +help: if this is intentional, prefix it with an underscore + | +LL | E::A(_x) | E::B(_x) => {} + | ~~ ~~ + +error: unused variable: `x` + --> $DIR/issue-56685.rs:25:14 + | +LL | F::A(x, y) | F::B(x, y) => { y }, + | ^ ^ + | +help: if this is intentional, prefix it with an underscore + | +LL | F::A(_x, y) | F::B(_x, y) => { y }, + | ~~ ~~ + +error: unused variable: `a` + --> $DIR/issue-56685.rs:27:14 + | +LL | F::C(a, b) => { 3 } + | ^ help: if this is intentional, prefix it with an underscore: `_a` + +error: unused variable: `b` + --> $DIR/issue-56685.rs:27:17 + | +LL | F::C(a, b) => { 3 } + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `x` + --> $DIR/issue-56685.rs:32:25 + | +LL | let _ = if let F::A(x, y) | F::B(x, y) = F::A(1, 2) { + | ^ ^ + | +help: if this is intentional, prefix it with an underscore + | +LL | let _ = if let F::A(_x, y) | F::B(_x, y) = F::A(1, 2) { + | ~~ ~~ + +error: unused variable: `x` + --> $DIR/issue-56685.rs:39:20 + | +LL | while let F::A(x, y) | F::B(x, y) = F::A(1, 2) { + | ^ ^ + | +help: if this is intentional, prefix it with an underscore + | +LL | while let F::A(_x, y) | F::B(_x, y) = F::A(1, 2) { + | ~~ ~~ + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/match/issue-70972-dyn-trait.rs b/src/test/ui/match/issue-70972-dyn-trait.rs new file mode 100644 index 000000000..97d161c59 --- /dev/null +++ b/src/test/ui/match/issue-70972-dyn-trait.rs @@ -0,0 +1,10 @@ +const F: &'static dyn Send = &7u32; + +fn main() { + let a: &dyn Send = &7u32; + match a { + F => panic!(), + //~^ ERROR `&dyn Send` cannot be used in patterns + _ => {} + } +} diff --git a/src/test/ui/match/issue-70972-dyn-trait.stderr b/src/test/ui/match/issue-70972-dyn-trait.stderr new file mode 100644 index 000000000..7581070eb --- /dev/null +++ b/src/test/ui/match/issue-70972-dyn-trait.stderr @@ -0,0 +1,8 @@ +error: `&dyn Send` cannot be used in patterns + --> $DIR/issue-70972-dyn-trait.rs:6:9 + | +LL | F => panic!(), + | ^ + +error: aborting due to previous error + diff --git a/src/test/ui/match/issue-72680.rs b/src/test/ui/match/issue-72680.rs new file mode 100644 index 000000000..c13cace76 --- /dev/null +++ b/src/test/ui/match/issue-72680.rs @@ -0,0 +1,63 @@ +// run-pass + +fn main() { + assert!(f("", 0)); + assert!(f("a", 1)); + assert!(f("b", 1)); + + assert!(!f("", 1)); + assert!(!f("a", 0)); + assert!(!f("b", 0)); + + assert!(!f("asdf", 32)); + + //// + + assert!(!g(true, true, true)); + assert!(!g(false, true, true)); + assert!(!g(true, false, true)); + assert!(!g(false, false, true)); + assert!(!g(true, true, false)); + + assert!(g(false, true, false)); + assert!(g(true, false, false)); + assert!(g(false, false, false)); + + //// + + assert!(!h(true, true, true)); + assert!(!h(false, true, true)); + assert!(!h(true, false, true)); + assert!(!h(false, false, true)); + assert!(!h(true, true, false)); + + assert!(h(false, true, false)); + assert!(h(true, false, false)); + assert!(h(false, false, false)); +} + +fn f(s: &str, num: usize) -> bool { + match (s, num) { + ("", 0) | ("a" | "b", 1) => true, + + _ => false, + } +} + +fn g(x: bool, y: bool, z: bool) -> bool { + match (x, y, x, z) { + (true | false, false, true, false) => true, + (false, true | false, true | false, false) => true, + (true | false, true | false, true | false, true) => false, + (true, true | false, true | false, false) => false, + } +} + +fn h(x: bool, y: bool, z: bool) -> bool { + match (x, (y, (x, (z,)))) { + (true | false, (false, (true, (false,)))) => true, + (false, (true | false, (true | false, (false,)))) => true, + (true | false, (true | false, (true | false, (true,)))) => false, + (true, (true | false, (true | false, (false,)))) => false, + } +} diff --git a/src/test/ui/match/issue-72896.rs b/src/test/ui/match/issue-72896.rs new file mode 100644 index 000000000..3a8b82037 --- /dev/null +++ b/src/test/ui/match/issue-72896.rs @@ -0,0 +1,23 @@ +// run-pass +trait EnumSetType { + type Repr; +} + +enum Enum8 { } +impl EnumSetType for Enum8 { + type Repr = u8; +} + +#[derive(PartialEq, Eq)] +struct EnumSet<T: EnumSetType> { + __enumset_underlying: T::Repr, +} + +const CONST_SET: EnumSet<Enum8> = EnumSet { __enumset_underlying: 3 }; + +fn main() { + match CONST_SET { + CONST_SET => { /* ok */ } + _ => panic!("match fell through?"), + } +} diff --git a/src/test/ui/match/issue-74050-end-span.rs b/src/test/ui/match/issue-74050-end-span.rs new file mode 100644 index 000000000..cc81214e2 --- /dev/null +++ b/src/test/ui/match/issue-74050-end-span.rs @@ -0,0 +1,13 @@ +fn main() { + let mut args = std::env::args_os(); + let _arg = match args.next() { + Some(arg) => { + match arg.to_str() { + //~^ ERROR `arg` does not live long enough + Some(s) => s, + None => return, + } + } + None => return, + }; +} diff --git a/src/test/ui/match/issue-74050-end-span.stderr b/src/test/ui/match/issue-74050-end-span.stderr new file mode 100644 index 000000000..59c091e44 --- /dev/null +++ b/src/test/ui/match/issue-74050-end-span.stderr @@ -0,0 +1,15 @@ +error[E0597]: `arg` does not live long enough + --> $DIR/issue-74050-end-span.rs:5:19 + | +LL | let _arg = match args.next() { + | ---- borrow later stored here +LL | Some(arg) => { +LL | match arg.to_str() { + | ^^^^^^^^^^^^ borrowed value does not live long enough +... +LL | } + | - `arg` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/match/issue-82392.rs b/src/test/ui/match/issue-82392.rs new file mode 100644 index 000000000..d26d88304 --- /dev/null +++ b/src/test/ui/match/issue-82392.rs @@ -0,0 +1,9 @@ +// https://github.com/rust-lang/rust/issues/82329 +// compile-flags: -Zunpretty=hir,typed +// check-pass + +pub fn main() { + if true { + } else if let Some(a) = Some(3) { + } +} diff --git a/src/test/ui/match/issue-82392.stdout b/src/test/ui/match/issue-82392.stdout new file mode 100644 index 000000000..ffe730743 --- /dev/null +++ b/src/test/ui/match/issue-82392.stdout @@ -0,0 +1,16 @@ +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; +// https://github.com/rust-lang/rust/issues/82329 +// compile-flags: -Zunpretty=hir,typed +// check-pass + +fn main() ({ + (if (true as bool) + ({ } as + ()) else if (let Some(a) = + ((Some as + fn(i32) -> Option<i32> {Option::<i32>::Some})((3 as i32)) as + Option<i32>) as bool) ({ } as ()) as ()) + } as ()) diff --git a/src/test/ui/match/issue-82866.rs b/src/test/ui/match/issue-82866.rs new file mode 100644 index 000000000..95cd62261 --- /dev/null +++ b/src/test/ui/match/issue-82866.rs @@ -0,0 +1,7 @@ +fn main() { + match x { + //~^ ERROR cannot find value `x` in this scope + Some::<v>(v) => (), + //~^ ERROR cannot find type `v` in this scope + } +} diff --git a/src/test/ui/match/issue-82866.stderr b/src/test/ui/match/issue-82866.stderr new file mode 100644 index 000000000..f9e3360a5 --- /dev/null +++ b/src/test/ui/match/issue-82866.stderr @@ -0,0 +1,16 @@ +error[E0425]: cannot find value `x` in this scope + --> $DIR/issue-82866.rs:2:11 + | +LL | match x { + | ^ not found in this scope + +error[E0412]: cannot find type `v` in this scope + --> $DIR/issue-82866.rs:4:16 + | +LL | Some::<v>(v) => (), + | ^ not found in this scope + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0412, E0425. +For more information about an error, try `rustc --explain E0412`. diff --git a/src/test/ui/match/issue-84434.rs b/src/test/ui/match/issue-84434.rs new file mode 100644 index 000000000..423481fd5 --- /dev/null +++ b/src/test/ui/match/issue-84434.rs @@ -0,0 +1,18 @@ +// https://github.com/rust-lang/rust/issues/84434 +// check-pass + +use std::path::Path; +struct A { + pub func: fn(check: bool, a: &Path, b: Option<&Path>), +} +const MY_A: A = A { + func: |check, a, b| { + if check { + let _ = (); + } else if let Some(parent) = b.and_then(|p| p.parent()) { + let _ = (); + } + }, +}; + +fn main() {} diff --git a/src/test/ui/match/issue-91058.rs b/src/test/ui/match/issue-91058.rs new file mode 100644 index 000000000..4845937d5 --- /dev/null +++ b/src/test/ui/match/issue-91058.rs @@ -0,0 +1,11 @@ +struct S(()); + +fn main() { + let array = [S(())]; + + match array { + [()] => {} + //~^ ERROR mismatched types [E0308] + _ => {} + } +} diff --git a/src/test/ui/match/issue-91058.stderr b/src/test/ui/match/issue-91058.stderr new file mode 100644 index 000000000..ec1d7e21f --- /dev/null +++ b/src/test/ui/match/issue-91058.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/issue-91058.rs:7:10 + | +LL | match array { + | ----- this expression has type `[S; 1]` +LL | [()] => {} + | ^^ expected struct `S`, found `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/match/issue-92100.rs b/src/test/ui/match/issue-92100.rs new file mode 100644 index 000000000..021166b2b --- /dev/null +++ b/src/test/ui/match/issue-92100.rs @@ -0,0 +1,7 @@ +#![feature(half_open_range_patterns)] + +fn main() { + match [1, 2] { + [a.., a] => {} //~ ERROR cannot find value `a` in this scope + } +} diff --git a/src/test/ui/match/issue-92100.stderr b/src/test/ui/match/issue-92100.stderr new file mode 100644 index 000000000..0f694c587 --- /dev/null +++ b/src/test/ui/match/issue-92100.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `a` in this scope + --> $DIR/issue-92100.rs:5:10 + | +LL | [a.., a] => {} + | ^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/match/match-arm-resolving-to-never.rs b/src/test/ui/match/match-arm-resolving-to-never.rs new file mode 100644 index 000000000..6ef249c05 --- /dev/null +++ b/src/test/ui/match/match-arm-resolving-to-never.rs @@ -0,0 +1,19 @@ +enum E { + A, + B, + C, + D, + E, + F, +} + +fn main() { + match E::F { + E::A => 1, + E::B => 2, + E::C => 3, + E::D => 4, + E::E => unimplemented!(""), + E::F => "", //~ ERROR `match` arms have incompatible types + }; +} diff --git a/src/test/ui/match/match-arm-resolving-to-never.stderr b/src/test/ui/match/match-arm-resolving-to-never.stderr new file mode 100644 index 000000000..686fbd0ba --- /dev/null +++ b/src/test/ui/match/match-arm-resolving-to-never.stderr @@ -0,0 +1,18 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/match-arm-resolving-to-never.rs:17:17 + | +LL | / match E::F { +LL | | E::A => 1, +LL | | E::B => 2, +LL | | E::C => 3, +LL | | E::D => 4, +LL | | E::E => unimplemented!(""), + | | ------------------ this and all prior arms are found to be of type `{integer}` +LL | | E::F => "", + | | ^^ expected integer, found `&str` +LL | | }; + | |_____- `match` arms have incompatible types + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/match/match-bot-panic.rs b/src/test/ui/match/match-bot-panic.rs new file mode 100644 index 000000000..e4a6f6d6f --- /dev/null +++ b/src/test/ui/match/match-bot-panic.rs @@ -0,0 +1,16 @@ +// run-fail +// error-pattern:explicit panic +// ignore-emscripten no processes + +#![allow(unreachable_code)] +#![allow(unused_variables)] + +fn foo(s: String) {} + +fn main() { + let i = match Some::<isize>(3) { + None::<isize> => panic!(), + Some::<isize>(_) => panic!(), + }; + foo(i); +} diff --git a/src/test/ui/match/match-disc-bot.rs b/src/test/ui/match/match-disc-bot.rs new file mode 100644 index 000000000..18cfd5e23 --- /dev/null +++ b/src/test/ui/match/match-disc-bot.rs @@ -0,0 +1,16 @@ +// run-fail +// error-pattern:quux +// ignore-emscripten no processes + +fn f() -> ! { + panic!("quux") +} +fn g() -> isize { + match f() { + true => 1, + false => 0, + } +} +fn main() { + g(); +} diff --git a/src/test/ui/match/match-fn-call.rs b/src/test/ui/match/match-fn-call.rs new file mode 100644 index 000000000..99092602c --- /dev/null +++ b/src/test/ui/match/match-fn-call.rs @@ -0,0 +1,12 @@ +use std::path::Path; + +fn main() { + let path = Path::new("foo"); + match path { + Path::new("foo") => println!("foo"), + //~^ ERROR expected tuple struct or tuple variant + Path::new("bar") => println!("bar"), + //~^ ERROR expected tuple struct or tuple variant + _ => (), + } +} diff --git a/src/test/ui/match/match-fn-call.stderr b/src/test/ui/match/match-fn-call.stderr new file mode 100644 index 000000000..297aa4cd9 --- /dev/null +++ b/src/test/ui/match/match-fn-call.stderr @@ -0,0 +1,19 @@ +error[E0164]: expected tuple struct or tuple variant, found associated function `Path::new` + --> $DIR/match-fn-call.rs:6:9 + | +LL | Path::new("foo") => println!("foo"), + | ^^^^^^^^^^^^^^^^ `fn` calls are not allowed in patterns + | + = help: for more information, visit https://doc.rust-lang.org/book/ch18-00-patterns.html + +error[E0164]: expected tuple struct or tuple variant, found associated function `Path::new` + --> $DIR/match-fn-call.rs:8:9 + | +LL | Path::new("bar") => println!("bar"), + | ^^^^^^^^^^^^^^^^ `fn` calls are not allowed in patterns + | + = help: for more information, visit https://doc.rust-lang.org/book/ch18-00-patterns.html + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0164`. diff --git a/src/test/ui/match/match-ill-type2.rs b/src/test/ui/match/match-ill-type2.rs new file mode 100644 index 000000000..6612f6e39 --- /dev/null +++ b/src/test/ui/match/match-ill-type2.rs @@ -0,0 +1,7 @@ +fn main() { + match 1i32 { + 1i32 => 1, + 2u32 => 1, //~ ERROR mismatched types + _ => 2, + }; +} diff --git a/src/test/ui/match/match-ill-type2.stderr b/src/test/ui/match/match-ill-type2.stderr new file mode 100644 index 000000000..5078f03d6 --- /dev/null +++ b/src/test/ui/match/match-ill-type2.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/match-ill-type2.rs:4:9 + | +LL | match 1i32 { + | ---- this expression has type `i32` +LL | 1i32 => 1, +LL | 2u32 => 1, + | ^^^^ expected `i32`, found `u32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/match/match-incompat-type-semi.rs b/src/test/ui/match/match-incompat-type-semi.rs new file mode 100644 index 000000000..37f6beabd --- /dev/null +++ b/src/test/ui/match/match-incompat-type-semi.rs @@ -0,0 +1,52 @@ +// Diagnostic enhancement explained in issue #75418. +// Point at the last statement in the block if there's no tail expression, +// and suggest removing the semicolon if appropriate. + +fn main() { + let _ = match Some(42) { + Some(x) => { + x + }, + None => { + 0; + //~^ ERROR incompatible types + //~| HELP consider removing this semicolon + }, + }; + + let _ = if let Some(x) = Some(42) { + x + } else { + 0; + //~^ ERROR incompatible types + //~| HELP consider removing this semicolon + }; + + let _ = match Some(42) { + Some(x) => { + x + }, + None => { + (); + //~^ ERROR incompatible types + }, + }; + + let _ = match Some(42) { + Some(x) => { + x + }, + None => { //~ ERROR incompatible types + }, + }; + + let _ = match Some(42) { + Some(x) => "rust-lang.org" + .chars() + .skip(1) + .chain(Some(x as u8 as char)) + .take(10) + .any(char::is_alphanumeric), + None => {} //~ ERROR incompatible types + }; +} diff --git a/src/test/ui/match/match-incompat-type-semi.stderr b/src/test/ui/match/match-incompat-type-semi.stderr new file mode 100644 index 000000000..008b1c1e9 --- /dev/null +++ b/src/test/ui/match/match-incompat-type-semi.stderr @@ -0,0 +1,88 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/match-incompat-type-semi.rs:11:13 + | +LL | let _ = match Some(42) { + | _____________- +LL | | Some(x) => { +LL | | x + | | - this is found to be of type `{integer}` +LL | | }, +LL | | None => { +LL | | 0; + | | ^- + | | || + | | |help: consider removing this semicolon + | | expected integer, found `()` +... | +LL | | }, +LL | | }; + | |_____- `match` arms have incompatible types + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/match-incompat-type-semi.rs:20:9 + | +LL | let _ = if let Some(x) = Some(42) { + | _____________- +LL | | x + | | - expected because of this +LL | | } else { +LL | | 0; + | | ^- + | | || + | | |help: consider removing this semicolon + | | expected integer, found `()` +LL | | +LL | | +LL | | }; + | |_____- `if` and `else` have incompatible types + +error[E0308]: `match` arms have incompatible types + --> $DIR/match-incompat-type-semi.rs:30:13 + | +LL | let _ = match Some(42) { + | _____________- +LL | | Some(x) => { +LL | | x + | | - this is found to be of type `{integer}` +LL | | }, +LL | | None => { +LL | | (); + | | ^^^ expected integer, found `()` +LL | | +LL | | }, +LL | | }; + | |_____- `match` arms have incompatible types + +error[E0308]: `match` arms have incompatible types + --> $DIR/match-incompat-type-semi.rs:39:17 + | +LL | let _ = match Some(42) { + | -------------- `match` arms have incompatible types +LL | Some(x) => { +LL | x + | - this is found to be of type `{integer}` +LL | }, +LL | None => { + | _________________^ +LL | | }, + | |_________^ expected integer, found `()` + +error[E0308]: `match` arms have incompatible types + --> $DIR/match-incompat-type-semi.rs:50:17 + | +LL | let _ = match Some(42) { + | -------------- `match` arms have incompatible types +LL | Some(x) => "rust-lang.org" + | ____________________- +LL | | .chars() +LL | | .skip(1) +LL | | .chain(Some(x as u8 as char)) +LL | | .take(10) +LL | | .any(char::is_alphanumeric), + | |_______________________________________- this is found to be of type `bool` +LL | None => {} + | ^^ expected `bool`, found `()` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/match/match-join.rs b/src/test/ui/match/match-join.rs new file mode 100644 index 000000000..b0f2593c8 --- /dev/null +++ b/src/test/ui/match/match-join.rs @@ -0,0 +1,11 @@ +// a good test that we merge paths correctly in the presence of a +// variable that's used before it's declared + +fn my_panic() -> ! { panic!(); } + +fn main() { + match true { false => { my_panic(); } true => { } } + + println!("{}", x); //~ ERROR cannot find value `x` in this scope + let x: isize; +} diff --git a/src/test/ui/match/match-join.stderr b/src/test/ui/match/match-join.stderr new file mode 100644 index 000000000..27a82c124 --- /dev/null +++ b/src/test/ui/match/match-join.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `x` in this scope + --> $DIR/match-join.rs:9:20 + | +LL | println!("{}", x); + | ^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/match/match-no-arms-unreachable-after.rs b/src/test/ui/match/match-no-arms-unreachable-after.rs new file mode 100644 index 000000000..8f83fd1a3 --- /dev/null +++ b/src/test/ui/match/match-no-arms-unreachable-after.rs @@ -0,0 +1,12 @@ +#![allow(warnings)] +#![deny(unreachable_code)] + +enum Void { } + +fn foo(v: Void) { + match v { } + let x = 2; //~ ERROR unreachable +} + +fn main() { +} diff --git a/src/test/ui/match/match-no-arms-unreachable-after.stderr b/src/test/ui/match/match-no-arms-unreachable-after.stderr new file mode 100644 index 000000000..a0a369726 --- /dev/null +++ b/src/test/ui/match/match-no-arms-unreachable-after.stderr @@ -0,0 +1,16 @@ +error: unreachable statement + --> $DIR/match-no-arms-unreachable-after.rs:8:5 + | +LL | match v { } + | ----------- any code following this expression is unreachable +LL | let x = 2; + | ^^^^^^^^^^ unreachable statement + | +note: the lint level is defined here + --> $DIR/match-no-arms-unreachable-after.rs:2:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/match/match-on-negative-integer-ranges.rs b/src/test/ui/match/match-on-negative-integer-ranges.rs new file mode 100644 index 000000000..53e9ea9a5 --- /dev/null +++ b/src/test/ui/match/match-on-negative-integer-ranges.rs @@ -0,0 +1,7 @@ +// run-pass + +fn main() { + assert_eq!(false, match -50_i8 { -128i8..=-101i8 => true, _ => false, }); + + assert_eq!(false, if let -128i8..=-101i8 = -50_i8 { true } else { false }); +} diff --git a/src/test/ui/match/match-pattern-field-mismatch-2.rs b/src/test/ui/match/match-pattern-field-mismatch-2.rs new file mode 100644 index 000000000..fa03cdac2 --- /dev/null +++ b/src/test/ui/match/match-pattern-field-mismatch-2.rs @@ -0,0 +1,16 @@ +fn main() { + enum Color { + Rgb(usize, usize, usize), + Cmyk(usize, usize, usize, usize), + NoColor, + } + + fn foo(c: Color) { + match c { + Color::Rgb(_, _, _) => { } + Color::Cmyk(_, _, _, _) => { } + Color::NoColor(_) => { } + //~^ ERROR expected tuple struct or tuple variant, found unit variant `Color::NoColor` + } + } +} diff --git a/src/test/ui/match/match-pattern-field-mismatch-2.stderr b/src/test/ui/match/match-pattern-field-mismatch-2.stderr new file mode 100644 index 000000000..ba32d0e99 --- /dev/null +++ b/src/test/ui/match/match-pattern-field-mismatch-2.stderr @@ -0,0 +1,12 @@ +error[E0532]: expected tuple struct or tuple variant, found unit variant `Color::NoColor` + --> $DIR/match-pattern-field-mismatch-2.rs:12:11 + | +LL | NoColor, + | ------- `Color::NoColor` defined here +... +LL | Color::NoColor(_) => { } + | ^^^^^^^^^^^^^^^^^ help: use this syntax instead: `Color::NoColor` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0532`. diff --git a/src/test/ui/match/match-pattern-field-mismatch.rs b/src/test/ui/match/match-pattern-field-mismatch.rs new file mode 100644 index 000000000..a4fa97fef --- /dev/null +++ b/src/test/ui/match/match-pattern-field-mismatch.rs @@ -0,0 +1,16 @@ +fn main() { + enum Color { + Rgb(usize, usize, usize), + Cmyk(usize, usize, usize, usize), + NoColor, + } + + fn foo(c: Color) { + match c { + Color::Rgb(_, _) => { } + //~^ ERROR this pattern has 2 fields, but the corresponding tuple variant has 3 + Color::Cmyk(_, _, _, _) => { } + Color::NoColor => { } + } + } +} diff --git a/src/test/ui/match/match-pattern-field-mismatch.stderr b/src/test/ui/match/match-pattern-field-mismatch.stderr new file mode 100644 index 000000000..c994ee4f6 --- /dev/null +++ b/src/test/ui/match/match-pattern-field-mismatch.stderr @@ -0,0 +1,21 @@ +error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 3 fields + --> $DIR/match-pattern-field-mismatch.rs:10:22 + | +LL | Rgb(usize, usize, usize), + | ----- ----- ----- tuple variant has 3 fields +... +LL | Color::Rgb(_, _) => { } + | ^ ^ expected 3 fields, found 2 + | +help: use `_` to explicitly ignore each field + | +LL | Color::Rgb(_, _, _) => { } + | +++ +help: use `..` to ignore all fields + | +LL | Color::Rgb(..) => { } + | ~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0023`. diff --git a/src/test/ui/match/match-range-fail-2.rs b/src/test/ui/match/match-range-fail-2.rs new file mode 100644 index 000000000..792664e1d --- /dev/null +++ b/src/test/ui/match/match-range-fail-2.rs @@ -0,0 +1,24 @@ +#![feature(exclusive_range_pattern)] + +fn main() { + match 5 { + 6 ..= 1 => { } + _ => { } + }; + //~^^^ ERROR lower range bound must be less than or equal to upper + //~| ERROR lower range bound must be less than or equal to upper + + match 5 { + 0 .. 0 => { } + _ => { } + }; + //~^^^ ERROR lower range bound must be less than upper + //~| ERROR lower range bound must be less than upper + + match 5u64 { + 0xFFFF_FFFF_FFFF_FFFF ..= 1 => { } + _ => { } + }; + //~^^^ ERROR lower range bound must be less than or equal to upper + //~| ERROR lower range bound must be less than or equal to upper +} diff --git a/src/test/ui/match/match-range-fail-2.stderr b/src/test/ui/match/match-range-fail-2.stderr new file mode 100644 index 000000000..7a0852d7e --- /dev/null +++ b/src/test/ui/match/match-range-fail-2.stderr @@ -0,0 +1,40 @@ +error[E0030]: lower range bound must be less than or equal to upper + --> $DIR/match-range-fail-2.rs:5:9 + | +LL | 6 ..= 1 => { } + | ^ lower bound larger than upper bound + +error[E0579]: lower range bound must be less than upper + --> $DIR/match-range-fail-2.rs:12:9 + | +LL | 0 .. 0 => { } + | ^ + +error[E0030]: lower range bound must be less than or equal to upper + --> $DIR/match-range-fail-2.rs:19:9 + | +LL | 0xFFFF_FFFF_FFFF_FFFF ..= 1 => { } + | ^^^^^^^^^^^^^^^^^^^^^ lower bound larger than upper bound + +error[E0030]: lower range bound must be less than or equal to upper + --> $DIR/match-range-fail-2.rs:5:9 + | +LL | 6 ..= 1 => { } + | ^ lower bound larger than upper bound + +error[E0579]: lower range bound must be less than upper + --> $DIR/match-range-fail-2.rs:12:9 + | +LL | 0 .. 0 => { } + | ^ + +error[E0030]: lower range bound must be less than or equal to upper + --> $DIR/match-range-fail-2.rs:19:9 + | +LL | 0xFFFF_FFFF_FFFF_FFFF ..= 1 => { } + | ^^^^^^^^^^^^^^^^^^^^^ lower bound larger than upper bound + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0030, E0579. +For more information about an error, try `rustc --explain E0030`. diff --git a/src/test/ui/match/match-range-fail.rs b/src/test/ui/match/match-range-fail.rs new file mode 100644 index 000000000..e53c8463e --- /dev/null +++ b/src/test/ui/match/match-range-fail.rs @@ -0,0 +1,22 @@ +fn main() { + match "wow" { + "bar" ..= "foo" => { } + }; + //~^^ ERROR only `char` and numeric types are allowed in range + + match "wow" { + 10 ..= "what" => () + }; + //~^^ ERROR only `char` and numeric types are allowed in range + + match "wow" { + true ..= "what" => {} + }; + //~^^ ERROR only `char` and numeric types are allowed in range + + match 5 { + 'c' ..= 100 => { } + _ => { } + }; + //~^^^ ERROR mismatched types +} diff --git a/src/test/ui/match/match-range-fail.stderr b/src/test/ui/match/match-range-fail.stderr new file mode 100644 index 000000000..65db92df1 --- /dev/null +++ b/src/test/ui/match/match-range-fail.stderr @@ -0,0 +1,40 @@ +error[E0029]: only `char` and numeric types are allowed in range patterns + --> $DIR/match-range-fail.rs:3:9 + | +LL | "bar" ..= "foo" => { } + | -----^^^^^----- + | | | + | | this is of type `&'static str` but it should be `char` or numeric + | this is of type `&'static str` but it should be `char` or numeric + +error[E0029]: only `char` and numeric types are allowed in range patterns + --> $DIR/match-range-fail.rs:8:16 + | +LL | 10 ..= "what" => () + | -- ^^^^^^ this is of type `&'static str` but it should be `char` or numeric + | | + | this is of type `{integer}` + +error[E0029]: only `char` and numeric types are allowed in range patterns + --> $DIR/match-range-fail.rs:13:9 + | +LL | true ..= "what" => {} + | ----^^^^^------ + | | | + | | this is of type `&'static str` but it should be `char` or numeric + | this is of type `bool` but it should be `char` or numeric + +error[E0308]: mismatched types + --> $DIR/match-range-fail.rs:18:9 + | +LL | match 5 { + | - this expression has type `{integer}` +LL | 'c' ..= 100 => { } + | ^^^ --- this is of type `{integer}` + | | + | expected integer, found `char` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0029, E0308. +For more information about an error, try `rustc --explain E0029`. diff --git a/src/test/ui/match/match-ref-mut-invariance.rs b/src/test/ui/match/match-ref-mut-invariance.rs new file mode 100644 index 000000000..4250696c6 --- /dev/null +++ b/src/test/ui/match/match-ref-mut-invariance.rs @@ -0,0 +1,15 @@ +// Check that when making a ref mut binding with type `&mut T`, the +// type `T` must match precisely the type `U` of the value being +// matched, and in particular cannot be some supertype of `U`. Issue +// #23116. This test focuses on a `match`. + +#![allow(dead_code)] +struct S<'b>(&'b i32); +impl<'b> S<'b> { + fn bar<'a>(&'a mut self) -> &'a mut &'a i32 { + match self.0 { ref mut x => x } + //~^ ERROR lifetime may not live long enough + } +} + +fn main() {} diff --git a/src/test/ui/match/match-ref-mut-invariance.stderr b/src/test/ui/match/match-ref-mut-invariance.stderr new file mode 100644 index 000000000..3b7e53cd5 --- /dev/null +++ b/src/test/ui/match/match-ref-mut-invariance.stderr @@ -0,0 +1,17 @@ +error: lifetime may not live long enough + --> $DIR/match-ref-mut-invariance.rs:10:9 + | +LL | impl<'b> S<'b> { + | -- lifetime `'b` defined here +LL | fn bar<'a>(&'a mut self) -> &'a mut &'a i32 { + | -- lifetime `'a` defined here +LL | match self.0 { ref mut x => x } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + = note: requirement occurs because of a mutable reference to `&i32` + = note: mutable references are invariant over their type parameter + = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance + +error: aborting due to previous error + diff --git a/src/test/ui/match/match-ref-mut-let-invariance.rs b/src/test/ui/match/match-ref-mut-let-invariance.rs new file mode 100644 index 000000000..a33be09ac --- /dev/null +++ b/src/test/ui/match/match-ref-mut-let-invariance.rs @@ -0,0 +1,16 @@ +// Check that when making a ref mut binding with type `&mut T`, the +// type `T` must match precisely the type `U` of the value being +// matched, and in particular cannot be some supertype of `U`. Issue +// #23116. This test focuses on a `let`. + +#![allow(dead_code)] +struct S<'b>(&'b i32); +impl<'b> S<'b> { + fn bar<'a>(&'a mut self) -> &'a mut &'a i32 { + let ref mut x = self.0; + x + //~^ ERROR lifetime may not live long enough + } +} + +fn main() {} diff --git a/src/test/ui/match/match-ref-mut-let-invariance.stderr b/src/test/ui/match/match-ref-mut-let-invariance.stderr new file mode 100644 index 000000000..f4d1cea67 --- /dev/null +++ b/src/test/ui/match/match-ref-mut-let-invariance.stderr @@ -0,0 +1,18 @@ +error: lifetime may not live long enough + --> $DIR/match-ref-mut-let-invariance.rs:11:9 + | +LL | impl<'b> S<'b> { + | -- lifetime `'b` defined here +LL | fn bar<'a>(&'a mut self) -> &'a mut &'a i32 { + | -- lifetime `'a` defined here +LL | let ref mut x = self.0; +LL | x + | ^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + = note: requirement occurs because of a mutable reference to `&i32` + = note: mutable references are invariant over their type parameter + = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance + +error: aborting due to previous error + diff --git a/src/test/ui/match/match-ref-mut-stability.rs b/src/test/ui/match/match-ref-mut-stability.rs new file mode 100644 index 000000000..52120360b --- /dev/null +++ b/src/test/ui/match/match-ref-mut-stability.rs @@ -0,0 +1,37 @@ +// Check that `ref mut` variables don't change address between the match guard +// and the arm expression. + +// run-pass + +// Test that z always point to the same temporary. +fn referent_stability() { + let p; + match 0 { + ref mut z if { p = z as *const _; true } => assert_eq!(p, z as *const _), + _ => unreachable!(), + }; +} + +// Test that z is always effectively the same variable. +fn variable_stability() { + let p; + match 0 { + ref mut z if { p = &z as *const _; true } => assert_eq!(p, &z as *const _), + _ => unreachable!(), + }; +} + +// Test that a borrow of *z can cross from the guard to the arm. +fn persist_borrow() { + let r; + match 0 { + ref mut z if { r = z as &_; true } => assert_eq!(*r, 0), + _ => unreachable!(), + } +} + +fn main() { + referent_stability(); + variable_stability(); + persist_borrow(); +} diff --git a/src/test/ui/match/match-struct.rs b/src/test/ui/match/match-struct.rs new file mode 100644 index 000000000..7a54c54b9 --- /dev/null +++ b/src/test/ui/match/match-struct.rs @@ -0,0 +1,11 @@ +struct S { a: isize } +enum E { C(isize) } + +fn main() { + match (S { a: 1 }) { + E::C(_) => (), + //~^ ERROR mismatched types + //~| expected struct `S`, found enum `E` + _ => () + } +} diff --git a/src/test/ui/match/match-struct.stderr b/src/test/ui/match/match-struct.stderr new file mode 100644 index 000000000..a475bd5e5 --- /dev/null +++ b/src/test/ui/match/match-struct.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/match-struct.rs:6:9 + | +LL | match (S { a: 1 }) { + | ------------ this expression has type `S` +LL | E::C(_) => (), + | ^^^^^^^ expected struct `S`, found enum `E` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/match/match-tag-nullary.rs b/src/test/ui/match/match-tag-nullary.rs new file mode 100644 index 000000000..bb2f59969 --- /dev/null +++ b/src/test/ui/match/match-tag-nullary.rs @@ -0,0 +1,4 @@ +enum A { A } +enum B { B } + +fn main() { let x: A = A::A; match x { B::B => { } } } //~ ERROR mismatched types diff --git a/src/test/ui/match/match-tag-nullary.stderr b/src/test/ui/match/match-tag-nullary.stderr new file mode 100644 index 000000000..a6add31d1 --- /dev/null +++ b/src/test/ui/match/match-tag-nullary.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/match-tag-nullary.rs:4:40 + | +LL | enum B { B } + | - unit variant defined here +LL | +LL | fn main() { let x: A = A::A; match x { B::B => { } } } + | - ^^^^ expected enum `A`, found enum `B` + | | + | this expression has type `A` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/match/match-tag-unary.rs b/src/test/ui/match/match-tag-unary.rs new file mode 100644 index 000000000..aedceafb4 --- /dev/null +++ b/src/test/ui/match/match-tag-unary.rs @@ -0,0 +1,4 @@ +enum A { A(isize) } +enum B { B(isize) } + +fn main() { let x: A = A::A(0); match x { B::B(y) => { } } } //~ ERROR mismatched types diff --git a/src/test/ui/match/match-tag-unary.stderr b/src/test/ui/match/match-tag-unary.stderr new file mode 100644 index 000000000..31f77bdff --- /dev/null +++ b/src/test/ui/match/match-tag-unary.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/match-tag-unary.rs:4:43 + | +LL | fn main() { let x: A = A::A(0); match x { B::B(y) => { } } } + | - ^^^^^^^ expected enum `A`, found enum `B` + | | + | this expression has type `A` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/match/match-type-err-first-arm.rs b/src/test/ui/match/match-type-err-first-arm.rs new file mode 100644 index 000000000..e9027eb24 --- /dev/null +++ b/src/test/ui/match/match-type-err-first-arm.rs @@ -0,0 +1,50 @@ +fn main() { + let _ = test_func1(1); + let _ = test_func2(1); +} + +fn test_func1(n: i32) -> i32 { //~ NOTE expected `i32` because of return type + match n { + 12 => 'b', + //~^ ERROR mismatched types + //~| NOTE expected `i32`, found `char` + _ => 42, + } +} + +fn test_func2(n: i32) -> i32 { + let x = match n { //~ NOTE `match` arms have incompatible types + 12 => 'b', //~ NOTE this is found to be of type `char` + _ => 42, + //~^ ERROR `match` arms have incompatible types + //~| NOTE expected `char`, found integer + }; + x +} + +fn test_func3(n: i32) -> i32 { + let x = match n { //~ NOTE `match` arms have incompatible types + 1 => 'b', + 2 => 'b', + 3 => 'b', + 4 => 'b', + 5 => 'b', + 6 => 'b', + //~^ NOTE this and all prior arms are found to be of type `char` + _ => 42, + //~^ ERROR `match` arms have incompatible types + //~| NOTE expected `char`, found integer + }; + x +} + +fn test_func4() { + match Some(0u32) { //~ NOTE `match` arms have incompatible types + Some(x) => { + x //~ NOTE this is found to be of type `u32` + }, + None => {} + //~^ ERROR `match` arms have incompatible types + //~| NOTE expected `u32`, found `()` + }; +} diff --git a/src/test/ui/match/match-type-err-first-arm.stderr b/src/test/ui/match/match-type-err-first-arm.stderr new file mode 100644 index 000000000..1cfe7ce1e --- /dev/null +++ b/src/test/ui/match/match-type-err-first-arm.stderr @@ -0,0 +1,65 @@ +error[E0308]: mismatched types + --> $DIR/match-type-err-first-arm.rs:8:15 + | +LL | fn test_func1(n: i32) -> i32 { + | --- expected `i32` because of return type +LL | match n { +LL | 12 => 'b', + | ^^^ expected `i32`, found `char` + | +help: you can cast a `char` to an `i32`, since a `char` always occupies 4 bytes + | +LL | 12 => 'b' as i32, + | ++++++ + +error[E0308]: `match` arms have incompatible types + --> $DIR/match-type-err-first-arm.rs:18:14 + | +LL | let x = match n { + | _____________- +LL | | 12 => 'b', + | | --- this is found to be of type `char` +LL | | _ => 42, + | | ^^ expected `char`, found integer +LL | | +LL | | +LL | | }; + | |_____- `match` arms have incompatible types + +error[E0308]: `match` arms have incompatible types + --> $DIR/match-type-err-first-arm.rs:34:14 + | +LL | let x = match n { + | _____________- +LL | | 1 => 'b', +LL | | 2 => 'b', +LL | | 3 => 'b', +... | +LL | | 6 => 'b', + | | --- this and all prior arms are found to be of type `char` +LL | | +LL | | _ => 42, + | | ^^ expected `char`, found integer +LL | | +LL | | +LL | | }; + | |_____- `match` arms have incompatible types + +error[E0308]: `match` arms have incompatible types + --> $DIR/match-type-err-first-arm.rs:46:17 + | +LL | / match Some(0u32) { +LL | | Some(x) => { +LL | | x + | | - this is found to be of type `u32` +LL | | }, +LL | | None => {} + | | ^^ expected `u32`, found `()` +LL | | +LL | | +LL | | }; + | |_____- `match` arms have incompatible types + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/match/match-unresolved-one-arm.rs b/src/test/ui/match/match-unresolved-one-arm.rs new file mode 100644 index 000000000..fa65d87b3 --- /dev/null +++ b/src/test/ui/match/match-unresolved-one-arm.rs @@ -0,0 +1,7 @@ +fn foo<T>() -> T { panic!("Rocks for my pillow") } + +fn main() { + let x = match () { //~ ERROR type annotations needed + () => foo() // T here should be unresolved + }; +} diff --git a/src/test/ui/match/match-unresolved-one-arm.stderr b/src/test/ui/match/match-unresolved-one-arm.stderr new file mode 100644 index 000000000..9eadb88a8 --- /dev/null +++ b/src/test/ui/match/match-unresolved-one-arm.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/match-unresolved-one-arm.rs:4:9 + | +LL | let x = match () { + | ^ + | +help: consider giving `x` an explicit type + | +LL | let x: _ = match () { + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/match/match-vec-mismatch-2.rs b/src/test/ui/match/match-vec-mismatch-2.rs new file mode 100644 index 000000000..553095837 --- /dev/null +++ b/src/test/ui/match/match-vec-mismatch-2.rs @@ -0,0 +1,6 @@ +fn main() { + match () { + [()] => { } + //~^ ERROR expected an array or slice, found `()` + } +} diff --git a/src/test/ui/match/match-vec-mismatch-2.stderr b/src/test/ui/match/match-vec-mismatch-2.stderr new file mode 100644 index 000000000..5247bea62 --- /dev/null +++ b/src/test/ui/match/match-vec-mismatch-2.stderr @@ -0,0 +1,9 @@ +error[E0529]: expected an array or slice, found `()` + --> $DIR/match-vec-mismatch-2.rs:3:9 + | +LL | [()] => { } + | ^^^^ pattern cannot match with input type `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0529`. diff --git a/src/test/ui/match/match-wildcards.rs b/src/test/ui/match/match-wildcards.rs new file mode 100644 index 000000000..43f6e4913 --- /dev/null +++ b/src/test/ui/match/match-wildcards.rs @@ -0,0 +1,21 @@ +// run-fail +// error-pattern:squirrelcupcake +// ignore-emscripten no processes + +fn cmp() -> isize { + match (Some('a'), None::<char>) { + (Some(_), _) => { + panic!("squirrelcupcake"); + } + (_, Some(_)) => { + panic!(); + } + _ => { + panic!("wat"); + } + } +} + +fn main() { + println!("{}", cmp()); +} diff --git a/src/test/ui/match/match_non_exhaustive.rs b/src/test/ui/match/match_non_exhaustive.rs new file mode 100644 index 000000000..8219f0eb1 --- /dev/null +++ b/src/test/ui/match/match_non_exhaustive.rs @@ -0,0 +1,32 @@ +// aux-build:match_non_exhaustive_lib.rs + +/* The error message for non-exhaustive matches on non-local enums + * marked as non-exhaustive should mention the fact that the enum + * is marked as non-exhaustive (issue #85227). + */ + +// Ignore non_exhaustive in the same crate +#[non_exhaustive] +enum L { A, B } + +extern crate match_non_exhaustive_lib; +use match_non_exhaustive_lib::{E1, E2}; + +fn foo() -> L {todo!()} +fn bar() -> (E1, E2) {todo!()} + +fn main() { + let l = foo(); + // No error for enums defined in this crate + match l { L::A => (), L::B => () }; + // (except if the match is already non-exhaustive) + match l { L::A => () }; + //~^ ERROR: non-exhaustive patterns: `B` not covered [E0004] + + // E1 is not visibly uninhabited from here + let (e1, e2) = bar(); + match e1 {}; + //~^ ERROR: non-exhaustive patterns: type `E1` is non-empty [E0004] + match e2 { E2::A => (), E2::B => () }; + //~^ ERROR: non-exhaustive patterns: `_` not covered [E0004] +} diff --git a/src/test/ui/match/match_non_exhaustive.stderr b/src/test/ui/match/match_non_exhaustive.stderr new file mode 100644 index 000000000..9d92f8fdb --- /dev/null +++ b/src/test/ui/match/match_non_exhaustive.stderr @@ -0,0 +1,56 @@ +error[E0004]: non-exhaustive patterns: `B` not covered + --> $DIR/match_non_exhaustive.rs:23:11 + | +LL | match l { L::A => () }; + | ^ pattern `B` not covered + | +note: `L` defined here + --> $DIR/match_non_exhaustive.rs:10:13 + | +LL | enum L { A, B } + | - ^ not covered + = note: the matched value is of type `L` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match l { L::A => (), B => todo!() }; + | ++++++++++++++ + +error[E0004]: non-exhaustive patterns: type `E1` is non-empty + --> $DIR/match_non_exhaustive.rs:28:11 + | +LL | match e1 {}; + | ^^ + | +note: `E1` defined here + --> $DIR/auxiliary/match_non_exhaustive_lib.rs:2:1 + | +LL | pub enum E1 {} + | ^^^^^^^^^^^ + = note: the matched value is of type `E1`, which is marked as non-exhaustive +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match e1 { +LL + _ => todo!(), +LL ~ }; + | + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/match_non_exhaustive.rs:30:11 + | +LL | match e2 { E2::A => (), E2::B => () }; + | ^^ pattern `_` not covered + | +note: `E2` defined here + --> $DIR/auxiliary/match_non_exhaustive_lib.rs:5:1 + | +LL | pub enum E2 { A, B } + | ^^^^^^^^^^^ + = note: the matched value is of type `E2`, which is marked as non-exhaustive +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match e2 { E2::A => (), E2::B => (), _ => todo!() }; + | ++++++++++++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/match/pattern-deref-miscompile.rs b/src/test/ui/match/pattern-deref-miscompile.rs new file mode 100644 index 000000000..caa6d184a --- /dev/null +++ b/src/test/ui/match/pattern-deref-miscompile.rs @@ -0,0 +1,46 @@ +// run-pass + +fn main() { + match b"." as &[u8] { + b"." if true => {}, + b"." => panic!(), + b".." => panic!(), + b"" => panic!(), + _ => panic!(), + } + match b"." as &[u8] { + b"." if false => panic!(), + b"." => {}, + b".." => panic!(), + b"" => panic!(), + _ => panic!(), + } + match b".." as &[u8] { + b"." if true => panic!(), // the miscompile caused this arm to be reached + b"." => panic!(), + b".." => {}, + b"" => panic!(), + _ => panic!(), + } + match b".." as &[u8] { + b"." if false => panic!(), + b"." => panic!(), + b".." => {}, + b"" => panic!(), + _ => panic!(), + } + match b"" as &[u8] { + b"." if true => panic!(), + b"." => panic!(), + b".." => panic!(), + b"" => {}, + _ => panic!(), + } + match b"" as &[u8] { + b"." if false => panic!(), + b"." => panic!(), + b".." => panic!(), + b"" => {}, + _ => panic!(), + } +} |