diff options
Diffstat (limited to 'tests/ui/pattern/usefulness')
153 files changed, 6438 insertions, 0 deletions
diff --git a/tests/ui/pattern/usefulness/always-inhabited-union-ref.rs b/tests/ui/pattern/usefulness/always-inhabited-union-ref.rs new file mode 100644 index 000000000..7d1cac8a4 --- /dev/null +++ b/tests/ui/pattern/usefulness/always-inhabited-union-ref.rs @@ -0,0 +1,32 @@ +// The precise semantics of inhabitedness with respect to unions and references is currently +// undecided. This test file currently checks a conservative choice. + +#![feature(exhaustive_patterns)] +#![feature(never_type)] + +#![allow(dead_code)] +#![allow(unreachable_code)] + +pub union Foo { + foo: !, +} + +fn uninhab_ref() -> &'static ! { + unimplemented!() +} + +fn uninhab_union() -> Foo { + unimplemented!() +} + +fn match_on_uninhab() { + match uninhab_ref() { + //~^ ERROR non-exhaustive patterns: type `&!` is non-empty + } + + match uninhab_union() { + //~^ ERROR non-exhaustive patterns: type `Foo` is non-empty + } +} + +fn main() {} diff --git a/tests/ui/pattern/usefulness/always-inhabited-union-ref.stderr b/tests/ui/pattern/usefulness/always-inhabited-union-ref.stderr new file mode 100644 index 000000000..cd5c283f9 --- /dev/null +++ b/tests/ui/pattern/usefulness/always-inhabited-union-ref.stderr @@ -0,0 +1,37 @@ +error[E0004]: non-exhaustive patterns: type `&!` is non-empty + --> $DIR/always-inhabited-union-ref.rs:23:11 + | +LL | match uninhab_ref() { + | ^^^^^^^^^^^^^ + | + = note: the matched value is of type `&!` + = note: references are always considered inhabited +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match uninhab_ref() { +LL + _ => todo!(), +LL + } + | + +error[E0004]: non-exhaustive patterns: type `Foo` is non-empty + --> $DIR/always-inhabited-union-ref.rs:27:11 + | +LL | match uninhab_union() { + | ^^^^^^^^^^^^^^^ + | +note: `Foo` defined here + --> $DIR/always-inhabited-union-ref.rs:10:11 + | +LL | pub union Foo { + | ^^^ + = note: the matched value is of type `Foo` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match uninhab_union() { +LL + _ => todo!(), +LL + } + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/auxiliary/empty.rs b/tests/ui/pattern/usefulness/auxiliary/empty.rs new file mode 100644 index 000000000..29a03c9e8 --- /dev/null +++ b/tests/ui/pattern/usefulness/auxiliary/empty.rs @@ -0,0 +1,10 @@ +#![crate_type = "rlib"] +pub enum EmptyForeignEnum {} + +pub struct VisiblyUninhabitedForeignStruct { + pub field: EmptyForeignEnum, +} + +pub struct SecretlyUninhabitedForeignStruct { + _priv: EmptyForeignEnum, +} diff --git a/tests/ui/pattern/usefulness/auxiliary/hidden.rs b/tests/ui/pattern/usefulness/auxiliary/hidden.rs new file mode 100644 index 000000000..364514ba1 --- /dev/null +++ b/tests/ui/pattern/usefulness/auxiliary/hidden.rs @@ -0,0 +1,14 @@ +pub enum HiddenEnum { + A, + B, + #[doc(hidden)] + C, +} + +#[derive(Default)] +pub struct HiddenStruct { + pub one: u8, + pub two: bool, + #[doc(hidden)] + pub hide: usize, +} diff --git a/tests/ui/pattern/usefulness/auxiliary/unstable.rs b/tests/ui/pattern/usefulness/auxiliary/unstable.rs new file mode 100644 index 000000000..a06b3a6e4 --- /dev/null +++ b/tests/ui/pattern/usefulness/auxiliary/unstable.rs @@ -0,0 +1,23 @@ +#![feature(staged_api)] +#![stable(feature = "stable_test_feature", since = "1.0.0")] + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub enum UnstableEnum { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + Stable, + #[stable(feature = "stable_test_feature", since = "1.0.0")] + Stable2, + #[unstable(feature = "unstable_test_feature", issue = "none")] + Unstable, +} + +#[derive(Default)] +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub struct UnstableStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + pub stable: bool, + #[stable(feature = "stable_test_feature", since = "1.0.0")] + pub stable2: usize, + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub unstable: u8, +} diff --git a/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.rs b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.rs new file mode 100644 index 000000000..02599d7c0 --- /dev/null +++ b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.rs @@ -0,0 +1,18 @@ +#![allow(warnings)] + +struct MyType; + +impl PartialEq<usize> for MyType { + fn eq(&self, y: &usize) -> bool { + true + } +} + +const CONSTANT: &&MyType = &&MyType; + +fn main() { + if let CONSTANT = &&MyType { + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + println!("did match!"); + } +} diff --git a/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr new file mode 100644 index 000000000..358421cd6 --- /dev/null +++ b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr @@ -0,0 +1,8 @@ +error: to use a constant of type `MyType` in a pattern, `MyType` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/const-partial_eq-fallback-ice.rs:14:12 + | +LL | if let CONSTANT = &&MyType { + | ^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/pattern/usefulness/const-pat-ice.rs b/tests/ui/pattern/usefulness/const-pat-ice.rs new file mode 100644 index 000000000..abfacf393 --- /dev/null +++ b/tests/ui/pattern/usefulness/const-pat-ice.rs @@ -0,0 +1,11 @@ +// check-pass + +const FOO: &&&u32 = &&&42; + +fn main() { + match unimplemented!() { + &&&42 => {}, + FOO => {}, + _ => {}, + } +} diff --git a/tests/ui/pattern/usefulness/const-private-fields.rs b/tests/ui/pattern/usefulness/const-private-fields.rs new file mode 100644 index 000000000..06c832ca4 --- /dev/null +++ b/tests/ui/pattern/usefulness/const-private-fields.rs @@ -0,0 +1,30 @@ +// check-pass +// +// Check that we don't ignore private fields in usefulness checking +#![deny(unreachable_patterns)] + +mod inner { + #[derive(PartialEq, Eq)] + pub struct PrivateField { + pub x: bool, + y: bool, + } + + pub const FOO: PrivateField = PrivateField { x: true, y: true }; + pub const BAR: PrivateField = PrivateField { x: true, y: false }; +} +use inner::*; + +fn main() { + match FOO { + FOO => {} + BAR => {} + _ => {} + } + + match FOO { + FOO => {} + PrivateField { x: true, .. } => {} + _ => {} + } +} diff --git a/tests/ui/pattern/usefulness/consts-opaque.rs b/tests/ui/pattern/usefulness/consts-opaque.rs new file mode 100644 index 000000000..ca4fcd85b --- /dev/null +++ b/tests/ui/pattern/usefulness/consts-opaque.rs @@ -0,0 +1,145 @@ +// This file tests the exhaustiveness algorithm on opaque constants. Most of the examples give +// unnecessary warnings because const_to_pat.rs converts a constant pattern to a wildcard when the +// constant is not allowed as a pattern. This is an edge case so we may not care to fix it. +// See also https://github.com/rust-lang/rust/issues/78057 + +#![deny(unreachable_patterns)] + +#[derive(PartialEq)] +struct Foo(i32); +impl Eq for Foo {} +const FOO: Foo = Foo(42); +const FOO_REF: &Foo = &Foo(42); +const FOO_REF_REF: &&Foo = &&Foo(42); + +#[derive(PartialEq)] +struct Bar; +impl Eq for Bar {} +const BAR: Bar = Bar; + +#[derive(PartialEq)] +enum Baz { + Baz1, + Baz2 +} +impl Eq for Baz {} +const BAZ: Baz = Baz::Baz1; + +fn main() { + match FOO { + FOO => {} + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + _ => {} // should not be emitting unreachable warning + //~^ ERROR unreachable pattern + } + + match FOO_REF { + FOO_REF => {} + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + Foo(_) => {} // should not be emitting unreachable warning + //~^ ERROR unreachable pattern + } + + // This used to cause an ICE (https://github.com/rust-lang/rust/issues/78071) + match FOO_REF_REF { + FOO_REF_REF => {} + //~^ WARNING must be annotated with `#[derive(PartialEq, Eq)]` + //~| WARNING this was previously accepted by the compiler but is being phased out + Foo(_) => {} + } + + match BAR { + Bar => {} + BAR => {} // should not be emitting unreachable warning + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + //~| ERROR unreachable pattern + _ => {} + //~^ ERROR unreachable pattern + } + + match BAR { + BAR => {} + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + Bar => {} // should not be emitting unreachable warning + //~^ ERROR unreachable pattern + _ => {} + //~^ ERROR unreachable pattern + } + + match BAR { + BAR => {} + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + BAR => {} // should not be emitting unreachable warning + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + //~| ERROR unreachable pattern + _ => {} // should not be emitting unreachable warning + //~^ ERROR unreachable pattern + } + + match BAZ { + BAZ => {} + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + Baz::Baz1 => {} // should not be emitting unreachable warning + //~^ ERROR unreachable pattern + _ => {} + //~^ ERROR unreachable pattern + } + + match BAZ { + Baz::Baz1 => {} + BAZ => {} + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + _ => {} + //~^ ERROR unreachable pattern + } + + match BAZ { + BAZ => {} + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + Baz::Baz2 => {} // should not be emitting unreachable warning + //~^ ERROR unreachable pattern + _ => {} // should not be emitting unreachable warning + //~^ ERROR unreachable pattern + } + + type Quux = fn(usize, usize) -> usize; + fn quux(a: usize, b: usize) -> usize { a + b } + const QUUX: Quux = quux; + + match QUUX { + QUUX => {} + QUUX => {} + _ => {} + } + + #[derive(PartialEq, Eq)] + struct Wrap<T>(T); + const WRAPQUUX: Wrap<Quux> = Wrap(quux); + + match WRAPQUUX { + WRAPQUUX => {} + WRAPQUUX => {} + Wrap(_) => {} + } + + match WRAPQUUX { + Wrap(_) => {} + WRAPQUUX => {} // detected unreachable because we do inspect the `Wrap` layer + //~^ ERROR unreachable pattern + } + + #[derive(PartialEq, Eq)] + enum WhoKnows<T> { + Yay(T), + Nope, + }; + const WHOKNOWSQUUX: WhoKnows<Quux> = WhoKnows::Yay(quux); + + match WHOKNOWSQUUX { + WHOKNOWSQUUX => {} + WhoKnows::Yay(_) => {} + WHOKNOWSQUUX => {} // detected unreachable because we do inspect the `WhoKnows` layer + //~^ ERROR unreachable pattern + WhoKnows::Nope => {} + } +} diff --git a/tests/ui/pattern/usefulness/consts-opaque.stderr b/tests/ui/pattern/usefulness/consts-opaque.stderr new file mode 100644 index 000000000..35396751a --- /dev/null +++ b/tests/ui/pattern/usefulness/consts-opaque.stderr @@ -0,0 +1,202 @@ +error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/consts-opaque.rs:30:9 + | +LL | FOO => {} + | ^^^ + +error: unreachable pattern + --> $DIR/consts-opaque.rs:32:9 + | +LL | FOO => {} + | --- matches any value +LL | +LL | _ => {} // should not be emitting unreachable warning + | ^ unreachable pattern + | +note: the lint level is defined here + --> $DIR/consts-opaque.rs:6:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/consts-opaque.rs:37:9 + | +LL | FOO_REF => {} + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/consts-opaque.rs:39:9 + | +LL | FOO_REF => {} + | ------- matches any value +LL | +LL | Foo(_) => {} // should not be emitting unreachable warning + | ^^^^^^ unreachable pattern + +warning: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/consts-opaque.rs:45:9 + | +LL | FOO_REF_REF => {} + | ^^^^^^^^^^^ + | + = 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 #62411 <https://github.com/rust-lang/rust/issues/62411> + = note: `#[warn(indirect_structural_match)]` on by default + +error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/consts-opaque.rs:53:9 + | +LL | BAR => {} // should not be emitting unreachable warning + | ^^^ + +error: unreachable pattern + --> $DIR/consts-opaque.rs:53:9 + | +LL | Bar => {} + | --- matches any value +LL | BAR => {} // should not be emitting unreachable warning + | ^^^ unreachable pattern + +error: unreachable pattern + --> $DIR/consts-opaque.rs:56:9 + | +LL | Bar => {} + | --- matches any value +... +LL | _ => {} + | ^ unreachable pattern + +error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/consts-opaque.rs:61:9 + | +LL | BAR => {} + | ^^^ + +error: unreachable pattern + --> $DIR/consts-opaque.rs:63:9 + | +LL | BAR => {} + | --- matches any value +LL | +LL | Bar => {} // should not be emitting unreachable warning + | ^^^ unreachable pattern + +error: unreachable pattern + --> $DIR/consts-opaque.rs:65:9 + | +LL | BAR => {} + | --- matches any value +... +LL | _ => {} + | ^ unreachable pattern + +error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/consts-opaque.rs:70:9 + | +LL | BAR => {} + | ^^^ + +error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/consts-opaque.rs:72:9 + | +LL | BAR => {} // should not be emitting unreachable warning + | ^^^ + +error: unreachable pattern + --> $DIR/consts-opaque.rs:72:9 + | +LL | BAR => {} + | --- matches any value +LL | +LL | BAR => {} // should not be emitting unreachable warning + | ^^^ unreachable pattern + +error: unreachable pattern + --> $DIR/consts-opaque.rs:75:9 + | +LL | BAR => {} + | --- matches any value +... +LL | _ => {} // should not be emitting unreachable warning + | ^ unreachable pattern + +error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/consts-opaque.rs:80:9 + | +LL | BAZ => {} + | ^^^ + +error: unreachable pattern + --> $DIR/consts-opaque.rs:82:9 + | +LL | BAZ => {} + | --- matches any value +LL | +LL | Baz::Baz1 => {} // should not be emitting unreachable warning + | ^^^^^^^^^ unreachable pattern + +error: unreachable pattern + --> $DIR/consts-opaque.rs:84:9 + | +LL | BAZ => {} + | --- matches any value +... +LL | _ => {} + | ^ unreachable pattern + +error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/consts-opaque.rs:90:9 + | +LL | BAZ => {} + | ^^^ + +error: unreachable pattern + --> $DIR/consts-opaque.rs:92:9 + | +LL | BAZ => {} + | --- matches any value +LL | +LL | _ => {} + | ^ unreachable pattern + +error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/consts-opaque.rs:97:9 + | +LL | BAZ => {} + | ^^^ + +error: unreachable pattern + --> $DIR/consts-opaque.rs:99:9 + | +LL | BAZ => {} + | --- matches any value +LL | +LL | Baz::Baz2 => {} // should not be emitting unreachable warning + | ^^^^^^^^^ unreachable pattern + +error: unreachable pattern + --> $DIR/consts-opaque.rs:101:9 + | +LL | BAZ => {} + | --- matches any value +... +LL | _ => {} // should not be emitting unreachable warning + | ^ unreachable pattern + +error: unreachable pattern + --> $DIR/consts-opaque.rs:127:9 + | +LL | Wrap(_) => {} + | ------- matches any value +LL | WRAPQUUX => {} // detected unreachable because we do inspect the `Wrap` layer + | ^^^^^^^^ unreachable pattern + +error: unreachable pattern + --> $DIR/consts-opaque.rs:141:9 + | +LL | WHOKNOWSQUUX => {} // detected unreachable because we do inspect the `WhoKnows` layer + | ^^^^^^^^^^^^ + +error: aborting due to 24 previous errors; 1 warning emitted + diff --git a/tests/ui/pattern/usefulness/deny-irrefutable-let-patterns.rs b/tests/ui/pattern/usefulness/deny-irrefutable-let-patterns.rs new file mode 100644 index 000000000..c85af7f3b --- /dev/null +++ b/tests/ui/pattern/usefulness/deny-irrefutable-let-patterns.rs @@ -0,0 +1,16 @@ +#![feature(if_let_guard)] + +#![deny(irrefutable_let_patterns)] + +fn main() { + if let _ = 5 {} //~ ERROR irrefutable `if let` pattern + + while let _ = 5 { //~ ERROR irrefutable `while let` pattern + break; + } + + match 5 { + _ if let _ = 2 => {} //~ ERROR irrefutable `if let` guard pattern + _ => {} + } +} diff --git a/tests/ui/pattern/usefulness/deny-irrefutable-let-patterns.stderr b/tests/ui/pattern/usefulness/deny-irrefutable-let-patterns.stderr new file mode 100644 index 000000000..cdb6b5c7a --- /dev/null +++ b/tests/ui/pattern/usefulness/deny-irrefutable-let-patterns.stderr @@ -0,0 +1,34 @@ +error: irrefutable `if let` pattern + --> $DIR/deny-irrefutable-let-patterns.rs:6:8 + | +LL | if let _ = 5 {} + | ^^^^^^^^^ + | + = note: this pattern will always match, so the `if let` is useless + = help: consider replacing the `if let` with a `let` +note: the lint level is defined here + --> $DIR/deny-irrefutable-let-patterns.rs:3:9 + | +LL | #![deny(irrefutable_let_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: irrefutable `while let` pattern + --> $DIR/deny-irrefutable-let-patterns.rs:8:11 + | +LL | while let _ = 5 { + | ^^^^^^^^^ + | + = note: this pattern will always match, so the loop will never exit + = help: consider instead using a `loop { ... }` with a `let` inside it + +error: irrefutable `if let` guard pattern + --> $DIR/deny-irrefutable-let-patterns.rs:13:18 + | +LL | _ if let _ = 2 => {} + | ^ + | + = note: this pattern will always match, so the guard is useless + = help: consider removing the guard and adding a `let` inside the match arm + +error: aborting due to 3 previous errors + diff --git a/tests/ui/pattern/usefulness/doc-hidden-fields.rs b/tests/ui/pattern/usefulness/doc-hidden-fields.rs new file mode 100644 index 000000000..4163b87dc --- /dev/null +++ b/tests/ui/pattern/usefulness/doc-hidden-fields.rs @@ -0,0 +1,26 @@ +// aux-build:hidden.rs + +extern crate hidden; + +use hidden::HiddenStruct; + +struct InCrate { + a: usize, + b: bool, + #[doc(hidden)] + im_hidden: u8 +} + +fn main() { + let HiddenStruct { one, two } = HiddenStruct::default(); + //~^ pattern requires `..` due to inaccessible fields + + let HiddenStruct { one } = HiddenStruct::default(); + //~^ pattern does not mention field `two` and inaccessible fields + + let HiddenStruct { one, hide } = HiddenStruct::default(); + //~^ pattern does not mention field `two` + + let InCrate { a, b } = InCrate { a: 0, b: false, im_hidden: 0 }; + //~^ pattern does not mention field `im_hidden` +} diff --git a/tests/ui/pattern/usefulness/doc-hidden-fields.stderr b/tests/ui/pattern/usefulness/doc-hidden-fields.stderr new file mode 100644 index 000000000..f277bfbc8 --- /dev/null +++ b/tests/ui/pattern/usefulness/doc-hidden-fields.stderr @@ -0,0 +1,59 @@ +error: pattern requires `..` due to inaccessible fields + --> $DIR/doc-hidden-fields.rs:15:9 + | +LL | let HiddenStruct { one, two } = HiddenStruct::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: ignore the inaccessible and unused fields + | +LL | let HiddenStruct { one, two, .. } = HiddenStruct::default(); + | ++++ + +error[E0027]: pattern does not mention field `two` and inaccessible fields + --> $DIR/doc-hidden-fields.rs:18:9 + | +LL | let HiddenStruct { one } = HiddenStruct::default(); + | ^^^^^^^^^^^^^^^^^^^^ missing field `two` and inaccessible fields + | +help: include the missing field in the pattern and ignore the inaccessible fields + | +LL | let HiddenStruct { one, two, .. } = HiddenStruct::default(); + | ~~~~~~~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | let HiddenStruct { one, .. } = HiddenStruct::default(); + | ~~~~~~ + +error[E0027]: pattern does not mention field `two` + --> $DIR/doc-hidden-fields.rs:21:9 + | +LL | let HiddenStruct { one, hide } = HiddenStruct::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ missing field `two` + | +help: include the missing field in the pattern + | +LL | let HiddenStruct { one, hide, two } = HiddenStruct::default(); + | ~~~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | let HiddenStruct { one, hide, .. } = HiddenStruct::default(); + | ~~~~~~ + +error[E0027]: pattern does not mention field `im_hidden` + --> $DIR/doc-hidden-fields.rs:24:9 + | +LL | let InCrate { a, b } = InCrate { a: 0, b: false, im_hidden: 0 }; + | ^^^^^^^^^^^^^^^^ missing field `im_hidden` + | +help: include the missing field in the pattern + | +LL | let InCrate { a, b, im_hidden } = InCrate { a: 0, b: false, im_hidden: 0 }; + | ~~~~~~~~~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | let InCrate { a, b, .. } = InCrate { a: 0, b: false, im_hidden: 0 }; + | ~~~~~~ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0027`. diff --git a/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.rs b/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.rs new file mode 100644 index 000000000..5d4181a30 --- /dev/null +++ b/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.rs @@ -0,0 +1,43 @@ +// aux-build:hidden.rs + +extern crate hidden; + +use hidden::HiddenEnum; + +enum InCrate { + A, + B, + #[doc(hidden)] + C, +} + +fn main() { + match HiddenEnum::A { + HiddenEnum::A => {} + HiddenEnum::B => {} + } + //~^^^^ non-exhaustive patterns: `_` not covered + + match HiddenEnum::A { + HiddenEnum::A => {} + HiddenEnum::C => {} + } + //~^^^^ non-exhaustive patterns: `HiddenEnum::B` not covered + + match HiddenEnum::A { + HiddenEnum::A => {} + } + //~^^^ non-exhaustive patterns: `HiddenEnum::B` and `_` not covered + + match None { + None => {} + Some(HiddenEnum::A) => {} + } + //~^^^^ non-exhaustive patterns: `Some(HiddenEnum::B)` and `Some(_)` not covered + + match InCrate::A { + InCrate::A => {} + InCrate::B => {} + } + //~^^^^ non-exhaustive patterns: `InCrate::C` not covered +} diff --git a/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr b/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr new file mode 100644 index 000000000..17e1a2304 --- /dev/null +++ b/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr @@ -0,0 +1,102 @@ +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/doc-hidden-non-exhaustive.rs:15:11 + | +LL | match HiddenEnum::A { + | ^^^^^^^^^^^^^ pattern `_` not covered + | +note: `HiddenEnum` defined here + --> $DIR/auxiliary/hidden.rs:1:1 + | +LL | pub enum HiddenEnum { + | ^^^^^^^^^^^^^^^^^^^ + = note: the matched value is of type `HiddenEnum` +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 ~ HiddenEnum::B => {} +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `HiddenEnum::B` not covered + --> $DIR/doc-hidden-non-exhaustive.rs:21:11 + | +LL | match HiddenEnum::A { + | ^^^^^^^^^^^^^ pattern `HiddenEnum::B` not covered + | +note: `HiddenEnum` defined here + --> $DIR/auxiliary/hidden.rs:3:5 + | +LL | pub enum HiddenEnum { + | ------------------- +LL | A, +LL | B, + | ^ not covered + = note: the matched value is of type `HiddenEnum` +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 ~ HiddenEnum::C => {} +LL + HiddenEnum::B => todo!() + | + +error[E0004]: non-exhaustive patterns: `HiddenEnum::B` and `_` not covered + --> $DIR/doc-hidden-non-exhaustive.rs:27:11 + | +LL | match HiddenEnum::A { + | ^^^^^^^^^^^^^ patterns `HiddenEnum::B` and `_` not covered + | +note: `HiddenEnum` defined here + --> $DIR/auxiliary/hidden.rs:3:5 + | +LL | pub enum HiddenEnum { + | ------------------- +LL | A, +LL | B, + | ^ not covered + = note: the matched value is of type `HiddenEnum` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ HiddenEnum::A => {} +LL + HiddenEnum::B | _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `Some(HiddenEnum::B)` and `Some(_)` not covered + --> $DIR/doc-hidden-non-exhaustive.rs:32:11 + | +LL | match None { + | ^^^^ patterns `Some(HiddenEnum::B)` and `Some(_)` not covered + | +note: `Option<HiddenEnum>` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option<HiddenEnum>` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ Some(HiddenEnum::A) => {} +LL + Some(HiddenEnum::B) | Some(_) => todo!() + | + +error[E0004]: non-exhaustive patterns: `InCrate::C` not covered + --> $DIR/doc-hidden-non-exhaustive.rs:38:11 + | +LL | match InCrate::A { + | ^^^^^^^^^^ pattern `InCrate::C` not covered + | +note: `InCrate` defined here + --> $DIR/doc-hidden-non-exhaustive.rs:11:5 + | +LL | enum InCrate { + | ------- +... +LL | C, + | ^ not covered + = note: the matched value is of type `InCrate` +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 ~ InCrate::B => {} +LL + InCrate::C => todo!() + | + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr new file mode 100644 index 000000000..5e12bc1d2 --- /dev/null +++ b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr @@ -0,0 +1,303 @@ +error: unreachable pattern + --> $DIR/empty-match.rs:37:9 + | +LL | _ => {}, + | ^ + | +note: the lint level is defined here + --> $DIR/empty-match.rs:8:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/empty-match.rs:40:9 + | +LL | _ if false => {}, + | ^ + +error: unreachable pattern + --> $DIR/empty-match.rs:47:9 + | +LL | _ => {}, + | ^ + +error: unreachable pattern + --> $DIR/empty-match.rs:50:9 + | +LL | _ if false => {}, + | ^ + +error: unreachable pattern + --> $DIR/empty-match.rs:57:9 + | +LL | _ => {}, + | ^ + +error: unreachable pattern + --> $DIR/empty-match.rs:60:9 + | +LL | _ if false => {}, + | ^ + +error[E0004]: non-exhaustive patterns: type `u8` is non-empty + --> $DIR/empty-match.rs:78:20 + | +LL | match_no_arms!(0u8); + | ^^^ + | + = note: the matched value is of type `u8` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty + --> $DIR/empty-match.rs:79:20 + | +LL | match_no_arms!(NonEmptyStruct1); + | ^^^^^^^^^^^^^^^ + | +note: `NonEmptyStruct1` defined here + --> $DIR/empty-match.rs:14:8 + | +LL | struct NonEmptyStruct1; + | ^^^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyStruct1` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty + --> $DIR/empty-match.rs:80:20 + | +LL | match_no_arms!(NonEmptyStruct2(true)); + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: `NonEmptyStruct2` defined here + --> $DIR/empty-match.rs:15:8 + | +LL | struct NonEmptyStruct2(bool); + | ^^^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyStruct2` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty + --> $DIR/empty-match.rs:81:20 + | +LL | match_no_arms!((NonEmptyUnion1 { foo: () })); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `NonEmptyUnion1` defined here + --> $DIR/empty-match.rs:16:7 + | +LL | union NonEmptyUnion1 { + | ^^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyUnion1` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty + --> $DIR/empty-match.rs:82:20 + | +LL | match_no_arms!((NonEmptyUnion2 { foo: () })); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `NonEmptyUnion2` defined here + --> $DIR/empty-match.rs:19:7 + | +LL | union NonEmptyUnion2 { + | ^^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyUnion2` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered + --> $DIR/empty-match.rs:83:20 + | +LL | match_no_arms!(NonEmptyEnum1::Foo(true)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered + | +note: `NonEmptyEnum1` defined here + --> $DIR/empty-match.rs:24:5 + | +LL | enum NonEmptyEnum1 { + | ------------- +LL | Foo(bool), + | ^^^ not covered + = note: the matched value is of type `NonEmptyEnum1` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern + +error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered + --> $DIR/empty-match.rs:84:20 + | +LL | match_no_arms!(NonEmptyEnum2::Foo(true)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered + | +note: `NonEmptyEnum2` defined here + --> $DIR/empty-match.rs:27:5 + | +LL | enum NonEmptyEnum2 { + | ------------- +LL | Foo(bool), + | ^^^ not covered +LL | Bar, + | ^^^ not covered + = note: the matched value is of type `NonEmptyEnum2` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms + +error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered + --> $DIR/empty-match.rs:85:20 + | +LL | match_no_arms!(NonEmptyEnum5::V1); + | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered + | +note: `NonEmptyEnum5` defined here + --> $DIR/empty-match.rs:30:6 + | +LL | enum NonEmptyEnum5 { + | ^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyEnum5` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/empty-match.rs:87:24 + | +LL | match_guarded_arm!(0u8); + | ^^^ pattern `_` not covered + | + = note: the matched value is of type `u8` +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 ~ _ if false => {} +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered + --> $DIR/empty-match.rs:88:24 + | +LL | match_guarded_arm!(NonEmptyStruct1); + | ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered + | +note: `NonEmptyStruct1` defined here + --> $DIR/empty-match.rs:14:8 + | +LL | struct NonEmptyStruct1; + | ^^^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyStruct1` +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 ~ _ if false => {} +LL + NonEmptyStruct1 => todo!() + | + +error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered + --> $DIR/empty-match.rs:89:24 + | +LL | match_guarded_arm!(NonEmptyStruct2(true)); + | ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered + | +note: `NonEmptyStruct2` defined here + --> $DIR/empty-match.rs:15:8 + | +LL | struct NonEmptyStruct2(bool); + | ^^^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyStruct2` +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 ~ _ if false => {} +LL + NonEmptyStruct2(_) => todo!() + | + +error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered + --> $DIR/empty-match.rs:90:24 + | +LL | match_guarded_arm!((NonEmptyUnion1 { foo: () })); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered + | +note: `NonEmptyUnion1` defined here + --> $DIR/empty-match.rs:16:7 + | +LL | union NonEmptyUnion1 { + | ^^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyUnion1` +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 ~ _ if false => {} +LL + NonEmptyUnion1 { .. } => todo!() + | + +error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered + --> $DIR/empty-match.rs:91:24 + | +LL | match_guarded_arm!((NonEmptyUnion2 { foo: () })); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered + | +note: `NonEmptyUnion2` defined here + --> $DIR/empty-match.rs:19:7 + | +LL | union NonEmptyUnion2 { + | ^^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyUnion2` +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 ~ _ if false => {} +LL + NonEmptyUnion2 { .. } => todo!() + | + +error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered + --> $DIR/empty-match.rs:92:24 + | +LL | match_guarded_arm!(NonEmptyEnum1::Foo(true)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered + | +note: `NonEmptyEnum1` defined here + --> $DIR/empty-match.rs:24:5 + | +LL | enum NonEmptyEnum1 { + | ------------- +LL | Foo(bool), + | ^^^ not covered + = note: the matched value is of type `NonEmptyEnum1` +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 ~ _ if false => {} +LL + NonEmptyEnum1::Foo(_) => todo!() + | + +error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered + --> $DIR/empty-match.rs:93:24 + | +LL | match_guarded_arm!(NonEmptyEnum2::Foo(true)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered + | +note: `NonEmptyEnum2` defined here + --> $DIR/empty-match.rs:27:5 + | +LL | enum NonEmptyEnum2 { + | ------------- +LL | Foo(bool), + | ^^^ not covered +LL | Bar, + | ^^^ not covered + = note: the matched value is of type `NonEmptyEnum2` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ _ if false => {} +LL + NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!() + | + +error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered + --> $DIR/empty-match.rs:94:24 + | +LL | match_guarded_arm!(NonEmptyEnum5::V1); + | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered + | +note: `NonEmptyEnum5` defined here + --> $DIR/empty-match.rs:30:6 + | +LL | enum NonEmptyEnum5 { + | ^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyEnum5` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms + | +LL ~ _ if false => {} +LL + _ => todo!() + | + +error: aborting due to 22 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/empty-match.normal.stderr b/tests/ui/pattern/usefulness/empty-match.normal.stderr new file mode 100644 index 000000000..5e12bc1d2 --- /dev/null +++ b/tests/ui/pattern/usefulness/empty-match.normal.stderr @@ -0,0 +1,303 @@ +error: unreachable pattern + --> $DIR/empty-match.rs:37:9 + | +LL | _ => {}, + | ^ + | +note: the lint level is defined here + --> $DIR/empty-match.rs:8:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/empty-match.rs:40:9 + | +LL | _ if false => {}, + | ^ + +error: unreachable pattern + --> $DIR/empty-match.rs:47:9 + | +LL | _ => {}, + | ^ + +error: unreachable pattern + --> $DIR/empty-match.rs:50:9 + | +LL | _ if false => {}, + | ^ + +error: unreachable pattern + --> $DIR/empty-match.rs:57:9 + | +LL | _ => {}, + | ^ + +error: unreachable pattern + --> $DIR/empty-match.rs:60:9 + | +LL | _ if false => {}, + | ^ + +error[E0004]: non-exhaustive patterns: type `u8` is non-empty + --> $DIR/empty-match.rs:78:20 + | +LL | match_no_arms!(0u8); + | ^^^ + | + = note: the matched value is of type `u8` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty + --> $DIR/empty-match.rs:79:20 + | +LL | match_no_arms!(NonEmptyStruct1); + | ^^^^^^^^^^^^^^^ + | +note: `NonEmptyStruct1` defined here + --> $DIR/empty-match.rs:14:8 + | +LL | struct NonEmptyStruct1; + | ^^^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyStruct1` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty + --> $DIR/empty-match.rs:80:20 + | +LL | match_no_arms!(NonEmptyStruct2(true)); + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: `NonEmptyStruct2` defined here + --> $DIR/empty-match.rs:15:8 + | +LL | struct NonEmptyStruct2(bool); + | ^^^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyStruct2` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty + --> $DIR/empty-match.rs:81:20 + | +LL | match_no_arms!((NonEmptyUnion1 { foo: () })); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `NonEmptyUnion1` defined here + --> $DIR/empty-match.rs:16:7 + | +LL | union NonEmptyUnion1 { + | ^^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyUnion1` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty + --> $DIR/empty-match.rs:82:20 + | +LL | match_no_arms!((NonEmptyUnion2 { foo: () })); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `NonEmptyUnion2` defined here + --> $DIR/empty-match.rs:19:7 + | +LL | union NonEmptyUnion2 { + | ^^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyUnion2` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered + --> $DIR/empty-match.rs:83:20 + | +LL | match_no_arms!(NonEmptyEnum1::Foo(true)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered + | +note: `NonEmptyEnum1` defined here + --> $DIR/empty-match.rs:24:5 + | +LL | enum NonEmptyEnum1 { + | ------------- +LL | Foo(bool), + | ^^^ not covered + = note: the matched value is of type `NonEmptyEnum1` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern + +error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered + --> $DIR/empty-match.rs:84:20 + | +LL | match_no_arms!(NonEmptyEnum2::Foo(true)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered + | +note: `NonEmptyEnum2` defined here + --> $DIR/empty-match.rs:27:5 + | +LL | enum NonEmptyEnum2 { + | ------------- +LL | Foo(bool), + | ^^^ not covered +LL | Bar, + | ^^^ not covered + = note: the matched value is of type `NonEmptyEnum2` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms + +error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered + --> $DIR/empty-match.rs:85:20 + | +LL | match_no_arms!(NonEmptyEnum5::V1); + | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered + | +note: `NonEmptyEnum5` defined here + --> $DIR/empty-match.rs:30:6 + | +LL | enum NonEmptyEnum5 { + | ^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyEnum5` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/empty-match.rs:87:24 + | +LL | match_guarded_arm!(0u8); + | ^^^ pattern `_` not covered + | + = note: the matched value is of type `u8` +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 ~ _ if false => {} +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered + --> $DIR/empty-match.rs:88:24 + | +LL | match_guarded_arm!(NonEmptyStruct1); + | ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered + | +note: `NonEmptyStruct1` defined here + --> $DIR/empty-match.rs:14:8 + | +LL | struct NonEmptyStruct1; + | ^^^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyStruct1` +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 ~ _ if false => {} +LL + NonEmptyStruct1 => todo!() + | + +error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered + --> $DIR/empty-match.rs:89:24 + | +LL | match_guarded_arm!(NonEmptyStruct2(true)); + | ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered + | +note: `NonEmptyStruct2` defined here + --> $DIR/empty-match.rs:15:8 + | +LL | struct NonEmptyStruct2(bool); + | ^^^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyStruct2` +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 ~ _ if false => {} +LL + NonEmptyStruct2(_) => todo!() + | + +error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered + --> $DIR/empty-match.rs:90:24 + | +LL | match_guarded_arm!((NonEmptyUnion1 { foo: () })); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered + | +note: `NonEmptyUnion1` defined here + --> $DIR/empty-match.rs:16:7 + | +LL | union NonEmptyUnion1 { + | ^^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyUnion1` +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 ~ _ if false => {} +LL + NonEmptyUnion1 { .. } => todo!() + | + +error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered + --> $DIR/empty-match.rs:91:24 + | +LL | match_guarded_arm!((NonEmptyUnion2 { foo: () })); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered + | +note: `NonEmptyUnion2` defined here + --> $DIR/empty-match.rs:19:7 + | +LL | union NonEmptyUnion2 { + | ^^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyUnion2` +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 ~ _ if false => {} +LL + NonEmptyUnion2 { .. } => todo!() + | + +error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered + --> $DIR/empty-match.rs:92:24 + | +LL | match_guarded_arm!(NonEmptyEnum1::Foo(true)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered + | +note: `NonEmptyEnum1` defined here + --> $DIR/empty-match.rs:24:5 + | +LL | enum NonEmptyEnum1 { + | ------------- +LL | Foo(bool), + | ^^^ not covered + = note: the matched value is of type `NonEmptyEnum1` +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 ~ _ if false => {} +LL + NonEmptyEnum1::Foo(_) => todo!() + | + +error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered + --> $DIR/empty-match.rs:93:24 + | +LL | match_guarded_arm!(NonEmptyEnum2::Foo(true)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered + | +note: `NonEmptyEnum2` defined here + --> $DIR/empty-match.rs:27:5 + | +LL | enum NonEmptyEnum2 { + | ------------- +LL | Foo(bool), + | ^^^ not covered +LL | Bar, + | ^^^ not covered + = note: the matched value is of type `NonEmptyEnum2` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ _ if false => {} +LL + NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!() + | + +error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered + --> $DIR/empty-match.rs:94:24 + | +LL | match_guarded_arm!(NonEmptyEnum5::V1); + | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered + | +note: `NonEmptyEnum5` defined here + --> $DIR/empty-match.rs:30:6 + | +LL | enum NonEmptyEnum5 { + | ^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyEnum5` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms + | +LL ~ _ if false => {} +LL + _ => todo!() + | + +error: aborting due to 22 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/empty-match.rs b/tests/ui/pattern/usefulness/empty-match.rs new file mode 100644 index 000000000..9cdc0413b --- /dev/null +++ b/tests/ui/pattern/usefulness/empty-match.rs @@ -0,0 +1,95 @@ +// aux-build:empty.rs +// revisions: normal exhaustive_patterns +// +// This tests a match with no arms on various types. +#![feature(never_type)] +#![feature(never_type_fallback)] +#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))] +#![deny(unreachable_patterns)] + +extern crate empty; + +enum EmptyEnum {} + +struct NonEmptyStruct1; +struct NonEmptyStruct2(bool); +union NonEmptyUnion1 { + foo: (), +} +union NonEmptyUnion2 { + foo: (), + bar: (), +} +enum NonEmptyEnum1 { + Foo(bool), +} +enum NonEmptyEnum2 { + Foo(bool), + Bar, +} +enum NonEmptyEnum5 { + V1, V2, V3, V4, V5, +} + +fn empty_enum(x: EmptyEnum) { + match x {} // ok + match x { + _ => {}, //~ ERROR unreachable pattern + } + match x { + _ if false => {}, //~ ERROR unreachable pattern + } +} + +fn empty_foreign_enum(x: empty::EmptyForeignEnum) { + match x {} // ok + match x { + _ => {}, //~ ERROR unreachable pattern + } + match x { + _ if false => {}, //~ ERROR unreachable pattern + } +} + +fn never(x: !) { + match x {} // ok + match x { + _ => {}, //~ ERROR unreachable pattern + } + match x { + _ if false => {}, //~ ERROR unreachable pattern + } +} + +macro_rules! match_no_arms { + ($e:expr) => { + match $e {} + }; +} +macro_rules! match_guarded_arm { + ($e:expr) => { + match $e { + _ if false => {} + } + }; +} + +fn main() { + match_no_arms!(0u8); //~ ERROR type `u8` is non-empty + match_no_arms!(NonEmptyStruct1); //~ ERROR type `NonEmptyStruct1` is non-empty + match_no_arms!(NonEmptyStruct2(true)); //~ ERROR type `NonEmptyStruct2` is non-empty + match_no_arms!((NonEmptyUnion1 { foo: () })); //~ ERROR type `NonEmptyUnion1` is non-empty + match_no_arms!((NonEmptyUnion2 { foo: () })); //~ ERROR type `NonEmptyUnion2` is non-empty + match_no_arms!(NonEmptyEnum1::Foo(true)); //~ ERROR `NonEmptyEnum1::Foo(_)` not covered + match_no_arms!(NonEmptyEnum2::Foo(true)); //~ ERROR `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered + match_no_arms!(NonEmptyEnum5::V1); //~ ERROR `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered + + match_guarded_arm!(0u8); //~ ERROR `_` not covered + match_guarded_arm!(NonEmptyStruct1); //~ ERROR `NonEmptyStruct1` not covered + match_guarded_arm!(NonEmptyStruct2(true)); //~ ERROR `NonEmptyStruct2(_)` not covered + match_guarded_arm!((NonEmptyUnion1 { foo: () })); //~ ERROR `NonEmptyUnion1 { .. }` not covered + match_guarded_arm!((NonEmptyUnion2 { foo: () })); //~ ERROR `NonEmptyUnion2 { .. }` not covered + match_guarded_arm!(NonEmptyEnum1::Foo(true)); //~ ERROR `NonEmptyEnum1::Foo(_)` not covered + match_guarded_arm!(NonEmptyEnum2::Foo(true)); //~ ERROR `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered + match_guarded_arm!(NonEmptyEnum5::V1); //~ ERROR `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered +} diff --git a/tests/ui/pattern/usefulness/floats.rs b/tests/ui/pattern/usefulness/floats.rs new file mode 100644 index 000000000..095f5ac9a --- /dev/null +++ b/tests/ui/pattern/usefulness/floats.rs @@ -0,0 +1,19 @@ +#![allow(illegal_floating_point_literal_pattern)] +#![deny(unreachable_patterns)] + +fn main() { + match 0.0 { + 0.0..=1.0 => {} + _ => {} // ok + } + + match 0.0 { //~ ERROR non-exhaustive patterns + 0.0..=1.0 => {} + } + + match 1.0f64 { + 0.01f64 ..= 6.5f64 => {} + 0.02f64 => {} //~ ERROR unreachable pattern + _ => {} + }; +} diff --git a/tests/ui/pattern/usefulness/floats.stderr b/tests/ui/pattern/usefulness/floats.stderr new file mode 100644 index 000000000..c926e50b3 --- /dev/null +++ b/tests/ui/pattern/usefulness/floats.stderr @@ -0,0 +1,28 @@ +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/floats.rs:10:11 + | +LL | match 0.0 { + | ^^^ pattern `_` not covered + | + = note: the matched value is of type `f64` +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 ~ 0.0..=1.0 => {} +LL + _ => todo!() + | + +error: unreachable pattern + --> $DIR/floats.rs:16:7 + | +LL | 0.02f64 => {} + | ^^^^^^^ + | +note: the lint level is defined here + --> $DIR/floats.rs:2:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/guards.rs b/tests/ui/pattern/usefulness/guards.rs new file mode 100644 index 000000000..b15440cf6 --- /dev/null +++ b/tests/ui/pattern/usefulness/guards.rs @@ -0,0 +1,22 @@ +#![feature(exclusive_range_pattern)] +#![deny(unreachable_patterns)] + +enum Q { R(Option<usize>) } + +pub fn main() { + match Q::R(None) { + Q::R(S) if S.is_some() => {} + _ => {} + } + + match 0u8 { //~ ERROR non-exhaustive patterns + 0 .. 128 => {} + 128 ..= 255 if true => {} + } + + match 0u8 { + 0 .. 128 => {} + 128 ..= 255 if false => {} + 128 ..= 255 => {} // ok, because previous arm was guarded + } +} diff --git a/tests/ui/pattern/usefulness/guards.stderr b/tests/ui/pattern/usefulness/guards.stderr new file mode 100644 index 000000000..0c1563c16 --- /dev/null +++ b/tests/ui/pattern/usefulness/guards.stderr @@ -0,0 +1,16 @@ +error[E0004]: non-exhaustive patterns: `128_u8..=u8::MAX` not covered + --> $DIR/guards.rs:12:11 + | +LL | match 0u8 { + | ^^^ pattern `128_u8..=u8::MAX` not covered + | + = note: the matched value is of type `u8` +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 ~ 128 ..= 255 if true => {} +LL + 128_u8..=u8::MAX => todo!() + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs b/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs new file mode 100644 index 000000000..0f5f49c4c --- /dev/null +++ b/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs @@ -0,0 +1,101 @@ +#![feature(exclusive_range_pattern)] +#![allow(overlapping_range_endpoints)] +#![deny(unreachable_patterns)] + +macro_rules! m { + ($s:expr, $($t:tt)+) => { + match $s { $($t)+ => {} } + } +} + +macro_rules! test_int { + ($s:expr, $min:path, $max:path) => { + m!($s, $min..=$max); + m!($s, $min..5 | 5..=$max); + m!($s, $min..=4 | 5..=$max); + m!($s, $min..$max | $max); + m!(($s, true), ($min..5, true) | (5..=$max, true) | ($min..=$max, false)); + } +} + +fn main() { + test_int!(0u8, u8::MIN, u8::MAX); + test_int!(0u16, u16::MIN, u16::MAX); + test_int!(0u32, u32::MIN, u32::MAX); + test_int!(0u64, u64::MIN, u64::MAX); + test_int!(0u128, u128::MIN, u128::MAX); + + test_int!(0i8, i8::MIN, i8::MAX); + test_int!(0i16, i16::MIN, i16::MAX); + test_int!(0i32, i32::MIN, i32::MAX); + test_int!(0i64, i64::MIN, i64::MAX); + test_int!(0i128, i128::MIN, i128::MAX); + + m!('a', '\u{0}'..=char::MAX); + m!('a', '\u{0}'..='\u{10_FFFF}'); + // We can get away with just covering the following two ranges, which correspond to all valid + // Unicode Scalar Values. + m!('a', '\u{0}'..='\u{D7FF}' | '\u{E000}'..=char::MAX); + m!('a', '\u{0}'..'\u{D7FF}' | '\u{D7FF}' | '\u{E000}'..=char::MAX); + + let 0..=255 = 0u8; + let -128..=127 = 0i8; + let -2147483648..=2147483647 = 0i32; + let '\u{0000}'..='\u{10FFFF}' = 'v'; + + // Almost exhaustive + m!(0u8, 0..255); //~ ERROR non-exhaustive patterns + m!(0u8, 0..=254); //~ ERROR non-exhaustive patterns + m!(0u8, 1..=255); //~ ERROR non-exhaustive patterns + m!(0u8, 0..42 | 43..=255); //~ ERROR non-exhaustive patterns + m!(0i8, -128..127); //~ ERROR non-exhaustive patterns + m!(0i8, -128..=126); //~ ERROR non-exhaustive patterns + m!(0i8, -127..=127); //~ ERROR non-exhaustive patterns + match 0i8 { //~ ERROR non-exhaustive patterns + i8::MIN ..= -1 => {} + 1 ..= i8::MAX => {} + } + const ALMOST_MAX: u128 = u128::MAX - 1; + m!(0u128, 0..=ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0u128, 0..=4); //~ ERROR non-exhaustive patterns + m!(0u128, 1..=u128::MAX); //~ ERROR non-exhaustive patterns + + // More complicatedly (non-)exhaustive + match 0u8 { + 0 ..= 30 => {} + 20 ..= 70 => {} + 50 ..= 255 => {} + } + match (0u8, true) { //~ ERROR non-exhaustive patterns + (0 ..= 125, false) => {} + (128 ..= 255, false) => {} + (0 ..= 255, true) => {} + } + match (0u8, true) { // ok + (0 ..= 125, false) => {} + (128 ..= 255, false) => {} + (0 ..= 255, true) => {} + (125 .. 128, false) => {} + } + match (true, 0u8) { + (true, 0 ..= 255) => {} + (false, 0 ..= 125) => {} + (false, 128 ..= 255) => {} + (false, 125 .. 128) => {} + } + match Some(0u8) { + None => {} + Some(0 ..= 125) => {} + Some(128 ..= 255) => {} + Some(125 .. 128) => {} + } + const FOO: u8 = 41; + const BAR: &u8 = &42; + match &0u8 { + 0..41 => {} + &FOO => {} + BAR => {} + 43..=255 => {} + } + +} diff --git a/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr b/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr new file mode 100644 index 000000000..f30ba05df --- /dev/null +++ b/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr @@ -0,0 +1,149 @@ +error[E0004]: non-exhaustive patterns: `u8::MAX` not covered + --> $DIR/exhaustiveness.rs:47:8 + | +LL | m!(0u8, 0..255); + | ^^^ pattern `u8::MAX` not covered + | + = note: the matched value is of type `u8` +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 $s { $($t)+ => {}, u8::MAX => todo!() } + | ++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `u8::MAX` not covered + --> $DIR/exhaustiveness.rs:48:8 + | +LL | m!(0u8, 0..=254); + | ^^^ pattern `u8::MAX` not covered + | + = note: the matched value is of type `u8` +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 $s { $($t)+ => {}, u8::MAX => todo!() } + | ++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `0_u8` not covered + --> $DIR/exhaustiveness.rs:49:8 + | +LL | m!(0u8, 1..=255); + | ^^^ pattern `0_u8` not covered + | + = note: the matched value is of type `u8` +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 $s { $($t)+ => {}, 0_u8 => todo!() } + | +++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `42_u8` not covered + --> $DIR/exhaustiveness.rs:50:8 + | +LL | m!(0u8, 0..42 | 43..=255); + | ^^^ pattern `42_u8` not covered + | + = note: the matched value is of type `u8` +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 $s { $($t)+ => {}, 42_u8 => todo!() } + | ++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `i8::MAX` not covered + --> $DIR/exhaustiveness.rs:51:8 + | +LL | m!(0i8, -128..127); + | ^^^ pattern `i8::MAX` not covered + | + = note: the matched value is of type `i8` +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 $s { $($t)+ => {}, i8::MAX => todo!() } + | ++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `i8::MAX` not covered + --> $DIR/exhaustiveness.rs:52:8 + | +LL | m!(0i8, -128..=126); + | ^^^ pattern `i8::MAX` not covered + | + = note: the matched value is of type `i8` +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 $s { $($t)+ => {}, i8::MAX => todo!() } + | ++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `i8::MIN` not covered + --> $DIR/exhaustiveness.rs:53:8 + | +LL | m!(0i8, -127..=127); + | ^^^ pattern `i8::MIN` not covered + | + = note: the matched value is of type `i8` +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 $s { $($t)+ => {}, i8::MIN => todo!() } + | ++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `0_i8` not covered + --> $DIR/exhaustiveness.rs:54:11 + | +LL | match 0i8 { + | ^^^ pattern `0_i8` not covered + | + = note: the matched value is of type `i8` +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 ~ 1 ..= i8::MAX => {} +LL + 0_i8 => todo!() + | + +error[E0004]: non-exhaustive patterns: `u128::MAX` not covered + --> $DIR/exhaustiveness.rs:59:8 + | +LL | m!(0u128, 0..=ALMOST_MAX); + | ^^^^^ pattern `u128::MAX` not covered + | + = note: the matched value is of type `u128` +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 $s { $($t)+ => {}, u128::MAX => todo!() } + | ++++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `5_u128..=u128::MAX` not covered + --> $DIR/exhaustiveness.rs:60:8 + | +LL | m!(0u128, 0..=4); + | ^^^^^ pattern `5_u128..=u128::MAX` not covered + | + = note: the matched value is of type `u128` +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 $s { $($t)+ => {}, 5_u128..=u128::MAX => todo!() } + | +++++++++++++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `0_u128` not covered + --> $DIR/exhaustiveness.rs:61:8 + | +LL | m!(0u128, 1..=u128::MAX); + | ^^^^^ pattern `0_u128` not covered + | + = note: the matched value is of type `u128` +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 $s { $($t)+ => {}, 0_u128 => todo!() } + | +++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `(126_u8..=127_u8, false)` not covered + --> $DIR/exhaustiveness.rs:69:11 + | +LL | match (0u8, true) { + | ^^^^^^^^^^^ pattern `(126_u8..=127_u8, false)` not covered + | + = note: the matched value is of type `(u8, bool)` +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 ~ (0 ..= 255, true) => {} +LL + (126_u8..=127_u8, false) => todo!() + | + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.rs b/tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.rs new file mode 100644 index 000000000..5ea92b070 --- /dev/null +++ b/tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.rs @@ -0,0 +1,59 @@ +#![feature(exclusive_range_pattern)] +#![deny(overlapping_range_endpoints)] + +macro_rules! m { + ($s:expr, $t1:pat, $t2:pat) => { + match $s { + $t1 => {} + $t2 => {} + _ => {} + } + } +} + +fn main() { + m!(0u8, 20..=30, 30..=40); //~ ERROR multiple patterns overlap on their endpoints + m!(0u8, 30..=40, 20..=30); //~ ERROR multiple patterns overlap on their endpoints + m!(0u8, 20..=30, 31..=40); + m!(0u8, 20..=30, 29..=40); + m!(0u8, 20.. 30, 29..=40); //~ ERROR multiple patterns overlap on their endpoints + m!(0u8, 20.. 30, 28..=40); + m!(0u8, 20.. 30, 30..=40); + m!(0u8, 20..=30, 30..=30); + m!(0u8, 20..=30, 30..=31); //~ ERROR multiple patterns overlap on their endpoints + m!(0u8, 20..=30, 29..=30); + m!(0u8, 20..=30, 20..=20); + m!(0u8, 20..=30, 20..=21); + m!(0u8, 20..=30, 19..=20); //~ ERROR multiple patterns overlap on their endpoints + m!(0u8, 20..=30, 20); + m!(0u8, 20..=30, 25); + m!(0u8, 20..=30, 30); + m!(0u8, 20.. 30, 29); + m!(0u8, 20, 20..=30); + m!(0u8, 25, 20..=30); + m!(0u8, 30, 20..=30); + + match 0u8 { + 0..=10 => {} + 20..=30 => {} + 10..=20 => {} //~ ERROR multiple patterns overlap on their endpoints + _ => {} + } + match (0u8, true) { + (0..=10, true) => {} + (10..20, true) => {} // not detected + (10..20, false) => {} + _ => {} + } + match (true, 0u8) { + (true, 0..=10) => {} + (true, 10..20) => {} //~ ERROR multiple patterns overlap on their endpoints + (false, 10..20) => {} + _ => {} + } + match Some(0u8) { + Some(0..=10) => {} + Some(10..20) => {} //~ ERROR multiple patterns overlap on their endpoints + _ => {} + } +} diff --git a/tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr b/tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr new file mode 100644 index 000000000..ea0e8f6e4 --- /dev/null +++ b/tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr @@ -0,0 +1,89 @@ +error: multiple patterns overlap on their endpoints + --> $DIR/overlapping_range_endpoints.rs:15:22 + | +LL | m!(0u8, 20..=30, 30..=40); + | ------- ^^^^^^^ ... with this range + | | + | this range overlaps on `30_u8`... + | + = note: you likely meant to write mutually exclusive ranges +note: the lint level is defined here + --> $DIR/overlapping_range_endpoints.rs:2:9 + | +LL | #![deny(overlapping_range_endpoints)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: multiple patterns overlap on their endpoints + --> $DIR/overlapping_range_endpoints.rs:16:22 + | +LL | m!(0u8, 30..=40, 20..=30); + | ------- ^^^^^^^ ... with this range + | | + | this range overlaps on `30_u8`... + | + = note: you likely meant to write mutually exclusive ranges + +error: multiple patterns overlap on their endpoints + --> $DIR/overlapping_range_endpoints.rs:19:22 + | +LL | m!(0u8, 20.. 30, 29..=40); + | ------- ^^^^^^^ ... with this range + | | + | this range overlaps on `29_u8`... + | + = note: you likely meant to write mutually exclusive ranges + +error: multiple patterns overlap on their endpoints + --> $DIR/overlapping_range_endpoints.rs:23:22 + | +LL | m!(0u8, 20..=30, 30..=31); + | ------- ^^^^^^^ ... with this range + | | + | this range overlaps on `30_u8`... + | + = note: you likely meant to write mutually exclusive ranges + +error: multiple patterns overlap on their endpoints + --> $DIR/overlapping_range_endpoints.rs:27:22 + | +LL | m!(0u8, 20..=30, 19..=20); + | ------- ^^^^^^^ ... with this range + | | + | this range overlaps on `20_u8`... + | + = note: you likely meant to write mutually exclusive ranges + +error: multiple patterns overlap on their endpoints + --> $DIR/overlapping_range_endpoints.rs:39:9 + | +LL | 0..=10 => {} + | ------ this range overlaps on `10_u8`... +LL | 20..=30 => {} + | ------- this range overlaps on `20_u8`... +LL | 10..=20 => {} + | ^^^^^^^ ... with this range + | + = note: you likely meant to write mutually exclusive ranges + +error: multiple patterns overlap on their endpoints + --> $DIR/overlapping_range_endpoints.rs:50:16 + | +LL | (true, 0..=10) => {} + | ------ this range overlaps on `10_u8`... +LL | (true, 10..20) => {} + | ^^^^^^ ... with this range + | + = note: you likely meant to write mutually exclusive ranges + +error: multiple patterns overlap on their endpoints + --> $DIR/overlapping_range_endpoints.rs:56:14 + | +LL | Some(0..=10) => {} + | ------ this range overlaps on `10_u8`... +LL | Some(10..20) => {} + | ^^^^^^ ... with this range + | + = note: you likely meant to write mutually exclusive ranges + +error: aborting due to 8 previous errors + diff --git a/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.allow.stderr b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.allow.stderr new file mode 100644 index 000000000..9f277fa1e --- /dev/null +++ b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.allow.stderr @@ -0,0 +1,17 @@ +error[E0004]: non-exhaustive patterns: type `usize` is non-empty + --> $DIR/pointer-sized-int.rs:48:11 + | +LL | match 7usize {} + | ^^^^^^ + | + = note: the matched value is of type `usize` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match 7usize { +LL + _ => todo!(), +LL + } + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr new file mode 100644 index 000000000..e3eb98ccd --- /dev/null +++ b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr @@ -0,0 +1,170 @@ +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/pointer-sized-int.rs:12:11 + | +LL | match 0usize { + | ^^^^^^ pattern `_` not covered + | + = note: the matched value is of type `usize` + = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching +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 ~ 0 ..= usize::MAX => {} +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/pointer-sized-int.rs:17:11 + | +LL | match 0isize { + | ^^^^^^ pattern `_` not covered + | + = note: the matched value is of type `isize` + = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching +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 ~ isize::MIN ..= isize::MAX => {} +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/pointer-sized-int.rs:22:8 + | +LL | m!(0usize, 0..=usize::MAX); + | ^^^^^^ pattern `_` not covered + | + = note: the matched value is of type `usize` + = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching +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 $s { $($t)+ => {}, _ => todo!() } + | ++++++++++++++ + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/pointer-sized-int.rs:24:8 + | +LL | m!(0usize, 0..5 | 5..=usize::MAX); + | ^^^^^^ pattern `_` not covered + | + = note: the matched value is of type `usize` + = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching +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 $s { $($t)+ => {}, _ => todo!() } + | ++++++++++++++ + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/pointer-sized-int.rs:26:8 + | +LL | m!(0usize, 0..usize::MAX | usize::MAX); + | ^^^^^^ pattern `_` not covered + | + = note: the matched value is of type `usize` + = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching +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 $s { $($t)+ => {}, _ => todo!() } + | ++++++++++++++ + +error[E0004]: non-exhaustive patterns: `(_, _)` not covered + --> $DIR/pointer-sized-int.rs:28:8 + | +LL | m!((0usize, true), (0..5, true) | (5..=usize::MAX, true) | (0..=usize::MAX, false)); + | ^^^^^^^^^^^^^^ pattern `(_, _)` not covered + | + = note: the matched value is of type `(usize, bool)` +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 $s { $($t)+ => {}, (_, _) => todo!() } + | +++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/pointer-sized-int.rs:31:8 + | +LL | m!(0isize, isize::MIN..=isize::MAX); + | ^^^^^^ pattern `_` not covered + | + = note: the matched value is of type `isize` + = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching +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 $s { $($t)+ => {}, _ => todo!() } + | ++++++++++++++ + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/pointer-sized-int.rs:33:8 + | +LL | m!(0isize, isize::MIN..5 | 5..=isize::MAX); + | ^^^^^^ pattern `_` not covered + | + = note: the matched value is of type `isize` + = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching +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 $s { $($t)+ => {}, _ => todo!() } + | ++++++++++++++ + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/pointer-sized-int.rs:35:8 + | +LL | m!(0isize, isize::MIN..isize::MAX | isize::MAX); + | ^^^^^^ pattern `_` not covered + | + = note: the matched value is of type `isize` + = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching +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 $s { $($t)+ => {}, _ => todo!() } + | ++++++++++++++ + +error[E0004]: non-exhaustive patterns: `(_, _)` not covered + --> $DIR/pointer-sized-int.rs:37:8 + | +LL | m!((0isize, true), (isize::MIN..5, true) + | ^^^^^^^^^^^^^^ pattern `(_, _)` not covered + | + = note: the matched value is of type `(isize, bool)` +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 $s { $($t)+ => {}, (_, _) => todo!() } + | +++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/pointer-sized-int.rs:41:11 + | +LL | match 0isize { + | ^^^^^^ pattern `_` not covered + | + = note: the matched value is of type `isize` + = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching +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 ~ 1 ..= isize::MAX => {} +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: type `usize` is non-empty + --> $DIR/pointer-sized-int.rs:48:11 + | +LL | match 7usize {} + | ^^^^^^ + | + = note: the matched value is of type `usize` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match 7usize { +LL + _ => todo!(), +LL + } + | + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.rs b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.rs new file mode 100644 index 000000000..1ed18c267 --- /dev/null +++ b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.rs @@ -0,0 +1,50 @@ +// revisions: allow deny +#![feature(exclusive_range_pattern)] +#![cfg_attr(allow, feature(precise_pointer_size_matching))] + +macro_rules! m { + ($s:expr, $($t:tt)+) => { + match $s { $($t)+ => {} } + } +} + +fn main() { + match 0usize { + //[deny]~^ ERROR non-exhaustive patterns + 0 ..= usize::MAX => {} + } + + match 0isize { + //[deny]~^ ERROR non-exhaustive patterns + isize::MIN ..= isize::MAX => {} + } + + m!(0usize, 0..=usize::MAX); + //[deny]~^ ERROR non-exhaustive patterns + m!(0usize, 0..5 | 5..=usize::MAX); + //[deny]~^ ERROR non-exhaustive patterns + m!(0usize, 0..usize::MAX | usize::MAX); + //[deny]~^ ERROR non-exhaustive patterns + m!((0usize, true), (0..5, true) | (5..=usize::MAX, true) | (0..=usize::MAX, false)); + //[deny]~^ ERROR non-exhaustive patterns + + m!(0isize, isize::MIN..=isize::MAX); + //[deny]~^ ERROR non-exhaustive patterns + m!(0isize, isize::MIN..5 | 5..=isize::MAX); + //[deny]~^ ERROR non-exhaustive patterns + m!(0isize, isize::MIN..isize::MAX | isize::MAX); + //[deny]~^ ERROR non-exhaustive patterns + m!((0isize, true), (isize::MIN..5, true) + | (5..=isize::MAX, true) | (isize::MIN..=isize::MAX, false)); + //[deny]~^^ ERROR non-exhaustive patterns + + match 0isize { + //[deny]~^ ERROR non-exhaustive patterns + isize::MIN ..= -1 => {} + 0 => {} + 1 ..= isize::MAX => {} + } + + match 7usize {} + //~^ ERROR non-exhaustive patterns +} diff --git a/tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.rs b/tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.rs new file mode 100644 index 000000000..a2aa655ca --- /dev/null +++ b/tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.rs @@ -0,0 +1,18 @@ +// This tests that the lint message explains the reason for the error. +fn main() { + match 0usize { + //~^ ERROR non-exhaustive patterns: `_` not covered + //~| NOTE pattern `_` not covered + //~| NOTE the matched value is of type `usize` + //~| NOTE `usize` does not have a fixed maximum value + 0..=usize::MAX => {} + } + + match 0isize { + //~^ ERROR non-exhaustive patterns: `_` not covered + //~| NOTE pattern `_` not covered + //~| NOTE the matched value is of type `isize` + //~| NOTE `isize` does not have a fixed maximum value + isize::MIN..=isize::MAX => {} + } +} diff --git a/tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.stderr b/tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.stderr new file mode 100644 index 000000000..30492c982 --- /dev/null +++ b/tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.stderr @@ -0,0 +1,33 @@ +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/precise_pointer_matching-message.rs:3:11 + | +LL | match 0usize { + | ^^^^^^ pattern `_` not covered + | + = note: the matched value is of type `usize` + = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching +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 ~ 0..=usize::MAX => {} +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/precise_pointer_matching-message.rs:11:11 + | +LL | match 0isize { + | ^^^^^^ pattern `_` not covered + | + = note: the matched value is of type `isize` + = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching +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 ~ isize::MIN..=isize::MAX => {} +LL + _ => todo!() + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/integer-ranges/reachability.rs b/tests/ui/pattern/usefulness/integer-ranges/reachability.rs new file mode 100644 index 000000000..fb4d59b05 --- /dev/null +++ b/tests/ui/pattern/usefulness/integer-ranges/reachability.rs @@ -0,0 +1,113 @@ +#![feature(exclusive_range_pattern)] +#![allow(overlapping_range_endpoints)] +#![deny(unreachable_patterns)] + +macro_rules! m { + ($s:expr, $t1:pat, $t2:pat) => { + match $s { + $t1 => {} + $t2 => {} + _ => {} + } + } +} + +fn main() { + m!(0u8, 42, 41); + m!(0u8, 42, 42); //~ ERROR unreachable pattern + m!(0u8, 42, 43); + + m!(0u8, 20..=30, 19); + m!(0u8, 20..=30, 20); //~ ERROR unreachable pattern + m!(0u8, 20..=30, 21); //~ ERROR unreachable pattern + m!(0u8, 20..=30, 25); //~ ERROR unreachable pattern + m!(0u8, 20..=30, 29); //~ ERROR unreachable pattern + m!(0u8, 20..=30, 30); //~ ERROR unreachable pattern + m!(0u8, 20..=30, 31); + m!(0u8, 20..30, 19); + m!(0u8, 20..30, 20); //~ ERROR unreachable pattern + m!(0u8, 20..30, 21); //~ ERROR unreachable pattern + m!(0u8, 20..30, 25); //~ ERROR unreachable pattern + m!(0u8, 20..30, 29); //~ ERROR unreachable pattern + m!(0u8, 20..30, 30); + m!(0u8, 20..30, 31); + + m!(0u8, 20..=30, 20..=30); //~ ERROR unreachable pattern + m!(0u8, 20.. 30, 20.. 30); //~ ERROR unreachable pattern + m!(0u8, 20..=30, 20.. 30); //~ ERROR unreachable pattern + m!(0u8, 20..=30, 19..=30); + m!(0u8, 20..=30, 21..=30); //~ ERROR unreachable pattern + m!(0u8, 20..=30, 20..=29); //~ ERROR unreachable pattern + m!(0u8, 20..=30, 20..=31); + m!('a', 'A'..='z', 'a'..='z'); //~ ERROR unreachable pattern + + match 0u8 { + 5 => {}, + 6 => {}, + 7 => {}, + 8 => {}, + 5..=8 => {}, //~ ERROR unreachable pattern + _ => {}, + } + match 0u8 { + 0..10 => {}, + 10..20 => {}, + 5..15 => {}, //~ ERROR unreachable pattern + _ => {}, + } + match 0u8 { + 0..10 => {}, + 10..20 => {}, + 20..30 => {}, + 5..25 => {}, //~ ERROR unreachable pattern + _ => {}, + } + match 0u8 { + 0..10 => {}, + 10 => {}, + 11..=23 => {}, + 19..30 => {}, + 5..25 => {}, //~ ERROR unreachable pattern + _ => {}, + } + match 0usize { + 0..10 => {}, + 10..20 => {}, + 5..15 => {}, //~ ERROR unreachable pattern + _ => {}, + } + // Chars between '\u{D7FF}' and '\u{E000}' are invalid even though ranges that contain them are + // allowed. + match 'a' { + _ => {}, + '\u{D7FF}'..='\u{E000}' => {}, //~ ERROR unreachable pattern + } + match 'a' { + '\u{0}'..='\u{D7FF}' => {}, + '\u{E000}'..='\u{10_FFFF}' => {}, + '\u{D7FF}'..='\u{E000}' => {}, // FIXME should be unreachable + } + + match (0u8, true) { + (0..=255, false) => {} + (0..=255, true) => {} // ok + } + match (true, 0u8) { + (false, 0..=255) => {} + (true, 0..=255) => {} // ok + } + + const FOO: i32 = 42; + const BAR: &i32 = &42; + match &0 { + &42 => {} + &FOO => {} //~ ERROR unreachable pattern + BAR => {} //~ ERROR unreachable pattern + _ => {} + } + // Regression test, see https://github.com/rust-lang/rust/pull/66326#issuecomment-552889933 + match &0 { + BAR => {} // ok + _ => {} + } +} diff --git a/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr b/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr new file mode 100644 index 000000000..0ffb0ffd8 --- /dev/null +++ b/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr @@ -0,0 +1,154 @@ +error: unreachable pattern + --> $DIR/reachability.rs:17:17 + | +LL | m!(0u8, 42, 42); + | ^^ + | +note: the lint level is defined here + --> $DIR/reachability.rs:3:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/reachability.rs:21:22 + | +LL | m!(0u8, 20..=30, 20); + | ^^ + +error: unreachable pattern + --> $DIR/reachability.rs:22:22 + | +LL | m!(0u8, 20..=30, 21); + | ^^ + +error: unreachable pattern + --> $DIR/reachability.rs:23:22 + | +LL | m!(0u8, 20..=30, 25); + | ^^ + +error: unreachable pattern + --> $DIR/reachability.rs:24:22 + | +LL | m!(0u8, 20..=30, 29); + | ^^ + +error: unreachable pattern + --> $DIR/reachability.rs:25:22 + | +LL | m!(0u8, 20..=30, 30); + | ^^ + +error: unreachable pattern + --> $DIR/reachability.rs:28:21 + | +LL | m!(0u8, 20..30, 20); + | ^^ + +error: unreachable pattern + --> $DIR/reachability.rs:29:21 + | +LL | m!(0u8, 20..30, 21); + | ^^ + +error: unreachable pattern + --> $DIR/reachability.rs:30:21 + | +LL | m!(0u8, 20..30, 25); + | ^^ + +error: unreachable pattern + --> $DIR/reachability.rs:31:21 + | +LL | m!(0u8, 20..30, 29); + | ^^ + +error: unreachable pattern + --> $DIR/reachability.rs:35:22 + | +LL | m!(0u8, 20..=30, 20..=30); + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/reachability.rs:36:22 + | +LL | m!(0u8, 20.. 30, 20.. 30); + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/reachability.rs:37:22 + | +LL | m!(0u8, 20..=30, 20.. 30); + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/reachability.rs:39:22 + | +LL | m!(0u8, 20..=30, 21..=30); + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/reachability.rs:40:22 + | +LL | m!(0u8, 20..=30, 20..=29); + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/reachability.rs:42:24 + | +LL | m!('a', 'A'..='z', 'a'..='z'); + | ^^^^^^^^^ + +error: unreachable pattern + --> $DIR/reachability.rs:49:9 + | +LL | 5..=8 => {}, + | ^^^^^ + +error: unreachable pattern + --> $DIR/reachability.rs:55:9 + | +LL | 5..15 => {}, + | ^^^^^ + +error: unreachable pattern + --> $DIR/reachability.rs:62:9 + | +LL | 5..25 => {}, + | ^^^^^ + +error: unreachable pattern + --> $DIR/reachability.rs:70:9 + | +LL | 5..25 => {}, + | ^^^^^ + +error: unreachable pattern + --> $DIR/reachability.rs:76:9 + | +LL | 5..15 => {}, + | ^^^^^ + +error: unreachable pattern + --> $DIR/reachability.rs:83:9 + | +LL | _ => {}, + | - matches any value +LL | '\u{D7FF}'..='\u{E000}' => {}, + | ^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern + +error: unreachable pattern + --> $DIR/reachability.rs:104:9 + | +LL | &FOO => {} + | ^^^^ + +error: unreachable pattern + --> $DIR/reachability.rs:105:9 + | +LL | BAR => {} + | ^^^ + +error: aborting due to 24 previous errors + diff --git a/tests/ui/pattern/usefulness/irrefutable-let-patterns.rs b/tests/ui/pattern/usefulness/irrefutable-let-patterns.rs new file mode 100644 index 000000000..d400ef0bb --- /dev/null +++ b/tests/ui/pattern/usefulness/irrefutable-let-patterns.rs @@ -0,0 +1,11 @@ +// run-pass + +#![allow(irrefutable_let_patterns)] + +fn main() { + if let _ = 5 {} + + while let _ = 5 { + break; + } +} diff --git a/tests/ui/pattern/usefulness/irrefutable-unit.rs b/tests/ui/pattern/usefulness/irrefutable-unit.rs new file mode 100644 index 000000000..dd8f03b6d --- /dev/null +++ b/tests/ui/pattern/usefulness/irrefutable-unit.rs @@ -0,0 +1,6 @@ +// run-pass +// pretty-expanded FIXME #23616 + +pub fn main() { + let ((),()) = ((),()); +} diff --git a/tests/ui/pattern/usefulness/issue-12116.rs b/tests/ui/pattern/usefulness/issue-12116.rs new file mode 100644 index 000000000..3cb92a540 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-12116.rs @@ -0,0 +1,21 @@ +#![feature(box_patterns)] +#![allow(dead_code)] +#![allow(unused_variables)] +#![deny(unreachable_patterns)] + + +enum IntList { + Cons(isize, Box<IntList>), + Nil +} + +fn tail(source_list: &IntList) -> IntList { + match source_list { + &IntList::Cons(val, box ref next_list) => tail(next_list), + &IntList::Cons(val, box IntList::Nil) => IntList::Cons(val, Box::new(IntList::Nil)), + //~^ ERROR unreachable pattern + _ => panic!(), + } +} + +fn main() {} diff --git a/tests/ui/pattern/usefulness/issue-12116.stderr b/tests/ui/pattern/usefulness/issue-12116.stderr new file mode 100644 index 000000000..7f15c4703 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-12116.stderr @@ -0,0 +1,14 @@ +error: unreachable pattern + --> $DIR/issue-12116.rs:15:9 + | +LL | &IntList::Cons(val, box IntList::Nil) => IntList::Cons(val, Box::new(IntList::Nil)), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/issue-12116.rs:4:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/pattern/usefulness/issue-12369.rs b/tests/ui/pattern/usefulness/issue-12369.rs new file mode 100644 index 000000000..0481c1fd9 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-12369.rs @@ -0,0 +1,11 @@ +#![deny(unreachable_patterns)] + +fn main() { + let sl = vec![1,2,3]; + let v: isize = match &*sl { + &[] => 0, + &[a,b,c] => 3, + &[a, ref rest @ ..] => a, + &[10,a, ref rest @ ..] => 10 //~ ERROR: unreachable pattern + }; +} diff --git a/tests/ui/pattern/usefulness/issue-12369.stderr b/tests/ui/pattern/usefulness/issue-12369.stderr new file mode 100644 index 000000000..aab2be78c --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-12369.stderr @@ -0,0 +1,14 @@ +error: unreachable pattern + --> $DIR/issue-12369.rs:9:9 + | +LL | &[10,a, ref rest @ ..] => 10 + | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/issue-12369.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/pattern/usefulness/issue-13727.rs b/tests/ui/pattern/usefulness/issue-13727.rs new file mode 100644 index 000000000..7fb565ef3 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-13727.rs @@ -0,0 +1,15 @@ +#![allow(overflowing_literals)] +#![deny(unreachable_patterns)] + +fn test(val: u8) { + match val { + 256 => print!("0b1110\n"), + 512 => print!("0b1111\n"), + //~^ ERROR: unreachable pattern + _ => print!("fail\n"), + } +} + +fn main() { + test(1); +} diff --git a/tests/ui/pattern/usefulness/issue-13727.stderr b/tests/ui/pattern/usefulness/issue-13727.stderr new file mode 100644 index 000000000..07ca56a56 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-13727.stderr @@ -0,0 +1,14 @@ +error: unreachable pattern + --> $DIR/issue-13727.rs:7:5 + | +LL | 512 => print!("0b1111\n"), + | ^^^ + | +note: the lint level is defined here + --> $DIR/issue-13727.rs:2:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/pattern/usefulness/issue-15129.rs b/tests/ui/pattern/usefulness/issue-15129.rs new file mode 100644 index 000000000..f02e5c0c6 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-15129.rs @@ -0,0 +1,17 @@ +pub enum T { + T1(()), + T2(()), +} + +pub enum V { + V1(isize), + V2(bool), +} + +fn main() { + match (T::T1(()), V::V2(true)) { + //~^ ERROR non-exhaustive patterns: `(T::T1(()), V::V2(_))` and `(T::T2(()), V::V1(_))` not covered + (T::T1(()), V::V1(i)) => (), + (T::T2(()), V::V2(b)) => (), + } +} diff --git a/tests/ui/pattern/usefulness/issue-15129.stderr b/tests/ui/pattern/usefulness/issue-15129.stderr new file mode 100644 index 000000000..ee8410b76 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-15129.stderr @@ -0,0 +1,16 @@ +error[E0004]: non-exhaustive patterns: `(T::T1(()), V::V2(_))` and `(T::T2(()), V::V1(_))` not covered + --> $DIR/issue-15129.rs:12:11 + | +LL | match (T::T1(()), V::V2(true)) { + | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `(T::T1(()), V::V2(_))` and `(T::T2(()), V::V1(_))` not covered + | + = note: the matched value is of type `(T, V)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ (T::T2(()), V::V2(b)) => (), +LL ~ (T::T1(()), V::V2(_)) | (T::T2(()), V::V1(_)) => todo!(), + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-2111.rs b/tests/ui/pattern/usefulness/issue-2111.rs new file mode 100644 index 000000000..d27beaeff --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-2111.rs @@ -0,0 +1,11 @@ +fn foo(a: Option<usize>, b: Option<usize>) { + match (a, b) { + //~^ ERROR: non-exhaustive patterns: `(None, None)` and `(Some(_), Some(_))` not covered + (Some(a), Some(b)) if a == b => {} + (Some(_), None) | (None, Some(_)) => {} + } +} + +fn main() { + foo(None, None); +} diff --git a/tests/ui/pattern/usefulness/issue-2111.stderr b/tests/ui/pattern/usefulness/issue-2111.stderr new file mode 100644 index 000000000..01890b73c --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-2111.stderr @@ -0,0 +1,16 @@ +error[E0004]: non-exhaustive patterns: `(None, None)` and `(Some(_), Some(_))` not covered + --> $DIR/issue-2111.rs:2:11 + | +LL | match (a, b) { + | ^^^^^^ patterns `(None, None)` and `(Some(_), Some(_))` not covered + | + = note: the matched value is of type `(Option<usize>, Option<usize>)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ (Some(_), None) | (None, Some(_)) => {} +LL + (None, None) | (Some(_), Some(_)) => todo!() + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-30240-b.rs b/tests/ui/pattern/usefulness/issue-30240-b.rs new file mode 100644 index 000000000..01a6e7d8c --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-30240-b.rs @@ -0,0 +1,15 @@ +#![deny(unreachable_patterns)] + +fn main() { + match "world" { + "hello" => {} + _ => {}, + } + + match "world" { + ref _x if false => {} + "hello" => {} + "hello" => {} //~ ERROR unreachable pattern + _ => {}, + } +} diff --git a/tests/ui/pattern/usefulness/issue-30240-b.stderr b/tests/ui/pattern/usefulness/issue-30240-b.stderr new file mode 100644 index 000000000..59d64bc25 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-30240-b.stderr @@ -0,0 +1,14 @@ +error: unreachable pattern + --> $DIR/issue-30240-b.rs:12:9 + | +LL | "hello" => {} + | ^^^^^^^ + | +note: the lint level is defined here + --> $DIR/issue-30240-b.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/pattern/usefulness/issue-30240-rpass.rs b/tests/ui/pattern/usefulness/issue-30240-rpass.rs new file mode 100644 index 000000000..ab16614fd --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-30240-rpass.rs @@ -0,0 +1,14 @@ +// run-pass +fn main() { + let &ref a = &[0i32] as &[_]; + assert_eq!(a, &[0i32] as &[_]); + + let &ref a = "hello"; + assert_eq!(a, "hello"); + + match "foo" { + "fool" => unreachable!(), + "foo" => {}, + ref _x => unreachable!() + } +} diff --git a/tests/ui/pattern/usefulness/issue-30240.rs b/tests/ui/pattern/usefulness/issue-30240.rs new file mode 100644 index 000000000..a0c0d1626 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-30240.rs @@ -0,0 +1,10 @@ +fn main() { + match "world" { //~ ERROR non-exhaustive patterns: `&_` + "hello" => {} + } + + match "world" { //~ ERROR non-exhaustive patterns: `&_` + ref _x if false => {} + "hello" => {} + } +} diff --git a/tests/ui/pattern/usefulness/issue-30240.stderr b/tests/ui/pattern/usefulness/issue-30240.stderr new file mode 100644 index 000000000..759fdeafe --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-30240.stderr @@ -0,0 +1,29 @@ +error[E0004]: non-exhaustive patterns: `&_` not covered + --> $DIR/issue-30240.rs:2:11 + | +LL | match "world" { + | ^^^^^^^ pattern `&_` not covered + | + = note: the matched value is of type `&str` +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 ~ "hello" => {} +LL + &_ => todo!() + | + +error[E0004]: non-exhaustive patterns: `&_` not covered + --> $DIR/issue-30240.rs:6:11 + | +LL | match "world" { + | ^^^^^^^ pattern `&_` not covered + | + = note: the matched value is of type `&str` +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 ~ "hello" => {} +LL + &_ => todo!() + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-3096-1.rs b/tests/ui/pattern/usefulness/issue-3096-1.rs new file mode 100644 index 000000000..edc3b3223 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-3096-1.rs @@ -0,0 +1,3 @@ +fn main() { + match () { } //~ ERROR non-exhaustive +} diff --git a/tests/ui/pattern/usefulness/issue-3096-1.stderr b/tests/ui/pattern/usefulness/issue-3096-1.stderr new file mode 100644 index 000000000..d8884394f --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-3096-1.stderr @@ -0,0 +1,17 @@ +error[E0004]: non-exhaustive patterns: type `()` is non-empty + --> $DIR/issue-3096-1.rs:2:11 + | +LL | match () { } + | ^^ + | + = note: the matched value is of type `()` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match () { +LL + _ => todo!(), +LL ~ } + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-3096-2.rs b/tests/ui/pattern/usefulness/issue-3096-2.rs new file mode 100644 index 000000000..a26e42580 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-3096-2.rs @@ -0,0 +1,6 @@ +enum Bottom { } + +fn main() { + let x = &() as *const () as *const Bottom; + match x { } //~ ERROR non-exhaustive patterns +} diff --git a/tests/ui/pattern/usefulness/issue-3096-2.stderr b/tests/ui/pattern/usefulness/issue-3096-2.stderr new file mode 100644 index 000000000..2df8911ba --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-3096-2.stderr @@ -0,0 +1,17 @@ +error[E0004]: non-exhaustive patterns: type `*const Bottom` is non-empty + --> $DIR/issue-3096-2.rs:5:11 + | +LL | match x { } + | ^ + | + = note: the matched value is of type `*const Bottom` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match x { +LL + _ => todo!(), +LL ~ } + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-31221.rs b/tests/ui/pattern/usefulness/issue-31221.rs new file mode 100644 index 000000000..e03f1ec5b --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-31221.rs @@ -0,0 +1,34 @@ +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(non_snake_case)] +#![deny(unreachable_patterns)] + +#[derive(Clone, Copy)] +enum Enum { + Var1, + Var2, +} + +fn main() { + use Enum::*; + let s = Var1; + match s { + Var1 => (), + Var3 => (), + Var2 => (), + //~^ ERROR unreachable pattern + }; + match &s { + &Var1 => (), + &Var3 => (), + &Var2 => (), + //~^ ERROR unreachable pattern + }; + let t = (Var1, Var1); + match t { + (Var1, b) => (), + (c, d) => (), + anything => () + //~^ ERROR unreachable pattern + }; +} diff --git a/tests/ui/pattern/usefulness/issue-31221.stderr b/tests/ui/pattern/usefulness/issue-31221.stderr new file mode 100644 index 000000000..7d3491444 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-31221.stderr @@ -0,0 +1,32 @@ +error: unreachable pattern + --> $DIR/issue-31221.rs:18:9 + | +LL | Var3 => (), + | ---- matches any value +LL | Var2 => (), + | ^^^^ unreachable pattern + | +note: the lint level is defined here + --> $DIR/issue-31221.rs:4:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/issue-31221.rs:24:9 + | +LL | &Var3 => (), + | ----- matches any value +LL | &Var2 => (), + | ^^^^^ unreachable pattern + +error: unreachable pattern + --> $DIR/issue-31221.rs:31:9 + | +LL | (c, d) => (), + | ------ matches any value +LL | anything => () + | ^^^^^^^^ unreachable pattern + +error: aborting due to 3 previous errors + diff --git a/tests/ui/pattern/usefulness/issue-31561.rs b/tests/ui/pattern/usefulness/issue-31561.rs new file mode 100644 index 000000000..82414f041 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-31561.rs @@ -0,0 +1,11 @@ +enum Thing { + Foo(u8), + Bar, + Baz +} + +fn main() { + let Thing::Foo(y) = Thing::Foo(1); + //~^ ERROR refutable pattern in local binding + //~| `Thing::Bar` and `Thing::Baz` not covered +} diff --git a/tests/ui/pattern/usefulness/issue-31561.stderr b/tests/ui/pattern/usefulness/issue-31561.stderr new file mode 100644 index 000000000..5367de5e5 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-31561.stderr @@ -0,0 +1,27 @@ +error[E0005]: refutable pattern in local binding + --> $DIR/issue-31561.rs:8:9 + | +LL | let Thing::Foo(y) = Thing::Foo(1); + | ^^^^^^^^^^^^^ patterns `Thing::Bar` and `Thing::Baz` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +note: `Thing` defined here + --> $DIR/issue-31561.rs:1:6 + | +LL | enum Thing { + | ^^^^^ +LL | Foo(u8), +LL | Bar, + | --- not covered +LL | Baz + | --- not covered + = note: the matched value is of type `Thing` +help: you might want to use `let else` to handle the variants that aren't matched + | +LL | let Thing::Foo(y) = Thing::Foo(1) else { todo!() }; + | ++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/pattern/usefulness/issue-35609.rs b/tests/ui/pattern/usefulness/issue-35609.rs new file mode 100644 index 000000000..8ef75e351 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-35609.rs @@ -0,0 +1,43 @@ +enum Enum { + A, B, C, D, E, F +} +use Enum::*; + +struct S(Enum, ()); +struct Sd { x: Enum, y: () } + +fn main() { + match (A, ()) { //~ ERROR non-exhaustive + (A, _) => {} + } + + match (A, A) { //~ ERROR non-exhaustive + (_, A) => {} + } + + match ((A, ()), ()) { //~ ERROR non-exhaustive + ((A, ()), _) => {} + } + + match ((A, ()), A) { //~ ERROR non-exhaustive + ((A, ()), _) => {} + } + + match ((A, ()), ()) { //~ ERROR non-exhaustive + ((A, _), _) => {} + } + + + match S(A, ()) { //~ ERROR non-exhaustive + S(A, _) => {} + } + + match (Sd { x: A, y: () }) { //~ ERROR non-exhaustive + Sd { x: A, y: _ } => {} + } + + match Some(A) { //~ ERROR non-exhaustive + Some(A) => (), + None => () + } +} diff --git a/tests/ui/pattern/usefulness/issue-35609.stderr b/tests/ui/pattern/usefulness/issue-35609.stderr new file mode 100644 index 000000000..12113957d --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-35609.stderr @@ -0,0 +1,119 @@ +error[E0004]: non-exhaustive patterns: `(Enum::B, _)`, `(Enum::C, _)`, `(Enum::D, _)` and 2 more not covered + --> $DIR/issue-35609.rs:10:11 + | +LL | match (A, ()) { + | ^^^^^^^ patterns `(Enum::B, _)`, `(Enum::C, _)`, `(Enum::D, _)` and 2 more not covered + | + = note: the matched value is of type `(Enum, ())` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms + | +LL ~ (A, _) => {} +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `(_, Enum::B)`, `(_, Enum::C)`, `(_, Enum::D)` and 2 more not covered + --> $DIR/issue-35609.rs:14:11 + | +LL | match (A, A) { + | ^^^^^^ patterns `(_, Enum::B)`, `(_, Enum::C)`, `(_, Enum::D)` and 2 more not covered + | + = note: the matched value is of type `(Enum, Enum)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms + | +LL ~ (_, A) => {} +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `((Enum::B, _), _)`, `((Enum::C, _), _)`, `((Enum::D, _), _)` and 2 more not covered + --> $DIR/issue-35609.rs:18:11 + | +LL | match ((A, ()), ()) { + | ^^^^^^^^^^^^^ patterns `((Enum::B, _), _)`, `((Enum::C, _), _)`, `((Enum::D, _), _)` and 2 more not covered + | + = note: the matched value is of type `((Enum, ()), ())` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms + | +LL ~ ((A, ()), _) => {} +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `((Enum::B, _), _)`, `((Enum::C, _), _)`, `((Enum::D, _), _)` and 2 more not covered + --> $DIR/issue-35609.rs:22:11 + | +LL | match ((A, ()), A) { + | ^^^^^^^^^^^^ patterns `((Enum::B, _), _)`, `((Enum::C, _), _)`, `((Enum::D, _), _)` and 2 more not covered + | + = note: the matched value is of type `((Enum, ()), Enum)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms + | +LL ~ ((A, ()), _) => {} +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `((Enum::B, _), _)`, `((Enum::C, _), _)`, `((Enum::D, _), _)` and 2 more not covered + --> $DIR/issue-35609.rs:26:11 + | +LL | match ((A, ()), ()) { + | ^^^^^^^^^^^^^ patterns `((Enum::B, _), _)`, `((Enum::C, _), _)`, `((Enum::D, _), _)` and 2 more not covered + | + = note: the matched value is of type `((Enum, ()), ())` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms + | +LL ~ ((A, _), _) => {} +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `S(Enum::B, _)`, `S(Enum::C, _)`, `S(Enum::D, _)` and 2 more not covered + --> $DIR/issue-35609.rs:31:11 + | +LL | match S(A, ()) { + | ^^^^^^^^ patterns `S(Enum::B, _)`, `S(Enum::C, _)`, `S(Enum::D, _)` and 2 more not covered + | +note: `S` defined here + --> $DIR/issue-35609.rs:6:8 + | +LL | struct S(Enum, ()); + | ^ + = note: the matched value is of type `S` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms + | +LL ~ S(A, _) => {} +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `Sd { x: Enum::B, .. }`, `Sd { x: Enum::C, .. }`, `Sd { x: Enum::D, .. }` and 2 more not covered + --> $DIR/issue-35609.rs:35:11 + | +LL | match (Sd { x: A, y: () }) { + | ^^^^^^^^^^^^^^^^^^^^ patterns `Sd { x: Enum::B, .. }`, `Sd { x: Enum::C, .. }`, `Sd { x: Enum::D, .. }` and 2 more not covered + | +note: `Sd` defined here + --> $DIR/issue-35609.rs:7:8 + | +LL | struct Sd { x: Enum, y: () } + | ^^ + = note: the matched value is of type `Sd` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms + | +LL ~ Sd { x: A, y: _ } => {} +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `Some(Enum::B)`, `Some(Enum::C)`, `Some(Enum::D)` and 2 more not covered + --> $DIR/issue-35609.rs:39:11 + | +LL | match Some(A) { + | ^^^^^^^ patterns `Some(Enum::B)`, `Some(Enum::C)`, `Some(Enum::D)` and 2 more not covered + | +note: `Option<Enum>` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + = note: the matched value is of type `Option<Enum>` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms + | +LL ~ None => (), +LL + _ => todo!() + | + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-3601.rs b/tests/ui/pattern/usefulness/issue-3601.rs new file mode 100644 index 000000000..6215a2398 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-3601.rs @@ -0,0 +1,34 @@ +#![feature(box_patterns)] + +struct HTMLImageData { + image: Option<String> +} + +struct ElementData { + kind: Box<ElementKind> +} + +enum ElementKind { + HTMLImageElement(HTMLImageData) +} + +enum NodeKind { + Element(ElementData) +} + +struct NodeData { + kind: Box<NodeKind>, +} + +fn main() { + let mut id = HTMLImageData { image: None }; + let ed = ElementData { kind: Box::new(ElementKind::HTMLImageElement(id)) }; + let n = NodeData { kind: Box::new(NodeKind::Element(ed)) }; + + // n.b. span could be better + match n.kind { + box NodeKind::Element(ed) => match ed.kind { //~ ERROR non-exhaustive patterns + box ElementKind::HTMLImageElement(ref d) if d.image.is_some() => { true } + }, + }; +} diff --git a/tests/ui/pattern/usefulness/issue-3601.stderr b/tests/ui/pattern/usefulness/issue-3601.stderr new file mode 100644 index 000000000..59d7bcd4b --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-3601.stderr @@ -0,0 +1,18 @@ +error[E0004]: non-exhaustive patterns: `box _` not covered + --> $DIR/issue-3601.rs:30:44 + | +LL | box NodeKind::Element(ed) => match ed.kind { + | ^^^^^^^ pattern `box _` not covered + | +note: `Box<ElementKind>` defined here + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + = note: the matched value is of type `Box<ElementKind>` +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 ~ box ElementKind::HTMLImageElement(ref d) if d.image.is_some() => { true } +LL + box _ => todo!() + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-39362.rs b/tests/ui/pattern/usefulness/issue-39362.rs new file mode 100644 index 000000000..ea3c8f88e --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-39362.rs @@ -0,0 +1,18 @@ +enum Foo { + Bar { bar: Bar, id: usize } +} + +enum Bar { + A, B, C, D, E, F +} + +fn test(f: Foo) { + match f { + //~^ ERROR non-exhaustive patterns + //~| patterns + Foo::Bar { bar: Bar::A, .. } => (), + Foo::Bar { bar: Bar::B, .. } => (), + } +} + +fn main() {} diff --git a/tests/ui/pattern/usefulness/issue-39362.stderr b/tests/ui/pattern/usefulness/issue-39362.stderr new file mode 100644 index 000000000..b8b17918a --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-39362.stderr @@ -0,0 +1,23 @@ +error[E0004]: non-exhaustive patterns: `Foo::Bar { bar: Bar::C, .. }`, `Foo::Bar { bar: Bar::D, .. }`, `Foo::Bar { bar: Bar::E, .. }` and 1 more not covered + --> $DIR/issue-39362.rs:10:11 + | +LL | match f { + | ^ patterns `Foo::Bar { bar: Bar::C, .. }`, `Foo::Bar { bar: Bar::D, .. }`, `Foo::Bar { bar: Bar::E, .. }` and 1 more not covered + | +note: `Foo` defined here + --> $DIR/issue-39362.rs:2:5 + | +LL | enum Foo { + | --- +LL | Bar { bar: Bar, id: usize } + | ^^^ not covered + = note: the matched value is of type `Foo` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms + | +LL ~ Foo::Bar { bar: Bar::B, .. } => (), +LL ~ _ => todo!(), + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-40221.rs b/tests/ui/pattern/usefulness/issue-40221.rs new file mode 100644 index 000000000..e1f7e975b --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-40221.rs @@ -0,0 +1,16 @@ +enum P { + C(PC), +} + +enum PC { + Q, + QA, +} + +fn test(proto: P) { + match proto { //~ ERROR non-exhaustive patterns + P::C(PC::Q) => (), + } +} + +fn main() {} diff --git a/tests/ui/pattern/usefulness/issue-40221.stderr b/tests/ui/pattern/usefulness/issue-40221.stderr new file mode 100644 index 000000000..4973e42b0 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-40221.stderr @@ -0,0 +1,23 @@ +error[E0004]: non-exhaustive patterns: `P::C(PC::QA)` not covered + --> $DIR/issue-40221.rs:11:11 + | +LL | match proto { + | ^^^^^ pattern `P::C(PC::QA)` not covered + | +note: `P` defined here + --> $DIR/issue-40221.rs:2:5 + | +LL | enum P { + | - +LL | C(PC), + | ^ not covered + = note: the matched value is of type `P` +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 ~ P::C(PC::Q) => (), +LL ~ P::C(PC::QA) => todo!(), + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-4321.rs b/tests/ui/pattern/usefulness/issue-4321.rs new file mode 100644 index 000000000..9715f2eba --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-4321.rs @@ -0,0 +1,8 @@ +fn main() { + let tup = (true, true); + println!("foo {:}", match tup { //~ ERROR non-exhaustive patterns: `(true, false)` not covered + (false, false) => "foo", + (false, true) => "bar", + (true, true) => "baz" + }); +} diff --git a/tests/ui/pattern/usefulness/issue-4321.stderr b/tests/ui/pattern/usefulness/issue-4321.stderr new file mode 100644 index 000000000..293273174 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-4321.stderr @@ -0,0 +1,16 @@ +error[E0004]: non-exhaustive patterns: `(true, false)` not covered + --> $DIR/issue-4321.rs:3:31 + | +LL | println!("foo {:}", match tup { + | ^^^ pattern `(true, false)` not covered + | + = note: the matched value is of type `(bool, bool)` +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 ~ (true, true) => "baz", +LL + (true, false) => todo!() + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-50900.rs b/tests/ui/pattern/usefulness/issue-50900.rs new file mode 100644 index 000000000..9cc760e9a --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-50900.rs @@ -0,0 +1,19 @@ +#[derive(PartialEq, Eq)] +pub struct Tag(pub Context, pub u16); + +#[derive(PartialEq, Eq)] +pub enum Context { + Tiff, + Exif, +} + +impl Tag { + const ExifIFDPointer: Tag = Tag(Context::Tiff, 34665); +} + +fn main() { + match Tag::ExifIFDPointer { + //~^ ERROR: non-exhaustive patterns: `Tag(Context::Exif, _)` not covered + Tag::ExifIFDPointer => {} + } +} diff --git a/tests/ui/pattern/usefulness/issue-50900.stderr b/tests/ui/pattern/usefulness/issue-50900.stderr new file mode 100644 index 000000000..348246d28 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-50900.stderr @@ -0,0 +1,21 @@ +error[E0004]: non-exhaustive patterns: `Tag(Context::Exif, _)` not covered + --> $DIR/issue-50900.rs:15:11 + | +LL | match Tag::ExifIFDPointer { + | ^^^^^^^^^^^^^^^^^^^ pattern `Tag(Context::Exif, _)` not covered + | +note: `Tag` defined here + --> $DIR/issue-50900.rs:2:12 + | +LL | pub struct Tag(pub Context, pub u16); + | ^^^ + = note: the matched value is of type `Tag` +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 ~ Tag::ExifIFDPointer => {} +LL + Tag(Context::Exif, _) => todo!() + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-53820-slice-pattern-large-array.rs b/tests/ui/pattern/usefulness/issue-53820-slice-pattern-large-array.rs new file mode 100644 index 000000000..5b0482de2 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-53820-slice-pattern-large-array.rs @@ -0,0 +1,11 @@ +// check-pass + +// This used to cause a stack overflow during exhaustiveness checking in the compiler. + +fn main() { + const LARGE_SIZE: usize = 1024 * 1024; + let [..] = [0u8; LARGE_SIZE]; + match [0u8; LARGE_SIZE] { + [..] => {} + } +} diff --git a/tests/ui/pattern/usefulness/issue-56379.rs b/tests/ui/pattern/usefulness/issue-56379.rs new file mode 100644 index 000000000..097cf98d0 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-56379.rs @@ -0,0 +1,14 @@ +enum Foo { + A(bool), + B(bool), + C(bool), +} + +fn main() { + match Foo::A(true) { + //~^ ERROR non-exhaustive patterns: `Foo::A(false)`, `Foo::B(false)` and `Foo::C(false)` not covered + Foo::A(true) => {} + Foo::B(true) => {} + Foo::C(true) => {} + } +} diff --git a/tests/ui/pattern/usefulness/issue-56379.stderr b/tests/ui/pattern/usefulness/issue-56379.stderr new file mode 100644 index 000000000..6eed6bfae --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-56379.stderr @@ -0,0 +1,27 @@ +error[E0004]: non-exhaustive patterns: `Foo::A(false)`, `Foo::B(false)` and `Foo::C(false)` not covered + --> $DIR/issue-56379.rs:8:11 + | +LL | match Foo::A(true) { + | ^^^^^^^^^^^^ patterns `Foo::A(false)`, `Foo::B(false)` and `Foo::C(false)` not covered + | +note: `Foo` defined here + --> $DIR/issue-56379.rs:2:5 + | +LL | enum Foo { + | --- +LL | A(bool), + | ^ not covered +LL | B(bool), + | ^ not covered +LL | C(bool), + | ^ not covered + = note: the matched value is of type `Foo` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ Foo::C(true) => {} +LL + Foo::A(false) | Foo::B(false) | Foo::C(false) => todo!() + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-57472.rs b/tests/ui/pattern/usefulness/issue-57472.rs new file mode 100644 index 000000000..113100637 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-57472.rs @@ -0,0 +1,35 @@ +#![crate_type="lib"] +#![deny(unreachable_patterns)] + +mod test_struct { + // Test the exact copy of the minimal example + // posted in the issue. + pub struct Punned { + foo: [u8; 1], + bar: [u8; 1], + } + + pub fn test(punned: Punned) { + match punned { + Punned { foo: [_], .. } => println!("foo"), + Punned { bar: [_], .. } => println!("bar"), + //~^ ERROR unreachable pattern [unreachable_patterns] + } + } +} + +mod test_union { + // Test the same thing using a union. + pub union Punned { + foo: [u8; 1], + bar: [u8; 1], + } + + pub fn test(punned: Punned) { + match punned { + Punned { foo: [_] } => println!("foo"), + Punned { bar: [_] } => println!("bar"), + //~^ ERROR unreachable pattern [unreachable_patterns] + } + } +} diff --git a/tests/ui/pattern/usefulness/issue-57472.stderr b/tests/ui/pattern/usefulness/issue-57472.stderr new file mode 100644 index 000000000..26efdf6db --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-57472.stderr @@ -0,0 +1,20 @@ +error: unreachable pattern + --> $DIR/issue-57472.rs:15:13 + | +LL | Punned { bar: [_], .. } => println!("bar"), + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/issue-57472.rs:2:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/issue-57472.rs:31:13 + | +LL | Punned { bar: [_] } => println!("bar"), + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/pattern/usefulness/issue-65413-constants-and-slices-exhaustiveness.rs b/tests/ui/pattern/usefulness/issue-65413-constants-and-slices-exhaustiveness.rs new file mode 100644 index 000000000..54dfa889e --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-65413-constants-and-slices-exhaustiveness.rs @@ -0,0 +1,15 @@ +// check-pass + +#![deny(unreachable_patterns)] + +const C0: &'static [u8] = b"\x00"; + +fn main() { + let x: &[u8] = &[0]; + match x { + &[] => {} + &[1..=255] => {} + C0 => {} + &[_, _, ..] => {} + } +} diff --git a/tests/ui/pattern/usefulness/issue-66501.rs b/tests/ui/pattern/usefulness/issue-66501.rs new file mode 100644 index 000000000..ffcfd4ad8 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-66501.rs @@ -0,0 +1,12 @@ +// check-pass + +#![allow(unreachable_patterns)] + +fn main() { + const CONST: &[Option<()>; 1] = &[Some(())]; + match &[Some(())] { + &[None] => {} + CONST => {} + &[Some(())] => {} + } +} diff --git a/tests/ui/pattern/usefulness/issue-71930-type-of-match-scrutinee.rs b/tests/ui/pattern/usefulness/issue-71930-type-of-match-scrutinee.rs new file mode 100644 index 000000000..e2ff9ac87 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-71930-type-of-match-scrutinee.rs @@ -0,0 +1,22 @@ +// check-pass + +// In PR 71930, it was discovered that the code to retrieve the inferred type of a match scrutinee +// was incorrect. + +fn f() -> ! { + panic!() +} + +fn g() -> usize { + match f() { // Should infer type `bool` + false => 0, + true => 1, + } +} + +fn h() -> usize { + match f() { // Should infer type `!` + } +} + +fn main() {} diff --git a/tests/ui/pattern/usefulness/issue-72377.rs b/tests/ui/pattern/usefulness/issue-72377.rs new file mode 100644 index 000000000..b5ad3075c --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-72377.rs @@ -0,0 +1,17 @@ +#[derive(PartialEq, Eq)] +enum X { A, B, C, } + +fn main() { + let x = X::A; + let y = Some(X::A); + + match (x, y) { + //~^ ERROR non-exhaustive patterns: `(X::A, Some(X::A))`, `(X::A, Some(X::B))`, `(X::B, Some(X::B))` and 2 + //~| more not covered + (_, None) => false, + (v, Some(w)) if v == w => true, + (X::B, Some(X::C)) => false, + (X::B, Some(X::A)) => false, + (X::A, Some(X::C)) | (X::C, Some(X::A)) => false, + }; +} diff --git a/tests/ui/pattern/usefulness/issue-72377.stderr b/tests/ui/pattern/usefulness/issue-72377.stderr new file mode 100644 index 000000000..123dd051d --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-72377.stderr @@ -0,0 +1,16 @@ +error[E0004]: non-exhaustive patterns: `(X::A, Some(X::A))`, `(X::A, Some(X::B))`, `(X::B, Some(X::B))` and 2 more not covered + --> $DIR/issue-72377.rs:8:11 + | +LL | match (x, y) { + | ^^^^^^ patterns `(X::A, Some(X::A))`, `(X::A, Some(X::B))`, `(X::B, Some(X::B))` and 2 more not covered + | + = note: the matched value is of type `(X, Option<X>)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms + | +LL ~ (X::A, Some(X::C)) | (X::C, Some(X::A)) => false, +LL ~ _ => todo!(), + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-72476-and-89393-associated-type.rs b/tests/ui/pattern/usefulness/issue-72476-and-89393-associated-type.rs new file mode 100644 index 000000000..058f41967 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-72476-and-89393-associated-type.rs @@ -0,0 +1,56 @@ +// check-pass + +// From https://github.com/rust-lang/rust/issues/72476 +// and https://github.com/rust-lang/rust/issues/89393 + +trait Trait { + type Projection; +} + +struct A; +impl Trait for A { + type Projection = bool; +} + +struct B; +impl Trait for B { + type Projection = (u32, u32); +} + +struct Next<T: Trait>(T::Projection); + +fn foo1(item: Next<A>) { + match item { + Next(true) => {} + Next(false) => {} + } +} + +fn foo2(x: <A as Trait>::Projection) { + match x { + true => {} + false => {} + } +} + +fn foo3(x: Next<B>) { + let Next((_, _)) = x; + match x { + Next((_, _)) => {} + } +} + +fn foo4(x: <B as Trait>::Projection) { + let (_, _) = x; + match x { + (_, _) => {} + } +} + +fn foo5<T: Trait>(x: <T as Trait>::Projection) { + match x { + _ => {} + } +} + +fn main() {} diff --git a/tests/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.rs b/tests/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.rs new file mode 100644 index 000000000..cbfcf0eaf --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.rs @@ -0,0 +1,12 @@ +enum A {} + //~^ NOTE `A` defined here + //~| NOTE + +fn f(a: &A) { + match a {} + //~^ ERROR non-exhaustive patterns: type `&A` is non-empty + //~| NOTE the matched value is of type `&A` + //~| NOTE references are always considered inhabited +} + +fn main() {} diff --git a/tests/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.stderr b/tests/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.stderr new file mode 100644 index 000000000..bf05d616d --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.stderr @@ -0,0 +1,23 @@ +error[E0004]: non-exhaustive patterns: type `&A` is non-empty + --> $DIR/issue-78123-non-exhaustive-reference.rs:6:11 + | +LL | match a {} + | ^ + | +note: `A` defined here + --> $DIR/issue-78123-non-exhaustive-reference.rs:1:6 + | +LL | enum A {} + | ^ + = note: the matched value is of type `&A` + = note: references are always considered inhabited +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match a { +LL + _ => todo!(), +LL + } + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-78549-ref-pat-and-str.rs b/tests/ui/pattern/usefulness/issue-78549-ref-pat-and-str.rs new file mode 100644 index 000000000..2879caf2c --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-78549-ref-pat-and-str.rs @@ -0,0 +1,25 @@ +// check-pass +// From https://github.com/rust-lang/rust/issues/78549 + +fn main() { + match "foo" { + "foo" => {}, + &_ => {}, + } + + match "foo" { + &_ => {}, + "foo" => {}, + } + + match ("foo", 0, "bar") { + (&_, 0, &_) => {}, + ("foo", _, "bar") => {}, + (&_, _, &_) => {}, + } + + match (&"foo", "bar") { + (&"foo", &_) => {}, + (&&_, &_) => {}, + } +} diff --git a/tests/ui/pattern/usefulness/issue-80501-or-pat-and-macro.rs b/tests/ui/pattern/usefulness/issue-80501-or-pat-and-macro.rs new file mode 100644 index 000000000..aac7d7d53 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-80501-or-pat-and-macro.rs @@ -0,0 +1,27 @@ +// check-pass +#![deny(unreachable_patterns)] +pub enum TypeCtor { + Slice, + Array, +} + +pub struct ApplicationTy(TypeCtor); + +macro_rules! ty_app { + ($ctor:pat) => { + ApplicationTy($ctor) + }; +} + +fn _foo(ty: ApplicationTy) { + match ty { + ty_app!(TypeCtor::Array) | ty_app!(TypeCtor::Slice) => {} + } + + // same as above, with the macro expanded + match ty { + ApplicationTy(TypeCtor::Array) | ApplicationTy(TypeCtor::Slice) => {} + } +} + +fn main() {} diff --git a/tests/ui/pattern/usefulness/issue-82772-match-box-as-struct.rs b/tests/ui/pattern/usefulness/issue-82772-match-box-as-struct.rs new file mode 100644 index 000000000..c1bfcc734 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-82772-match-box-as-struct.rs @@ -0,0 +1,6 @@ +// This used to ICE in exhaustiveness checking. Explanation here: +// https://github.com/rust-lang/rust/issues/82772#issuecomment-905946768 +fn main() { + let Box { 1: _, .. }: Box<()>; //~ ERROR field `1` of + let Box { .. }: Box<()>; +} diff --git a/tests/ui/pattern/usefulness/issue-82772-match-box-as-struct.stderr b/tests/ui/pattern/usefulness/issue-82772-match-box-as-struct.stderr new file mode 100644 index 000000000..2c8c85bb1 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-82772-match-box-as-struct.stderr @@ -0,0 +1,9 @@ +error[E0451]: field `1` of struct `Box` is private + --> $DIR/issue-82772-match-box-as-struct.rs:4:15 + | +LL | let Box { 1: _, .. }: Box<()>; + | ^^^^ private field + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0451`. diff --git a/tests/ui/pattern/usefulness/issue-88747.rs b/tests/ui/pattern/usefulness/issue-88747.rs new file mode 100644 index 000000000..948c99f9c --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-88747.rs @@ -0,0 +1,14 @@ +// check-pass: this used to be a stack overflow because of recursion in `usefulness.rs` + +macro_rules! long_tuple_arg { + ([$($t:tt)*]#$($h:tt)*) => { + long_tuple_arg!{[$($t)*$($t)*]$($h)*} + }; + ([$([$t:tt $y:tt])*]) => { + pub fn _f(($($t,)*): ($($y,)*)) {} + } +} + +long_tuple_arg!{[[_ u8]]########## ###} + +fn main() {} diff --git a/tests/ui/pattern/usefulness/match-arm-statics-2.rs b/tests/ui/pattern/usefulness/match-arm-statics-2.rs new file mode 100644 index 000000000..3c9c16561 --- /dev/null +++ b/tests/ui/pattern/usefulness/match-arm-statics-2.rs @@ -0,0 +1,62 @@ +use self::Direction::{North, East, South, West}; + +#[derive(PartialEq, Eq)] +struct NewBool(bool); + +#[derive(PartialEq, Eq)] +enum Direction { + North, + East, + South, + West +} + +const TRUE_TRUE: (bool, bool) = (true, true); + +fn nonexhaustive_1() { + match (true, false) { + //~^ ERROR non-exhaustive patterns: `(true, false)` not covered + TRUE_TRUE => (), + (false, false) => (), + (false, true) => () + } +} + +const NONE: Option<Direction> = None; +const EAST: Direction = East; + +fn nonexhaustive_2() { + match Some(Some(North)) { + //~^ ERROR non-exhaustive patterns: `Some(Some(Direction::West))` not covered + Some(NONE) => (), + Some(Some(North)) => (), + Some(Some(EAST)) => (), + Some(Some(South)) => (), + None => () + } +} + +const NEW_FALSE: NewBool = NewBool(false); +struct Foo { + bar: Option<Direction>, + baz: NewBool +} + +const STATIC_FOO: Foo = Foo { bar: None, baz: NEW_FALSE }; + +fn nonexhaustive_3() { + match (Foo { bar: Some(North), baz: NewBool(true) }) { + //~^ ERROR non-exhaustive patterns: `Foo { bar: Some(Direction::North), baz: NewBool(true) }` + Foo { bar: None, baz: NewBool(true) } => (), + Foo { bar: _, baz: NEW_FALSE } => (), + Foo { bar: Some(West), baz: NewBool(true) } => (), + Foo { bar: Some(South), .. } => (), + Foo { bar: Some(EAST), .. } => () + } +} + +fn main() { + nonexhaustive_1(); + nonexhaustive_2(); + nonexhaustive_3(); +} diff --git a/tests/ui/pattern/usefulness/match-arm-statics-2.stderr b/tests/ui/pattern/usefulness/match-arm-statics-2.stderr new file mode 100644 index 000000000..e4dd35a59 --- /dev/null +++ b/tests/ui/pattern/usefulness/match-arm-statics-2.stderr @@ -0,0 +1,54 @@ +error[E0004]: non-exhaustive patterns: `(true, false)` not covered + --> $DIR/match-arm-statics-2.rs:17:11 + | +LL | match (true, false) { + | ^^^^^^^^^^^^^ pattern `(true, false)` not covered + | + = note: the matched value is of type `(bool, bool)` +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 ~ (false, true) => (), +LL + (true, false) => todo!() + | + +error[E0004]: non-exhaustive patterns: `Some(Some(Direction::West))` not covered + --> $DIR/match-arm-statics-2.rs:29:11 + | +LL | match Some(Some(North)) { + | ^^^^^^^^^^^^^^^^^ pattern `Some(Some(Direction::West))` not covered + | +note: `Option<Option<Direction>>` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + | + = note: not covered + = note: the matched value is of type `Option<Option<Direction>>` +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 ~ None => (), +LL + Some(Some(Direction::West)) => todo!() + | + +error[E0004]: non-exhaustive patterns: `Foo { bar: Some(Direction::North), baz: NewBool(true) }` not covered + --> $DIR/match-arm-statics-2.rs:48:11 + | +LL | match (Foo { bar: Some(North), baz: NewBool(true) }) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo { bar: Some(Direction::North), baz: NewBool(true) }` not covered + | +note: `Foo` defined here + --> $DIR/match-arm-statics-2.rs:40:8 + | +LL | struct Foo { + | ^^^ + = note: the matched value is of type `Foo` +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 ~ Foo { bar: Some(EAST), .. } => (), +LL + Foo { bar: Some(Direction::North), baz: NewBool(true) } => todo!() + | + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/match-arm-statics.rs b/tests/ui/pattern/usefulness/match-arm-statics.rs new file mode 100644 index 000000000..91db76ebb --- /dev/null +++ b/tests/ui/pattern/usefulness/match-arm-statics.rs @@ -0,0 +1,69 @@ +#![allow(dead_code)] +#![deny(unreachable_patterns)] + +use self::Direction::{North, East, South, West}; + +#[derive(PartialEq, Eq)] +struct NewBool(bool); + +#[derive(PartialEq, Eq)] +enum Direction { + North, + East, + South, + West +} + +const TRUE_TRUE: (bool, bool) = (true, true); + +fn unreachable_1() { + match (true, false) { + TRUE_TRUE => (), + (false, false) => (), + (false, true) => (), + (true, false) => (), + (true, true) => () + //~^ ERROR unreachable pattern + } +} + +const NONE: Option<Direction> = None; +const EAST: Direction = East; + +fn unreachable_2() { + match Some(Some(North)) { + Some(NONE) => (), + Some(Some(North)) => (), + Some(Some(EAST)) => (), + Some(Some(South)) => (), + Some(Some(West)) => (), + Some(Some(East)) => (), + //~^ ERROR unreachable pattern + None => () + } +} + +const NEW_FALSE: NewBool = NewBool(false); +struct Foo { + bar: Option<Direction>, + baz: NewBool +} + +fn unreachable_3() { + match (Foo { bar: Some(EAST), baz: NewBool(true) }) { + Foo { bar: None, baz: NewBool(true) } => (), + Foo { bar: _, baz: NEW_FALSE } => (), + Foo { bar: Some(West), baz: NewBool(true) } => (), + Foo { bar: Some(South), .. } => (), + Foo { bar: Some(EAST), .. } => (), + Foo { bar: Some(North), baz: NewBool(true) } => (), + Foo { bar: Some(EAST), baz: NewBool(false) } => () + //~^ ERROR unreachable pattern + } +} + +fn main() { + unreachable_1(); + unreachable_2(); + unreachable_3(); +} diff --git a/tests/ui/pattern/usefulness/match-arm-statics.stderr b/tests/ui/pattern/usefulness/match-arm-statics.stderr new file mode 100644 index 000000000..a5dffebf6 --- /dev/null +++ b/tests/ui/pattern/usefulness/match-arm-statics.stderr @@ -0,0 +1,26 @@ +error: unreachable pattern + --> $DIR/match-arm-statics.rs:25:9 + | +LL | (true, true) => () + | ^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/match-arm-statics.rs:2:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/match-arm-statics.rs:40:9 + | +LL | Some(Some(East)) => (), + | ^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/match-arm-statics.rs:60:9 + | +LL | Foo { bar: Some(EAST), baz: NewBool(false) } => () + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/pattern/usefulness/match-byte-array-patterns-2.rs b/tests/ui/pattern/usefulness/match-byte-array-patterns-2.rs new file mode 100644 index 000000000..33468d03f --- /dev/null +++ b/tests/ui/pattern/usefulness/match-byte-array-patterns-2.rs @@ -0,0 +1,13 @@ +fn main() { + let buf = &[0, 1, 2, 3]; + + match buf { //~ ERROR non-exhaustive + b"AAAA" => {} + } + + let buf: &[u8] = buf; + + match buf { //~ ERROR non-exhaustive + b"AAAA" => {} + } +} diff --git a/tests/ui/pattern/usefulness/match-byte-array-patterns-2.stderr b/tests/ui/pattern/usefulness/match-byte-array-patterns-2.stderr new file mode 100644 index 000000000..a90f32f7a --- /dev/null +++ b/tests/ui/pattern/usefulness/match-byte-array-patterns-2.stderr @@ -0,0 +1,29 @@ +error[E0004]: non-exhaustive patterns: `&[0_u8..=64_u8, _, _, _]` and `&[66_u8..=u8::MAX, _, _, _]` not covered + --> $DIR/match-byte-array-patterns-2.rs:4:11 + | +LL | match buf { + | ^^^ patterns `&[0_u8..=64_u8, _, _, _]` and `&[66_u8..=u8::MAX, _, _, _]` not covered + | + = note: the matched value is of type `&[u8; 4]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ b"AAAA" => {} +LL + &[0_u8..=64_u8, _, _, _] | &[66_u8..=u8::MAX, _, _, _] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[]`, `&[_]`, `&[_, _]` and 2 more not covered + --> $DIR/match-byte-array-patterns-2.rs:10:11 + | +LL | match buf { + | ^^^ patterns `&[]`, `&[_]`, `&[_, _]` and 2 more not covered + | + = note: the matched value is of type `&[u8]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms + | +LL ~ b"AAAA" => {} +LL + _ => todo!() + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/match-byte-array-patterns.rs b/tests/ui/pattern/usefulness/match-byte-array-patterns.rs new file mode 100644 index 000000000..9b6c8bd55 --- /dev/null +++ b/tests/ui/pattern/usefulness/match-byte-array-patterns.rs @@ -0,0 +1,55 @@ +#![deny(unreachable_patterns)] + +fn main() { + let buf = &[0, 1, 2, 3]; + + match buf { + b"AAAA" => {}, + &[0x41, 0x41, 0x41, 0x41] => {} //~ ERROR unreachable pattern + _ => {} + } + + match buf { + &[0x41, 0x41, 0x41, 0x41] => {} + b"AAAA" => {}, //~ ERROR unreachable pattern + _ => {} + } + + match buf { + &[_, 0x41, 0x41, 0x41] => {}, + b"AAAA" => {}, //~ ERROR unreachable pattern + _ => {} + } + + match buf { + &[0x41, .., 0x41] => {} + b"AAAA" => {}, //~ ERROR unreachable pattern + _ => {} + } + + let buf: &[u8] = buf; + + match buf { + b"AAAA" => {}, + &[0x41, 0x41, 0x41, 0x41] => {} //~ ERROR unreachable pattern + _ => {} + } + + match buf { + &[0x41, 0x41, 0x41, 0x41] => {} + b"AAAA" => {}, //~ ERROR unreachable pattern + _ => {} + } + + match buf { + &[_, 0x41, 0x41, 0x41] => {}, + b"AAAA" => {}, //~ ERROR unreachable pattern + _ => {} + } + + match buf { + &[0x41, .., 0x41] => {} + b"AAAA" => {}, //~ ERROR unreachable pattern + _ => {} + } +} diff --git a/tests/ui/pattern/usefulness/match-byte-array-patterns.stderr b/tests/ui/pattern/usefulness/match-byte-array-patterns.stderr new file mode 100644 index 000000000..0c582be8d --- /dev/null +++ b/tests/ui/pattern/usefulness/match-byte-array-patterns.stderr @@ -0,0 +1,56 @@ +error: unreachable pattern + --> $DIR/match-byte-array-patterns.rs:8:9 + | +LL | &[0x41, 0x41, 0x41, 0x41] => {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/match-byte-array-patterns.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/match-byte-array-patterns.rs:14:9 + | +LL | b"AAAA" => {}, + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/match-byte-array-patterns.rs:20:9 + | +LL | b"AAAA" => {}, + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/match-byte-array-patterns.rs:26:9 + | +LL | b"AAAA" => {}, + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/match-byte-array-patterns.rs:34:9 + | +LL | &[0x41, 0x41, 0x41, 0x41] => {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/match-byte-array-patterns.rs:40:9 + | +LL | b"AAAA" => {}, + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/match-byte-array-patterns.rs:46:9 + | +LL | b"AAAA" => {}, + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/match-byte-array-patterns.rs:52:9 + | +LL | b"AAAA" => {}, + | ^^^^^^^ + +error: aborting due to 8 previous errors + diff --git a/tests/ui/pattern/usefulness/match-non-exhaustive.rs b/tests/ui/pattern/usefulness/match-non-exhaustive.rs new file mode 100644 index 000000000..3b210a115 --- /dev/null +++ b/tests/ui/pattern/usefulness/match-non-exhaustive.rs @@ -0,0 +1,4 @@ +fn main() { + match 0 { 1 => () } //~ ERROR non-exhaustive patterns + match 0 { 0 if false => () } //~ ERROR non-exhaustive patterns +} diff --git a/tests/ui/pattern/usefulness/match-non-exhaustive.stderr b/tests/ui/pattern/usefulness/match-non-exhaustive.stderr new file mode 100644 index 000000000..08dde523a --- /dev/null +++ b/tests/ui/pattern/usefulness/match-non-exhaustive.stderr @@ -0,0 +1,27 @@ +error[E0004]: non-exhaustive patterns: `i32::MIN..=0_i32` and `2_i32..=i32::MAX` not covered + --> $DIR/match-non-exhaustive.rs:2:11 + | +LL | match 0 { 1 => () } + | ^ patterns `i32::MIN..=0_i32` and `2_i32..=i32::MAX` not covered + | + = note: the matched value is of type `i32` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL | match 0 { 1 => (), i32::MIN..=0_i32 | 2_i32..=i32::MAX => todo!() } + | ++++++++++++++++++++++++++++++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/match-non-exhaustive.rs:3:11 + | +LL | match 0 { 0 if false => () } + | ^ pattern `_` not covered + | + = note: the matched value is of type `i32` +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 0 { 0 if false => (), _ => todo!() } + | ++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/match-privately-empty.rs b/tests/ui/pattern/usefulness/match-privately-empty.rs new file mode 100644 index 000000000..315eb03d1 --- /dev/null +++ b/tests/ui/pattern/usefulness/match-privately-empty.rs @@ -0,0 +1,21 @@ +#![feature(never_type)] +#![feature(exhaustive_patterns)] + +mod private { + pub struct Private { + _bot: !, + pub misc: bool, + } + pub const DATA: Option<Private> = None; +} + +fn main() { + match private::DATA { + //~^ ERROR non-exhaustive patterns: `Some(Private { misc: true, .. })` not covered + None => {} + Some(private::Private { + misc: false, + .. + }) => {} + } +} diff --git a/tests/ui/pattern/usefulness/match-privately-empty.stderr b/tests/ui/pattern/usefulness/match-privately-empty.stderr new file mode 100644 index 000000000..86f75d15c --- /dev/null +++ b/tests/ui/pattern/usefulness/match-privately-empty.stderr @@ -0,0 +1,21 @@ +error[E0004]: non-exhaustive patterns: `Some(Private { misc: true, .. })` not covered + --> $DIR/match-privately-empty.rs:13:11 + | +LL | match private::DATA { + | ^^^^^^^^^^^^^ pattern `Some(Private { misc: true, .. })` not covered + | +note: `Option<Private>` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option<Private>` +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 ~ }) => {} +LL + Some(Private { misc: true, .. }) => todo!() + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/match-ref-ice.rs b/tests/ui/pattern/usefulness/match-ref-ice.rs new file mode 100644 index 000000000..dee110f96 --- /dev/null +++ b/tests/ui/pattern/usefulness/match-ref-ice.rs @@ -0,0 +1,16 @@ +#![deny(unreachable_patterns)] + +// The arity of `ref x` is always 1. If the pattern is compared to some non-structural type whose +// arity is always 0, an ICE occurs. +// +// Related issue: #23009 + +fn main() { + let homura = [1, 2, 3]; + + match homura { + [1, ref _madoka, 3] => (), + [1, 2, 3] => (), //~ ERROR unreachable pattern + [_, _, _] => (), + } +} diff --git a/tests/ui/pattern/usefulness/match-ref-ice.stderr b/tests/ui/pattern/usefulness/match-ref-ice.stderr new file mode 100644 index 000000000..fad0940ba --- /dev/null +++ b/tests/ui/pattern/usefulness/match-ref-ice.stderr @@ -0,0 +1,14 @@ +error: unreachable pattern + --> $DIR/match-ref-ice.rs:13:9 + | +LL | [1, 2, 3] => (), + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/match-ref-ice.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/pattern/usefulness/match-slice-patterns.rs b/tests/ui/pattern/usefulness/match-slice-patterns.rs new file mode 100644 index 000000000..92d74b8c2 --- /dev/null +++ b/tests/ui/pattern/usefulness/match-slice-patterns.rs @@ -0,0 +1,12 @@ +fn check(list: &[Option<()>]) { + match list { + //~^ ERROR `&[_, Some(_), .., None, _]` not covered + &[] => {}, + &[_] => {}, + &[_, _] => {}, + &[_, None, ..] => {}, + &[.., Some(_), _] => {}, + } +} + +fn main() {} diff --git a/tests/ui/pattern/usefulness/match-slice-patterns.stderr b/tests/ui/pattern/usefulness/match-slice-patterns.stderr new file mode 100644 index 000000000..961dd5901 --- /dev/null +++ b/tests/ui/pattern/usefulness/match-slice-patterns.stderr @@ -0,0 +1,16 @@ +error[E0004]: non-exhaustive patterns: `&[_, Some(_), .., None, _]` not covered + --> $DIR/match-slice-patterns.rs:2:11 + | +LL | match list { + | ^^^^ pattern `&[_, Some(_), .., None, _]` not covered + | + = note: the matched value is of type `&[Option<()>]` +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 ~ &[.., Some(_), _] => {} +LL ~ &[_, Some(_), .., None, _] => todo!(), + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/match-vec-fixed.rs b/tests/ui/pattern/usefulness/match-vec-fixed.rs new file mode 100644 index 000000000..e611779de --- /dev/null +++ b/tests/ui/pattern/usefulness/match-vec-fixed.rs @@ -0,0 +1,18 @@ +#![deny(unreachable_patterns)] + +fn a() { + let v = [1, 2, 3]; + match v { + [_, _, _] => {} + [_, _, _] => {} //~ ERROR unreachable pattern + } + match v { + [_, 1, _] => {} + [_, 1, _] => {} //~ ERROR unreachable pattern + _ => {} + } +} + +fn main() { + a(); +} diff --git a/tests/ui/pattern/usefulness/match-vec-fixed.stderr b/tests/ui/pattern/usefulness/match-vec-fixed.stderr new file mode 100644 index 000000000..e388a06cb --- /dev/null +++ b/tests/ui/pattern/usefulness/match-vec-fixed.stderr @@ -0,0 +1,20 @@ +error: unreachable pattern + --> $DIR/match-vec-fixed.rs:7:9 + | +LL | [_, _, _] => {} + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/match-vec-fixed.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/match-vec-fixed.rs:11:9 + | +LL | [_, 1, _] => {} + | ^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/pattern/usefulness/match-vec-unreachable.rs b/tests/ui/pattern/usefulness/match-vec-unreachable.rs new file mode 100644 index 000000000..3342389be --- /dev/null +++ b/tests/ui/pattern/usefulness/match-vec-unreachable.rs @@ -0,0 +1,29 @@ +#![deny(unreachable_patterns)] + +fn main() { + let x: Vec<(isize, isize)> = Vec::new(); + let x: &[(isize, isize)] = &x; + match *x { + [a, (2, 3), _] => (), + [(1, 2), (2, 3), b] => (), //~ ERROR unreachable pattern + _ => () + } + + let x: Vec<String> = vec!["foo".to_string(), + "bar".to_string(), + "baz".to_string()]; + let x: &[String] = &x; + match *x { + [ref a, _, _, ..] => { println!("{}", a); } + [_, _, _, _, _] => { } //~ ERROR unreachable pattern + _ => { } + } + + let x: Vec<char> = vec!['a', 'b', 'c']; + let x: &[char] = &x; + match *x { + ['a', 'b', 'c', ref _tail @ ..] => {} + ['a', 'b', 'c'] => {} //~ ERROR unreachable pattern + _ => {} + } +} diff --git a/tests/ui/pattern/usefulness/match-vec-unreachable.stderr b/tests/ui/pattern/usefulness/match-vec-unreachable.stderr new file mode 100644 index 000000000..672fd92fb --- /dev/null +++ b/tests/ui/pattern/usefulness/match-vec-unreachable.stderr @@ -0,0 +1,26 @@ +error: unreachable pattern + --> $DIR/match-vec-unreachable.rs:8:9 + | +LL | [(1, 2), (2, 3), b] => (), + | ^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/match-vec-unreachable.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/match-vec-unreachable.rs:18:9 + | +LL | [_, _, _, _, _] => { } + | ^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/match-vec-unreachable.rs:26:9 + | +LL | ['a', 'b', 'c'] => {} + | ^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/pattern/usefulness/nested-exhaustive-match.rs b/tests/ui/pattern/usefulness/nested-exhaustive-match.rs new file mode 100644 index 000000000..8b2294f84 --- /dev/null +++ b/tests/ui/pattern/usefulness/nested-exhaustive-match.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +struct Foo { foo: bool, bar: Option<isize>, baz: isize } + +pub fn main() { + match (Foo{foo: true, bar: Some(10), baz: 20}) { + Foo{foo: true, bar: Some(_), ..} => {} + Foo{foo: false, bar: None, ..} => {} + Foo{foo: true, bar: None, ..} => {} + Foo{foo: false, bar: Some(_), ..} => {} + } +} diff --git a/tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs new file mode 100644 index 000000000..5145f7690 --- /dev/null +++ b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs @@ -0,0 +1,107 @@ +// Test the "defined here" and "not covered" diagnostic hints. +// We also make sure that references are peeled off from the scrutinee type +// so that the diagnostics work better with default binding modes. + +#[derive(Clone)] +enum E { + //~^ NOTE + //~| NOTE + //~| NOTE + //~| NOTE + //~| NOTE + //~| NOTE + A, + B, + //~^ NOTE `E` defined here + //~| NOTE `E` defined here + //~| NOTE `E` defined here + //~| NOTE not covered + //~| NOTE not covered + //~| NOTE not covered + //~| NOTE not covered + //~| NOTE not covered + //~| NOTE not covered + C + //~^ not covered + //~| not covered + //~| not covered + //~| not covered + //~| not covered + //~| not covered +} + +fn by_val(e: E) { + let e1 = e.clone(); + match e1 { //~ ERROR non-exhaustive patterns: `E::B` and `E::C` not covered + //~^ NOTE patterns `E::B` and `E::C` not covered + //~| NOTE the matched value is of type `E` + E::A => {} + } + + let E::A = e; + //~^ ERROR refutable pattern in local binding + //~| patterns `E::B` and `E::C` not covered + //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with + //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + //~| NOTE the matched value is of type `E` +} + +fn by_ref_once(e: &E) { + match e { + //~^ ERROR non-exhaustive patterns + //~| patterns `&E::B` and `&E::C` not covered + //~| NOTE the matched value is of type `&E` + E::A => {} + } + + let E::A = e; + //~^ ERROR refutable pattern in local binding + //~| patterns `&E::B` and `&E::C` not covered + //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with + //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + //~| NOTE the matched value is of type `&E` +} + +fn by_ref_thrice(e: & &mut &E) { + match e { + //~^ ERROR non-exhaustive patterns + //~| patterns `&&mut &E::B` and `&&mut &E::C` not covered + //~| NOTE the matched value is of type `&&mut &E` + E::A => {} + } + + let E::A = e; + //~^ ERROR refutable pattern in local binding + //~| patterns `&&mut &E::B` and `&&mut &E::C` not covered + //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with + //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + //~| NOTE the matched value is of type `&&mut &E` +} + +enum Opt { + //~^ NOTE + //~| NOTE + Some(u8), + None, + //~^ NOTE `Opt` defined here + //~| NOTE not covered + //~| NOTE not covered +} + +fn ref_pat(e: Opt) { + match e { + //~^ ERROR non-exhaustive patterns + //~| pattern `Opt::None` not covered + //~| NOTE the matched value is of type `Opt` + Opt::Some(ref _x) => {} + } + + let Opt::Some(ref _x) = e; + //~^ ERROR refutable pattern in local binding + //~| NOTE the matched value is of type `Opt` + //~| NOTE pattern `Opt::None` not covered + //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with + //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +} + +fn main() {} diff --git a/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr new file mode 100644 index 000000000..769d4070f --- /dev/null +++ b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr @@ -0,0 +1,194 @@ +error[E0004]: non-exhaustive patterns: `E::B` and `E::C` not covered + --> $DIR/non-exhaustive-defined-here.rs:35:11 + | +LL | match e1 { + | ^^ patterns `E::B` and `E::C` not covered + | +note: `E` defined here + --> $DIR/non-exhaustive-defined-here.rs:14:5 + | +LL | enum E { + | - +... +LL | B, + | ^ not covered +... +LL | C + | ^ not covered + = note: the matched value is of type `E` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ E::A => {} +LL + E::B | E::C => todo!() + | + +error[E0005]: refutable pattern in local binding + --> $DIR/non-exhaustive-defined-here.rs:41:9 + | +LL | let E::A = e; + | ^^^^ patterns `E::B` and `E::C` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +note: `E` defined here + --> $DIR/non-exhaustive-defined-here.rs:6:6 + | +LL | enum E { + | ^ +... +LL | B, + | - not covered +... +LL | C + | - not covered + = note: the matched value is of type `E` +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | if let E::A = e { todo!() } + | ++ ~~~~~~~~~~~ + +error[E0004]: non-exhaustive patterns: `&E::B` and `&E::C` not covered + --> $DIR/non-exhaustive-defined-here.rs:50:11 + | +LL | match e { + | ^ patterns `&E::B` and `&E::C` not covered + | +note: `E` defined here + --> $DIR/non-exhaustive-defined-here.rs:14:5 + | +LL | enum E { + | - +... +LL | B, + | ^ not covered +... +LL | C + | ^ not covered + = note: the matched value is of type `&E` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ E::A => {} +LL + &E::B | &E::C => todo!() + | + +error[E0005]: refutable pattern in local binding + --> $DIR/non-exhaustive-defined-here.rs:57:9 + | +LL | let E::A = e; + | ^^^^ patterns `&E::B` and `&E::C` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +note: `E` defined here + --> $DIR/non-exhaustive-defined-here.rs:6:6 + | +LL | enum E { + | ^ +... +LL | B, + | - not covered +... +LL | C + | - not covered + = note: the matched value is of type `&E` +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | if let E::A = e { todo!() } + | ++ ~~~~~~~~~~~ + +error[E0004]: non-exhaustive patterns: `&&mut &E::B` and `&&mut &E::C` not covered + --> $DIR/non-exhaustive-defined-here.rs:66:11 + | +LL | match e { + | ^ patterns `&&mut &E::B` and `&&mut &E::C` not covered + | +note: `E` defined here + --> $DIR/non-exhaustive-defined-here.rs:14:5 + | +LL | enum E { + | - +... +LL | B, + | ^ not covered +... +LL | C + | ^ not covered + = note: the matched value is of type `&&mut &E` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ E::A => {} +LL + &&mut &E::B | &&mut &E::C => todo!() + | + +error[E0005]: refutable pattern in local binding + --> $DIR/non-exhaustive-defined-here.rs:73:9 + | +LL | let E::A = e; + | ^^^^ patterns `&&mut &E::B` and `&&mut &E::C` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +note: `E` defined here + --> $DIR/non-exhaustive-defined-here.rs:6:6 + | +LL | enum E { + | ^ +... +LL | B, + | - not covered +... +LL | C + | - not covered + = note: the matched value is of type `&&mut &E` +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | if let E::A = e { todo!() } + | ++ ~~~~~~~~~~~ + +error[E0004]: non-exhaustive patterns: `Opt::None` not covered + --> $DIR/non-exhaustive-defined-here.rs:92:11 + | +LL | match e { + | ^ pattern `Opt::None` not covered + | +note: `Opt` defined here + --> $DIR/non-exhaustive-defined-here.rs:85:5 + | +LL | enum Opt { + | --- +... +LL | None, + | ^^^^ not covered + = note: the matched value is of type `Opt` +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 ~ Opt::Some(ref _x) => {} +LL + Opt::None => todo!() + | + +error[E0005]: refutable pattern in local binding + --> $DIR/non-exhaustive-defined-here.rs:99:9 + | +LL | let Opt::Some(ref _x) = e; + | ^^^^^^^^^^^^^^^^^ pattern `Opt::None` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +note: `Opt` defined here + --> $DIR/non-exhaustive-defined-here.rs:81:6 + | +LL | enum Opt { + | ^^^ +... +LL | None, + | ---- not covered + = note: the matched value is of type `Opt` +help: you might want to use `let else` to handle the variant that isn't matched + | +LL | let Opt::Some(ref _x) = e else { todo!() }; + | ++++++++++++++++ + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0004, E0005. +For more information about an error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/non-exhaustive-match-nested.rs b/tests/ui/pattern/usefulness/non-exhaustive-match-nested.rs new file mode 100644 index 000000000..69c3c7658 --- /dev/null +++ b/tests/ui/pattern/usefulness/non-exhaustive-match-nested.rs @@ -0,0 +1,19 @@ +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 + (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)", + (None, Ok(&[_, _, ..])) => "None, Ok(at least two elements)" + } +} + +fn main() { + let x = T::A(U::C); + match x { //~ ERROR non-exhaustive patterns: `T::A(U::C)` not covered + T::A(U::D) => { panic!("hello"); } + T::B => { panic!("goodbye"); } + } +} diff --git a/tests/ui/pattern/usefulness/non-exhaustive-match-nested.stderr b/tests/ui/pattern/usefulness/non-exhaustive-match-nested.stderr new file mode 100644 index 000000000..44f327421 --- /dev/null +++ b/tests/ui/pattern/usefulness/non-exhaustive-match-nested.stderr @@ -0,0 +1,34 @@ +error[E0004]: non-exhaustive patterns: `(Some(&[]), Err(_))` not covered + --> $DIR/non-exhaustive-match-nested.rs:5:11 + | +LL | match (l1, l2) { + | ^^^^^^^^ pattern `(Some(&[]), Err(_))` not covered + | + = note: the matched value is of type `(Option<&[T]>, Result<&[T], ()>)` +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 ~ (None, Ok(&[_, _, ..])) => "None, Ok(at least two elements)", +LL + (Some(&[]), Err(_)) => todo!() + | + +error[E0004]: non-exhaustive patterns: `T::A(U::C)` not covered + --> $DIR/non-exhaustive-match-nested.rs:15:11 + | +LL | match x { + | ^ pattern `T::A(U::C)` not covered + | +note: `T` defined here + --> $DIR/non-exhaustive-match-nested.rs:1:10 + | +LL | enum T { A(U), B } + | - ^ not covered + = note: the matched value is of type `T` +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 ~ T::B => { panic!("goodbye"); } +LL + T::A(U::C) => todo!() + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/non-exhaustive-match.rs b/tests/ui/pattern/usefulness/non-exhaustive-match.rs new file mode 100644 index 000000000..1cb58b8ce --- /dev/null +++ b/tests/ui/pattern/usefulness/non-exhaustive-match.rs @@ -0,0 +1,63 @@ +#![allow(illegal_floating_point_literal_pattern)] + +enum T { A, B } + +fn main() { + let x = T::A; + match x { T::B => { } } //~ ERROR non-exhaustive patterns: `T::A` not covered + match true { //~ ERROR non-exhaustive patterns: `false` not covered + true => {} + } + match Some(10) { //~ ERROR non-exhaustive patterns: `Some(_)` not covered + None => {} + } + match (2, 3, 4) { //~ ERROR non-exhaustive patterns: `(_, _, i32::MIN..=3_i32)` + // and `(_, _, 5_i32..=i32::MAX)` not covered + (_, _, 4) => {} + } + match (T::A, T::A) { //~ ERROR non-exhaustive patterns: `(T::A, T::A)` and `(T::B, T::B)` not covered + (T::A, T::B) => {} + (T::B, T::A) => {} + } + match T::A { //~ ERROR non-exhaustive patterns: `T::B` not covered + T::A => {} + } + // This is exhaustive, though the algorithm got it wrong at one point + match (T::A, T::B) { + (T::A, _) => {} + (_, T::A) => {} + (T::B, T::B) => {} + } + let vec = vec![Some(42), None, Some(21)]; + let vec: &[Option<isize>] = &vec; + match *vec { //~ ERROR non-exhaustive patterns: `[]` not covered + [Some(..), None, ref tail @ ..] => {} + [Some(..), Some(..), ref tail @ ..] => {} + [None] => {} + } + let vec = vec![1]; + let vec: &[isize] = &vec; + match *vec { + [_, ref tail @ ..] => (), + [] => () + } + let vec = vec![0.5f32]; + let vec: &[f32] = &vec; + match *vec { //~ ERROR non-exhaustive patterns: `[_, _, _, _, ..]` not covered + [0.1, 0.2, 0.3] => (), + [0.1, 0.2] => (), + [0.1] => (), + [] => () + } + let vec = vec![Some(42), None, Some(21)]; + let vec: &[Option<isize>] = &vec; + match *vec { + [Some(..), None, ref tail @ ..] => {} + [Some(..), Some(..), ref tail @ ..] => {} + [None, None, ref tail @ ..] => {} + [None, Some(..), ref tail @ ..] => {} + [Some(_)] => {} + [None] => {} + [] => {} + } +} diff --git a/tests/ui/pattern/usefulness/non-exhaustive-match.stderr b/tests/ui/pattern/usefulness/non-exhaustive-match.stderr new file mode 100644 index 000000000..e2260f50b --- /dev/null +++ b/tests/ui/pattern/usefulness/non-exhaustive-match.stderr @@ -0,0 +1,121 @@ +error[E0004]: non-exhaustive patterns: `T::A` not covered + --> $DIR/non-exhaustive-match.rs:7:11 + | +LL | match x { T::B => { } } + | ^ pattern `T::A` not covered + | +note: `T` defined here + --> $DIR/non-exhaustive-match.rs:3:10 + | +LL | enum T { A, B } + | - ^ not covered + = note: the matched value is of type `T` +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 x { T::B => { }, T::A => todo!() } + | +++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `false` not covered + --> $DIR/non-exhaustive-match.rs:8:11 + | +LL | match true { + | ^^^^ pattern `false` not covered + | + = note: the matched value is of type `bool` +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 ~ true => {} +LL + false => todo!() + | + +error[E0004]: non-exhaustive patterns: `Some(_)` not covered + --> $DIR/non-exhaustive-match.rs:11:11 + | +LL | match Some(10) { + | ^^^^^^^^ pattern `Some(_)` not covered + | +note: `Option<i32>` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option<i32>` +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 ~ None => {} +LL + Some(_) => todo!() + | + +error[E0004]: non-exhaustive patterns: `(_, _, i32::MIN..=3_i32)` and `(_, _, 5_i32..=i32::MAX)` not covered + --> $DIR/non-exhaustive-match.rs:14:11 + | +LL | match (2, 3, 4) { + | ^^^^^^^^^ patterns `(_, _, i32::MIN..=3_i32)` and `(_, _, 5_i32..=i32::MAX)` not covered + | + = note: the matched value is of type `(i32, i32, i32)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ (_, _, 4) => {} +LL + (_, _, i32::MIN..=3_i32) | (_, _, 5_i32..=i32::MAX) => todo!() + | + +error[E0004]: non-exhaustive patterns: `(T::A, T::A)` and `(T::B, T::B)` not covered + --> $DIR/non-exhaustive-match.rs:18:11 + | +LL | match (T::A, T::A) { + | ^^^^^^^^^^^^ patterns `(T::A, T::A)` and `(T::B, T::B)` not covered + | + = note: the matched value is of type `(T, T)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ (T::B, T::A) => {} +LL + (T::A, T::A) | (T::B, T::B) => todo!() + | + +error[E0004]: non-exhaustive patterns: `T::B` not covered + --> $DIR/non-exhaustive-match.rs:22:11 + | +LL | match T::A { + | ^^^^ pattern `T::B` not covered + | +note: `T` defined here + --> $DIR/non-exhaustive-match.rs:3:13 + | +LL | enum T { A, B } + | - ^ not covered + = note: the matched value is of type `T` +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 ~ T::A => {} +LL + T::B => todo!() + | + +error[E0004]: non-exhaustive patterns: `[]` not covered + --> $DIR/non-exhaustive-match.rs:33:11 + | +LL | match *vec { + | ^^^^ pattern `[]` not covered + | + = note: the matched value is of type `[Option<isize>]` +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 ~ [None] => {} +LL + [] => todo!() + | + +error[E0004]: non-exhaustive patterns: `[_, _, _, _, ..]` not covered + --> $DIR/non-exhaustive-match.rs:46:11 + | +LL | match *vec { + | ^^^^ pattern `[_, _, _, _, ..]` not covered + | + = note: the matched value is of type `[f32]` +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 ~ [] => (), +LL + [_, _, _, _, ..] => todo!() + | + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs b/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs new file mode 100644 index 000000000..4bd344219 --- /dev/null +++ b/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs @@ -0,0 +1,89 @@ +struct Foo { + first: bool, + second: Option<[usize; 4]> +} + +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 + Foo { first: true, second: None } => (), + Foo { first: true, second: Some(_) } => (), + Foo { first: false, second: None } => (), + Foo { first: false, second: Some([1, 2, 3, 4]) } => () + } +} + +enum Color { + Red, + Green, + CustomRGBA { a: bool, r: u8, g: u8, b: u8 } +} + +fn enum_with_single_missing_variant() { + match Color::Red { + //~^ ERROR non-exhaustive patterns: `Color::Red` not covered + Color::CustomRGBA { .. } => (), + Color::Green => () + } +} + +enum Direction { + North, East, South, West +} + +fn enum_with_multiple_missing_variants() { + match Direction::North { + //~^ ERROR non-exhaustive patterns: `Direction::East`, `Direction::South` and `Direction::West` not covered + Direction::North => () + } +} + +enum ExcessiveEnum { + First, Second, Third, Fourth, Fifth, Sixth, Seventh, Eighth, Ninth, Tenth, Eleventh, Twelfth +} + +fn enum_with_excessive_missing_variants() { + match ExcessiveEnum::First { + //~^ ERROR `ExcessiveEnum::Second`, `ExcessiveEnum::Third`, `ExcessiveEnum::Fourth` and 8 more not covered + + ExcessiveEnum::First => () + } +} + +fn enum_struct_variant() { + match Color::Red { + //~^ ERROR non-exhaustive patterns: `Color::CustomRGBA { a: true, .. }` not covered + Color::Red => (), + Color::Green => (), + Color::CustomRGBA { a: false, r: _, g: _, b: 0 } => (), + Color::CustomRGBA { a: false, r: _, g: _, b: _ } => () + } +} + +enum Enum { + First, + Second(bool) +} + +fn vectors_with_nested_enums() { + let x: &'static [Enum] = &[Enum::First, Enum::Second(false)]; + match *x { + //~^ ERROR non-exhaustive patterns: `[Enum::Second(true), Enum::Second(false)]` not covered + [] => (), + [_] => (), + [Enum::First, _] => (), + [Enum::Second(true), Enum::First] => (), + [Enum::Second(true), Enum::Second(true)] => (), + [Enum::Second(false), _] => (), + [_, _, ref tail @ .., _] => () + } +} + +fn missing_nil() { + match ((), false) { + //~^ ERROR non-exhaustive patterns: `((), false)` not covered + ((), true) => () + } +} + +fn main() {} diff --git a/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr b/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr new file mode 100644 index 000000000..b8af566de --- /dev/null +++ b/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr @@ -0,0 +1,129 @@ +error[E0004]: non-exhaustive patterns: `Foo { first: false, second: Some([_, _, _, _]) }` not covered + --> $DIR/non-exhaustive-pattern-witness.rs:7:11 + | +LL | match (Foo { first: true, second: None }) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo { first: false, second: Some([_, _, _, _]) }` not covered + | +note: `Foo` defined here + --> $DIR/non-exhaustive-pattern-witness.rs:1:8 + | +LL | struct Foo { + | ^^^ + = note: the matched value is of type `Foo` +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 ~ Foo { first: false, second: Some([1, 2, 3, 4]) } => (), +LL + Foo { first: false, second: Some([_, _, _, _]) } => todo!() + | + +error[E0004]: non-exhaustive patterns: `Color::Red` not covered + --> $DIR/non-exhaustive-pattern-witness.rs:23:11 + | +LL | match Color::Red { + | ^^^^^^^^^^ pattern `Color::Red` not covered + | +note: `Color` defined here + --> $DIR/non-exhaustive-pattern-witness.rs:17:5 + | +LL | enum Color { + | ----- +LL | Red, + | ^^^ not covered + = note: the matched value is of type `Color` +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 ~ Color::Green => (), +LL + Color::Red => todo!() + | + +error[E0004]: non-exhaustive patterns: `Direction::East`, `Direction::South` and `Direction::West` not covered + --> $DIR/non-exhaustive-pattern-witness.rs:35:11 + | +LL | match Direction::North { + | ^^^^^^^^^^^^^^^^ patterns `Direction::East`, `Direction::South` and `Direction::West` not covered + | +note: `Direction` defined here + --> $DIR/non-exhaustive-pattern-witness.rs:31:12 + | +LL | enum Direction { + | --------- +LL | North, East, South, West + | ^^^^ ^^^^^ ^^^^ not covered + | | | + | | not covered + | not covered + = note: the matched value is of type `Direction` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ Direction::North => (), +LL + Direction::East | Direction::South | Direction::West => todo!() + | + +error[E0004]: non-exhaustive patterns: `ExcessiveEnum::Second`, `ExcessiveEnum::Third`, `ExcessiveEnum::Fourth` and 8 more not covered + --> $DIR/non-exhaustive-pattern-witness.rs:46:11 + | +LL | match ExcessiveEnum::First { + | ^^^^^^^^^^^^^^^^^^^^ patterns `ExcessiveEnum::Second`, `ExcessiveEnum::Third`, `ExcessiveEnum::Fourth` and 8 more not covered + | +note: `ExcessiveEnum` defined here + --> $DIR/non-exhaustive-pattern-witness.rs:41:6 + | +LL | enum ExcessiveEnum { + | ^^^^^^^^^^^^^ + = note: the matched value is of type `ExcessiveEnum` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms + | +LL ~ ExcessiveEnum::First => (), +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `Color::CustomRGBA { a: true, .. }` not covered + --> $DIR/non-exhaustive-pattern-witness.rs:54:11 + | +LL | match Color::Red { + | ^^^^^^^^^^ pattern `Color::CustomRGBA { a: true, .. }` not covered + | +note: `Color` defined here + --> $DIR/non-exhaustive-pattern-witness.rs:19:5 + | +LL | enum Color { + | ----- +... +LL | CustomRGBA { a: bool, r: u8, g: u8, b: u8 } + | ^^^^^^^^^^ not covered + = note: the matched value is of type `Color` +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 ~ Color::CustomRGBA { a: false, r: _, g: _, b: _ } => (), +LL + Color::CustomRGBA { a: true, .. } => todo!() + | + +error[E0004]: non-exhaustive patterns: `[Enum::Second(true), Enum::Second(false)]` not covered + --> $DIR/non-exhaustive-pattern-witness.rs:70:11 + | +LL | match *x { + | ^^ pattern `[Enum::Second(true), Enum::Second(false)]` not covered + | + = note: the matched value is of type `[Enum]` +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 ~ [_, _, ref tail @ .., _] => (), +LL + [Enum::Second(true), Enum::Second(false)] => todo!() + | + +error[E0004]: non-exhaustive patterns: `((), false)` not covered + --> $DIR/non-exhaustive-pattern-witness.rs:83:11 + | +LL | match ((), false) { + | ^^^^^^^^^^^ pattern `((), false)` not covered + | + = note: the matched value is of type `((), bool)` +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 ~ ((), true) => (), +LL + ((), false) => todo!() + | + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/refutable-pattern-errors.rs b/tests/ui/pattern/usefulness/refutable-pattern-errors.rs new file mode 100644 index 000000000..7a3e991d5 --- /dev/null +++ b/tests/ui/pattern/usefulness/refutable-pattern-errors.rs @@ -0,0 +1,9 @@ +fn func((1, (Some(1), 2..=3)): (isize, (Option<isize>, isize))) { } +//~^ 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 + //~| `(i32::MIN..=0_i32, _)` and `(2_i32..=i32::MAX, _)` not covered +} diff --git a/tests/ui/pattern/usefulness/refutable-pattern-errors.stderr b/tests/ui/pattern/usefulness/refutable-pattern-errors.stderr new file mode 100644 index 000000000..c518de477 --- /dev/null +++ b/tests/ui/pattern/usefulness/refutable-pattern-errors.stderr @@ -0,0 +1,25 @@ +error[E0005]: refutable pattern in function argument + --> $DIR/refutable-pattern-errors.rs:1:9 + | +LL | fn func((1, (Some(1), 2..=3)): (isize, (Option<isize>, isize))) { } + | ^^^^^^^^^^^^^^^^^^^^^ pattern `(_, _)` not covered + | + = note: the matched value is of type `(isize, (Option<isize>, isize))` + +error[E0005]: refutable pattern in local binding + --> $DIR/refutable-pattern-errors.rs:6:9 + | +LL | let (1, (Some(1), 2..=3)) = (1, (None, 2)); + | ^^^^^^^^^^^^^^^^^^^^^ patterns `(i32::MIN..=0_i32, _)` and `(2_i32..=i32::MAX, _)` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `(i32, (Option<i32>, i32))` +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | if let (1, (Some(1), 2..=3)) = (1, (None, 2)) { todo!() } + | ++ ~~~~~~~~~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.rs b/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.rs new file mode 100644 index 000000000..17dc38ab2 --- /dev/null +++ b/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.rs @@ -0,0 +1,6 @@ +fn main() { + let f = |3: isize| println!("hello"); + //~^ ERROR refutable pattern in function argument + //~| `_` not covered + f(4); +} diff --git a/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr b/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr new file mode 100644 index 000000000..55f0b2319 --- /dev/null +++ b/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr @@ -0,0 +1,11 @@ +error[E0005]: refutable pattern in function argument + --> $DIR/refutable-pattern-in-fn-arg.rs:2:14 + | +LL | let f = |3: isize| println!("hello"); + | ^ pattern `_` not covered + | + = note: the matched value is of type `isize` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/pattern/usefulness/slice-pattern-const-2.rs b/tests/ui/pattern/usefulness/slice-pattern-const-2.rs new file mode 100644 index 000000000..4bf8d0fd2 --- /dev/null +++ b/tests/ui/pattern/usefulness/slice-pattern-const-2.rs @@ -0,0 +1,31 @@ +#![deny(unreachable_patterns)] + +fn main() { + let s = &[0x00; 4][..]; //Slice of any value + const MAGIC_TEST: &[u32] = &[4, 5, 6, 7]; //Const slice to pattern match with + match s { + MAGIC_TEST => (), + [0x00, 0x00, 0x00, 0x00] => (), + [4, 5, 6, 7] => (), //~ ERROR unreachable pattern + _ => (), + } + match s { + [0x00, 0x00, 0x00, 0x00] => (), + MAGIC_TEST => (), + [4, 5, 6, 7] => (), //~ ERROR unreachable pattern + _ => (), + } + match s { + [0x00, 0x00, 0x00, 0x00] => (), + [4, 5, 6, 7] => (), + MAGIC_TEST => (), //~ ERROR unreachable pattern + _ => (), + } + const FOO: [u32; 1] = [4]; + match [99] { + [0x00] => (), + [4] => (), + FOO => (), //~ ERROR unreachable pattern + _ => (), + } +} diff --git a/tests/ui/pattern/usefulness/slice-pattern-const-2.stderr b/tests/ui/pattern/usefulness/slice-pattern-const-2.stderr new file mode 100644 index 000000000..dcad11a38 --- /dev/null +++ b/tests/ui/pattern/usefulness/slice-pattern-const-2.stderr @@ -0,0 +1,32 @@ +error: unreachable pattern + --> $DIR/slice-pattern-const-2.rs:9:9 + | +LL | [4, 5, 6, 7] => (), + | ^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/slice-pattern-const-2.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const-2.rs:15:9 + | +LL | [4, 5, 6, 7] => (), + | ^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const-2.rs:21:9 + | +LL | MAGIC_TEST => (), + | ^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const-2.rs:28:9 + | +LL | FOO => (), + | ^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/pattern/usefulness/slice-pattern-const-3.rs b/tests/ui/pattern/usefulness/slice-pattern-const-3.rs new file mode 100644 index 000000000..2ca8323f0 --- /dev/null +++ b/tests/ui/pattern/usefulness/slice-pattern-const-3.rs @@ -0,0 +1,31 @@ +#![deny(unreachable_patterns)] + +fn main() { + let s = &["0x00"; 4][..]; //Slice of any value + const MAGIC_TEST: &[&str] = &["4", "5", "6", "7"]; //Const slice to pattern match with + match s { + MAGIC_TEST => (), + ["0x00", "0x00", "0x00", "0x00"] => (), + ["4", "5", "6", "7"] => (), //~ ERROR unreachable pattern + _ => (), + } + match s { + ["0x00", "0x00", "0x00", "0x00"] => (), + MAGIC_TEST => (), + ["4", "5", "6", "7"] => (), //~ ERROR unreachable pattern + _ => (), + } + match s { + ["0x00", "0x00", "0x00", "0x00"] => (), + ["4", "5", "6", "7"] => (), + MAGIC_TEST => (), //~ ERROR unreachable pattern + _ => (), + } + const FOO: [&str; 1] = ["boo"]; + match ["baa"] { + ["0x00"] => (), + ["boo"] => (), + FOO => (), //~ ERROR unreachable pattern + _ => (), + } +} diff --git a/tests/ui/pattern/usefulness/slice-pattern-const-3.stderr b/tests/ui/pattern/usefulness/slice-pattern-const-3.stderr new file mode 100644 index 000000000..b90b3a88a --- /dev/null +++ b/tests/ui/pattern/usefulness/slice-pattern-const-3.stderr @@ -0,0 +1,32 @@ +error: unreachable pattern + --> $DIR/slice-pattern-const-3.rs:9:9 + | +LL | ["4", "5", "6", "7"] => (), + | ^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/slice-pattern-const-3.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const-3.rs:15:9 + | +LL | ["4", "5", "6", "7"] => (), + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const-3.rs:21:9 + | +LL | MAGIC_TEST => (), + | ^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const-3.rs:28:9 + | +LL | FOO => (), + | ^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/pattern/usefulness/slice-pattern-const.rs b/tests/ui/pattern/usefulness/slice-pattern-const.rs new file mode 100644 index 000000000..89195d5b1 --- /dev/null +++ b/tests/ui/pattern/usefulness/slice-pattern-const.rs @@ -0,0 +1,54 @@ +#![deny(unreachable_patterns)] + +fn main() { + let s = &[0x00; 4][..]; //Slice of any value + const MAGIC_TEST: &[u8] = b"TEST"; //Const slice to pattern match with + match s { + MAGIC_TEST => (), + [0x00, 0x00, 0x00, 0x00] => (), + [84, 69, 83, 84] => (), //~ ERROR unreachable pattern + _ => (), + } + match s { + [0x00, 0x00, 0x00, 0x00] => (), + MAGIC_TEST => (), + [84, 69, 83, 84] => (), //~ ERROR unreachable pattern + _ => (), + } + match s { + [0x00, 0x00, 0x00, 0x00] => (), + [84, 69, 83, 84] => (), + MAGIC_TEST => (), //~ ERROR unreachable pattern + _ => (), + } + const FOO: [u8; 1] = [4]; + match [99] { + [0x00] => (), + [4] => (), + FOO => (), //~ ERROR unreachable pattern + _ => (), + } + const BAR: &[u8; 1] = &[4]; + match &[99] { + [0x00] => (), + [4] => (), + BAR => (), //~ ERROR unreachable pattern + b"a" => (), + _ => (), + } + + const BOO: &[u8; 0] = &[]; + match &[] { + [] => (), + BOO => (), //~ ERROR unreachable pattern + b"" => (), //~ ERROR unreachable pattern + _ => (), //~ ERROR unreachable pattern + } + + const CONST1: &[bool; 1] = &[true]; + match &[false] { + CONST1 => {} + [true] => {} //~ ERROR unreachable pattern + [false] => {} + } +} diff --git a/tests/ui/pattern/usefulness/slice-pattern-const.stderr b/tests/ui/pattern/usefulness/slice-pattern-const.stderr new file mode 100644 index 000000000..1fffb9fed --- /dev/null +++ b/tests/ui/pattern/usefulness/slice-pattern-const.stderr @@ -0,0 +1,62 @@ +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:9:9 + | +LL | [84, 69, 83, 84] => (), + | ^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/slice-pattern-const.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:15:9 + | +LL | [84, 69, 83, 84] => (), + | ^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:21:9 + | +LL | MAGIC_TEST => (), + | ^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:28:9 + | +LL | FOO => (), + | ^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:35:9 + | +LL | BAR => (), + | ^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:43:9 + | +LL | BOO => (), + | ^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:44:9 + | +LL | b"" => (), + | ^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:45:9 + | +LL | _ => (), + | ^ + +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:51:9 + | +LL | [true] => {} + | ^^^^^^ + +error: aborting due to 9 previous errors + diff --git a/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs b/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs new file mode 100644 index 000000000..46e0da5be --- /dev/null +++ b/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs @@ -0,0 +1,129 @@ +fn main() { + let s: &[bool] = &[true; 0]; + let s1: &[bool; 1] = &[false; 1]; + let s2: &[bool; 2] = &[false; 2]; + let s3: &[bool; 3] = &[false; 3]; + let s10: &[bool; 10] = &[false; 10]; + + match s2 { + //~^ ERROR `&[false, _]` not covered + [true, .., true] => {} + } + match s3 { + //~^ ERROR `&[false, ..]` not covered + [true, .., true] => {} + } + match s10 { + //~^ ERROR `&[false, ..]` not covered + [true, .., true] => {} + } + + match s1 { + [true, ..] => {} + [.., false] => {} + } + match s2 { + //~^ ERROR `&[false, true]` not covered + [true, ..] => {} + [.., false] => {} + } + match s3 { + //~^ ERROR `&[false, .., true]` not covered + [true, ..] => {} + [.., false] => {} + } + match s { + //~^ ERROR `&[false, .., true]` not covered + [] => {} + [true, ..] => {} + [.., false] => {} + } + + match s { + //~^ ERROR `&[_, ..]` not covered + [] => {} + } + match s { + //~^ ERROR `&[_, _, ..]` not covered + [] => {} + [_] => {} + } + match s { + //~^ ERROR `&[false, ..]` not covered + [] => {} + [true, ..] => {} + } + match s { + //~^ ERROR `&[false, _, ..]` not covered + [] => {} + [_] => {} + [true, ..] => {} + } + match s { + //~^ ERROR `&[_, .., false]` not covered + [] => {} + [_] => {} + [.., true] => {} + } + + match s { + //~^ ERROR `&[_, _, .., true]` not covered + [] => {} + [_] => {} + [_, _] => {} + [.., false] => {} + } + match s { + //~^ ERROR `&[true, _, .., _]` not covered + [] => {} + [_] => {} + [_, _] => {} + [false, .., false] => {} + } + + const CONST: &[bool] = &[true]; + match s { + //~^ ERROR `&[]` and `&[_, _, ..]` not covered + &[true] => {} + } + match s { + //~^ ERROR `&[]` and `&[_, _, ..]` not covered + CONST => {} + } + match s { + //~^ ERROR `&[]` and `&[_, _, ..]` not covered + CONST => {} + &[false] => {} + } + match s { + //~^ ERROR `&[]` and `&[_, _, ..]` not covered + &[false] => {} + CONST => {} + } + match s { + //~^ ERROR `&[_, _, ..]` not covered + &[] => {} + CONST => {} + } + match s { + //~^ ERROR `&[false]` not covered + &[] => {} + CONST => {} + &[_, _, ..] => {} + } + match s { + [] => {} + [false] => {} + CONST => {} + [_, _, ..] => {} + } + const CONST1: &[bool; 1] = &[true]; + match s1 { + //~^ ERROR `&[false]` not covered + CONST1 => {} + } + match s1 { + CONST1 => {} + [false] => {} + } +} diff --git a/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr b/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr new file mode 100644 index 000000000..5d1e170ae --- /dev/null +++ b/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr @@ -0,0 +1,263 @@ +error[E0004]: non-exhaustive patterns: `&[false, _]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:8:11 + | +LL | match s2 { + | ^^ pattern `&[false, _]` not covered + | + = note: the matched value is of type `&[bool; 2]` +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 ~ [true, .., true] => {} +LL + &[false, _] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:12:11 + | +LL | match s3 { + | ^^ pattern `&[false, ..]` not covered + | + = note: the matched value is of type `&[bool; 3]` +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 ~ [true, .., true] => {} +LL + &[false, ..] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:16:11 + | +LL | match s10 { + | ^^^ pattern `&[false, ..]` not covered + | + = note: the matched value is of type `&[bool; 10]` +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 ~ [true, .., true] => {} +LL + &[false, ..] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[false, true]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:25:11 + | +LL | match s2 { + | ^^ pattern `&[false, true]` not covered + | + = note: the matched value is of type `&[bool; 2]` +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 ~ [.., false] => {} +LL + &[false, true] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[false, .., true]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:30:11 + | +LL | match s3 { + | ^^ pattern `&[false, .., true]` not covered + | + = note: the matched value is of type `&[bool; 3]` +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 ~ [.., false] => {} +LL + &[false, .., true] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[false, .., true]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:35:11 + | +LL | match s { + | ^ pattern `&[false, .., true]` not covered + | + = note: the matched value is of type `&[bool]` +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 ~ [.., false] => {} +LL + &[false, .., true] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:42:11 + | +LL | match s { + | ^ pattern `&[_, ..]` not covered + | + = note: the matched value is of type `&[bool]` +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 ~ [] => {} +LL + &[_, ..] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[_, _, ..]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:46:11 + | +LL | match s { + | ^ pattern `&[_, _, ..]` not covered + | + = note: the matched value is of type `&[bool]` +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 ~ [_] => {} +LL + &[_, _, ..] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:51:11 + | +LL | match s { + | ^ pattern `&[false, ..]` not covered + | + = note: the matched value is of type `&[bool]` +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 ~ [true, ..] => {} +LL + &[false, ..] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[false, _, ..]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:56:11 + | +LL | match s { + | ^ pattern `&[false, _, ..]` not covered + | + = note: the matched value is of type `&[bool]` +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 ~ [true, ..] => {} +LL + &[false, _, ..] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[_, .., false]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:62:11 + | +LL | match s { + | ^ pattern `&[_, .., false]` not covered + | + = note: the matched value is of type `&[bool]` +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 ~ [.., true] => {} +LL + &[_, .., false] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[_, _, .., true]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:69:11 + | +LL | match s { + | ^ pattern `&[_, _, .., true]` not covered + | + = note: the matched value is of type `&[bool]` +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 ~ [.., false] => {} +LL + &[_, _, .., true] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[true, _, .., _]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:76:11 + | +LL | match s { + | ^ pattern `&[true, _, .., _]` not covered + | + = note: the matched value is of type `&[bool]` +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 ~ [false, .., false] => {} +LL + &[true, _, .., _] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:85:11 + | +LL | match s { + | ^ patterns `&[]` and `&[_, _, ..]` not covered + | + = note: the matched value is of type `&[bool]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ &[true] => {} +LL + &[] | &[_, _, ..] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:89:11 + | +LL | match s { + | ^ patterns `&[]` and `&[_, _, ..]` not covered + | + = note: the matched value is of type `&[bool]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ CONST => {} +LL + &[] | &[_, _, ..] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:93:11 + | +LL | match s { + | ^ patterns `&[]` and `&[_, _, ..]` not covered + | + = note: the matched value is of type `&[bool]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ &[false] => {} +LL + &[] | &[_, _, ..] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:98:11 + | +LL | match s { + | ^ patterns `&[]` and `&[_, _, ..]` not covered + | + = note: the matched value is of type `&[bool]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ CONST => {} +LL + &[] | &[_, _, ..] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[_, _, ..]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:103:11 + | +LL | match s { + | ^ pattern `&[_, _, ..]` not covered + | + = note: the matched value is of type `&[bool]` +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 ~ CONST => {} +LL + &[_, _, ..] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[false]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:108:11 + | +LL | match s { + | ^ pattern `&[false]` not covered + | + = note: the matched value is of type `&[bool]` +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 ~ &[_, _, ..] => {} +LL + &[false] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[false]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:121:11 + | +LL | match s1 { + | ^^ pattern `&[false]` not covered + | + = note: the matched value is of type `&[bool; 1]` +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 ~ CONST1 => {} +LL + &[false] => todo!() + | + +error: aborting due to 20 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/slice-patterns-irrefutable.rs b/tests/ui/pattern/usefulness/slice-patterns-irrefutable.rs new file mode 100644 index 000000000..cbf64e2c5 --- /dev/null +++ b/tests/ui/pattern/usefulness/slice-patterns-irrefutable.rs @@ -0,0 +1,26 @@ +// check-pass + +fn main() { + let s: &[bool] = &[true; 0]; + let s0: &[bool; 0] = &[]; + let s1: &[bool; 1] = &[false; 1]; + let s2: &[bool; 2] = &[false; 2]; + + let [] = s0; + let [_] = s1; + let [_, _] = s2; + + let [..] = s; + let [..] = s0; + let [..] = s1; + let [..] = s2; + + let [_, ..] = s1; + let [.., _] = s1; + let [_, ..] = s2; + let [.., _] = s2; + + let [_, _, ..] = s2; + let [_, .., _] = s2; + let [.., _, _] = s2; +} diff --git a/tests/ui/pattern/usefulness/slice-patterns-reachability.rs b/tests/ui/pattern/usefulness/slice-patterns-reachability.rs new file mode 100644 index 000000000..7c747b5e0 --- /dev/null +++ b/tests/ui/pattern/usefulness/slice-patterns-reachability.rs @@ -0,0 +1,25 @@ +#![deny(unreachable_patterns)] + +fn main() { + let s: &[bool] = &[]; + + match s { + [true, ..] => {} + [true, ..] => {} //~ ERROR unreachable pattern + [true] => {} //~ ERROR unreachable pattern + [..] => {} + } + match s { + [.., true] => {} + [.., true] => {} //~ ERROR unreachable pattern + [true] => {} //~ ERROR unreachable pattern + [..] => {} + } + match s { + [false, .., true] => {} + [false, .., true] => {} //~ ERROR unreachable pattern + [false, true] => {} //~ ERROR unreachable pattern + [false] => {} + [..] => {} + } +} diff --git a/tests/ui/pattern/usefulness/slice-patterns-reachability.stderr b/tests/ui/pattern/usefulness/slice-patterns-reachability.stderr new file mode 100644 index 000000000..607ffb765 --- /dev/null +++ b/tests/ui/pattern/usefulness/slice-patterns-reachability.stderr @@ -0,0 +1,44 @@ +error: unreachable pattern + --> $DIR/slice-patterns-reachability.rs:8:9 + | +LL | [true, ..] => {} + | ^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/slice-patterns-reachability.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/slice-patterns-reachability.rs:9:9 + | +LL | [true] => {} + | ^^^^^^ + +error: unreachable pattern + --> $DIR/slice-patterns-reachability.rs:14:9 + | +LL | [.., true] => {} + | ^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/slice-patterns-reachability.rs:15:9 + | +LL | [true] => {} + | ^^^^^^ + +error: unreachable pattern + --> $DIR/slice-patterns-reachability.rs:20:9 + | +LL | [false, .., true] => {} + | ^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/slice-patterns-reachability.rs:21:9 + | +LL | [false, true] => {} + | ^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/pattern/usefulness/stable-gated-fields.rs b/tests/ui/pattern/usefulness/stable-gated-fields.rs new file mode 100644 index 000000000..90f40a8d6 --- /dev/null +++ b/tests/ui/pattern/usefulness/stable-gated-fields.rs @@ -0,0 +1,16 @@ +// aux-build:unstable.rs + +extern crate unstable; + +use unstable::UnstableStruct; + +fn main() { + let UnstableStruct { stable } = UnstableStruct::default(); + //~^ pattern does not mention field `stable2` and inaccessible fields + + let UnstableStruct { stable, stable2 } = UnstableStruct::default(); + //~^ pattern requires `..` due to inaccessible fields + + // OK: stable field is matched + let UnstableStruct { stable, stable2, .. } = UnstableStruct::default(); +} diff --git a/tests/ui/pattern/usefulness/stable-gated-fields.stderr b/tests/ui/pattern/usefulness/stable-gated-fields.stderr new file mode 100644 index 000000000..cf98c51a2 --- /dev/null +++ b/tests/ui/pattern/usefulness/stable-gated-fields.stderr @@ -0,0 +1,29 @@ +error[E0027]: pattern does not mention field `stable2` and inaccessible fields + --> $DIR/stable-gated-fields.rs:8:9 + | +LL | let UnstableStruct { stable } = UnstableStruct::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ missing field `stable2` and inaccessible fields + | +help: include the missing field in the pattern and ignore the inaccessible fields + | +LL | let UnstableStruct { stable, stable2, .. } = UnstableStruct::default(); + | ~~~~~~~~~~~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | let UnstableStruct { stable, .. } = UnstableStruct::default(); + | ~~~~~~ + +error: pattern requires `..` due to inaccessible fields + --> $DIR/stable-gated-fields.rs:11:9 + | +LL | let UnstableStruct { stable, stable2 } = UnstableStruct::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: ignore the inaccessible and unused fields + | +LL | let UnstableStruct { stable, stable2, .. } = UnstableStruct::default(); + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0027`. diff --git a/tests/ui/pattern/usefulness/stable-gated-patterns.rs b/tests/ui/pattern/usefulness/stable-gated-patterns.rs new file mode 100644 index 000000000..03db01160 --- /dev/null +++ b/tests/ui/pattern/usefulness/stable-gated-patterns.rs @@ -0,0 +1,18 @@ +// aux-build:unstable.rs + +extern crate unstable; + +use unstable::UnstableEnum; + +fn main() { + match UnstableEnum::Stable { + UnstableEnum::Stable => {} + } + //~^^^ non-exhaustive patterns: `UnstableEnum::Stable2` and `_` not covered + + match UnstableEnum::Stable { + UnstableEnum::Stable => {} + UnstableEnum::Stable2 => {} + } + //~^^^^ non-exhaustive patterns: `_` not covered +} diff --git a/tests/ui/pattern/usefulness/stable-gated-patterns.stderr b/tests/ui/pattern/usefulness/stable-gated-patterns.stderr new file mode 100644 index 000000000..7b8588a3c --- /dev/null +++ b/tests/ui/pattern/usefulness/stable-gated-patterns.stderr @@ -0,0 +1,42 @@ +error[E0004]: non-exhaustive patterns: `UnstableEnum::Stable2` and `_` not covered + --> $DIR/stable-gated-patterns.rs:8:11 + | +LL | match UnstableEnum::Stable { + | ^^^^^^^^^^^^^^^^^^^^ patterns `UnstableEnum::Stable2` and `_` not covered + | +note: `UnstableEnum` defined here + --> $DIR/auxiliary/unstable.rs:9:5 + | +LL | pub enum UnstableEnum { + | --------------------- +... +LL | Stable2, + | ^^^^^^^ not covered + = note: the matched value is of type `UnstableEnum` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ UnstableEnum::Stable => {} +LL + UnstableEnum::Stable2 | _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/stable-gated-patterns.rs:13:11 + | +LL | match UnstableEnum::Stable { + | ^^^^^^^^^^^^^^^^^^^^ pattern `_` not covered + | +note: `UnstableEnum` defined here + --> $DIR/auxiliary/unstable.rs:5:1 + | +LL | pub enum UnstableEnum { + | ^^^^^^^^^^^^^^^^^^^^^ + = note: the matched value is of type `UnstableEnum` +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 ~ UnstableEnum::Stable2 => {} +LL + _ => todo!() + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.rs b/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.rs new file mode 100644 index 000000000..b1fc0f5ad --- /dev/null +++ b/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.rs @@ -0,0 +1,12 @@ +enum A { + B { x: Option<isize> }, + C +} + +fn main() { + let x = A::B { x: Some(3) }; + match x { //~ ERROR non-exhaustive patterns + A::C => {} + A::B { x: None } => {} + } +} diff --git a/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr b/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr new file mode 100644 index 000000000..85c97be29 --- /dev/null +++ b/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr @@ -0,0 +1,23 @@ +error[E0004]: non-exhaustive patterns: `A::B { x: Some(_) }` not covered + --> $DIR/struct-like-enum-nonexhaustive.rs:8:11 + | +LL | match x { + | ^ pattern `A::B { x: Some(_) }` not covered + | +note: `A` defined here + --> $DIR/struct-like-enum-nonexhaustive.rs:2:5 + | +LL | enum A { + | - +LL | B { x: Option<isize> }, + | ^ not covered + = note: the matched value is of type `A` +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 ~ A::B { x: None } => {} +LL + A::B { x: Some(_) } => todo!() + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/struct-pattern-match-useless.rs b/tests/ui/pattern/usefulness/struct-pattern-match-useless.rs new file mode 100644 index 000000000..93f0a9317 --- /dev/null +++ b/tests/ui/pattern/usefulness/struct-pattern-match-useless.rs @@ -0,0 +1,15 @@ +#![deny(unreachable_patterns)] + +struct Foo { + x: isize, + y: isize, +} + +pub fn main() { + let a = Foo { x: 1, y: 2 }; + match a { + Foo { x: _x, y: _y } => (), + Foo { .. } => () //~ ERROR unreachable pattern + } + +} diff --git a/tests/ui/pattern/usefulness/struct-pattern-match-useless.stderr b/tests/ui/pattern/usefulness/struct-pattern-match-useless.stderr new file mode 100644 index 000000000..fbee33de6 --- /dev/null +++ b/tests/ui/pattern/usefulness/struct-pattern-match-useless.stderr @@ -0,0 +1,16 @@ +error: unreachable pattern + --> $DIR/struct-pattern-match-useless.rs:12:9 + | +LL | Foo { x: _x, y: _y } => (), + | -------------------- matches any value +LL | Foo { .. } => () + | ^^^^^^^^^^ unreachable pattern + | +note: the lint level is defined here + --> $DIR/struct-pattern-match-useless.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/pattern/usefulness/top-level-alternation.rs b/tests/ui/pattern/usefulness/top-level-alternation.rs new file mode 100644 index 000000000..e8cd12ea4 --- /dev/null +++ b/tests/ui/pattern/usefulness/top-level-alternation.rs @@ -0,0 +1,57 @@ +#![deny(unreachable_patterns)] + +fn main() { + while let 0..=2 | 1 = 0 {} //~ ERROR unreachable pattern + if let 0..=2 | 1 = 0 {} //~ ERROR unreachable pattern + + match 0u8 { + 0 + | 0 => {} //~ ERROR unreachable pattern + _ => {} + } + match Some(0u8) { + Some(0) + | Some(0) => {} //~ ERROR unreachable pattern + _ => {} + } + match (0u8, 0u8) { + (0, _) | (_, 0) => {} + (0, 0) => {} //~ ERROR unreachable pattern + (1, 1) => {} + _ => {} + } + match (0u8, 0u8) { + (0, 1) | (2, 3) => {} + (0, 3) => {} + (2, 1) => {} + _ => {} + } + match (0u8, 0u8) { + (_, 0) | (_, 1) => {} + _ => {} + } + match (0u8, 0u8) { + (0, _) | (1, _) => {} + _ => {} + } + match Some(0u8) { + None | Some(_) => {} + _ => {} //~ ERROR unreachable pattern + } + match Some(0u8) { + None | Some(_) => {} + Some(_) => {} //~ ERROR unreachable pattern + None => {} //~ ERROR unreachable pattern + } + match Some(0u8) { + Some(_) => {} + None => {} + None | Some(_) => {} //~ ERROR unreachable pattern + } + match 0u8 { + 1 | 2 => {}, + 1..=2 => {}, //~ ERROR unreachable pattern + _ => {}, + } + let (0 | 0) = 0 else { return }; //~ ERROR unreachable pattern +} diff --git a/tests/ui/pattern/usefulness/top-level-alternation.stderr b/tests/ui/pattern/usefulness/top-level-alternation.stderr new file mode 100644 index 000000000..17fa951c5 --- /dev/null +++ b/tests/ui/pattern/usefulness/top-level-alternation.stderr @@ -0,0 +1,74 @@ +error: unreachable pattern + --> $DIR/top-level-alternation.rs:4:23 + | +LL | while let 0..=2 | 1 = 0 {} + | ^ + | +note: the lint level is defined here + --> $DIR/top-level-alternation.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/top-level-alternation.rs:5:20 + | +LL | if let 0..=2 | 1 = 0 {} + | ^ + +error: unreachable pattern + --> $DIR/top-level-alternation.rs:9:15 + | +LL | | 0 => {} + | ^ + +error: unreachable pattern + --> $DIR/top-level-alternation.rs:14:15 + | +LL | | Some(0) => {} + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/top-level-alternation.rs:19:9 + | +LL | (0, 0) => {} + | ^^^^^^ + +error: unreachable pattern + --> $DIR/top-level-alternation.rs:39:9 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/top-level-alternation.rs:43:9 + | +LL | Some(_) => {} + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/top-level-alternation.rs:44:9 + | +LL | None => {} + | ^^^^ + +error: unreachable pattern + --> $DIR/top-level-alternation.rs:49:9 + | +LL | None | Some(_) => {} + | ^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/top-level-alternation.rs:53:9 + | +LL | 1..=2 => {}, + | ^^^^^ + +error: unreachable pattern + --> $DIR/top-level-alternation.rs:56:14 + | +LL | let (0 | 0) = 0 else { return }; + | ^ + +error: aborting due to 11 previous errors + diff --git a/tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.rs b/tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.rs new file mode 100644 index 000000000..76bcf3fbd --- /dev/null +++ b/tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.rs @@ -0,0 +1,9 @@ +struct Foo(isize, isize); + +fn main() { + let x = Foo(1, 2); + match x { //~ ERROR non-exhaustive + Foo(1, b) => println!("{}", b), + Foo(2, b) => println!("{}", b) + } +} diff --git a/tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr b/tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr new file mode 100644 index 000000000..e2a65ff85 --- /dev/null +++ b/tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr @@ -0,0 +1,21 @@ +error[E0004]: non-exhaustive patterns: `Foo(_, _)` not covered + --> $DIR/tuple-struct-nonexhaustive.rs:5:11 + | +LL | match x { + | ^ pattern `Foo(_, _)` not covered + | +note: `Foo` defined here + --> $DIR/tuple-struct-nonexhaustive.rs:1:8 + | +LL | struct Foo(isize, isize); + | ^^^ + = note: the matched value is of type `Foo` +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 ~ Foo(2, b) => println!("{}", b), +LL + Foo(_, _) => todo!() + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/type_polymorphic_byte_str_literals.rs b/tests/ui/pattern/usefulness/type_polymorphic_byte_str_literals.rs new file mode 100644 index 000000000..cb44c1da7 --- /dev/null +++ b/tests/ui/pattern/usefulness/type_polymorphic_byte_str_literals.rs @@ -0,0 +1,36 @@ +#[deny(unreachable_patterns)] + +fn parse_data1(data: &[u8]) -> u32 { + match data { + b"" => 1, + _ => 2, + } +} + +fn parse_data2(data: &[u8]) -> u32 { + match data { //~ ERROR non-exhaustive patterns: `&[_, ..]` not covered + b"" => 1, + } +} + +fn parse_data3(data: &[u8; 0]) -> u8 { + match data { + b"" => 1, + } +} + +fn parse_data4(data: &[u8]) -> u8 { + match data { //~ ERROR non-exhaustive patterns + b"aaa" => 0, + [_, _, _] => 1, + } +} + +fn parse_data5(data: &[u8; 3]) -> u8 { + match data { + b"aaa" => 0, + [_, _, _] => 1, + } +} + +fn main() {} diff --git a/tests/ui/pattern/usefulness/type_polymorphic_byte_str_literals.stderr b/tests/ui/pattern/usefulness/type_polymorphic_byte_str_literals.stderr new file mode 100644 index 000000000..acae605da --- /dev/null +++ b/tests/ui/pattern/usefulness/type_polymorphic_byte_str_literals.stderr @@ -0,0 +1,29 @@ +error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered + --> $DIR/type_polymorphic_byte_str_literals.rs:11:11 + | +LL | match data { + | ^^^^ pattern `&[_, ..]` not covered + | + = note: the matched value is of type `&[u8]` +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 ~ b"" => 1, +LL ~ &[_, ..] => todo!(), + | + +error[E0004]: non-exhaustive patterns: `&[]`, `&[_]`, `&[_, _]` and 1 more not covered + --> $DIR/type_polymorphic_byte_str_literals.rs:23:11 + | +LL | match data { + | ^^^^ patterns `&[]`, `&[_]`, `&[_, _]` and 1 more not covered + | + = note: the matched value is of type `&[u8]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms + | +LL ~ [_, _, _] => 1, +LL ~ _ => todo!(), + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/uninhabited.rs b/tests/ui/pattern/usefulness/uninhabited.rs new file mode 100644 index 000000000..5622808d4 --- /dev/null +++ b/tests/ui/pattern/usefulness/uninhabited.rs @@ -0,0 +1,143 @@ +// check-pass +// aux-build:empty.rs +// +// This tests plays with matching and uninhabited types. This also serves as a test for the +// `Ty::is_inhabited_from` function. +#![feature(never_type)] +#![feature(never_type_fallback)] +#![feature(exhaustive_patterns)] +#![deny(unreachable_patterns)] + +macro_rules! assert_empty { + ($ty:ty) => { + const _: () = { + fn assert_empty(x: $ty) { + match x {} + match Some(x) { + None => {} + } + } + }; + }; +} +macro_rules! assert_non_empty { + ($ty:ty) => { + const _: () = { + fn assert_non_empty(x: $ty) { + match x { + _ => {} + } + match Some(x) { + None => {} + Some(_) => {} + } + } + }; + }; +} + +extern crate empty; +assert_empty!(empty::EmptyForeignEnum); +assert_empty!(empty::VisiblyUninhabitedForeignStruct); +assert_non_empty!(empty::SecretlyUninhabitedForeignStruct); + +enum Void {} +assert_empty!(Void); + +enum Enum2 { + Foo(Void), + Bar(!), +} +assert_empty!(Enum2); + +enum Enum3 { + Foo(Void), + Bar { + x: u64, + y: !, + }, +} +assert_empty!(Enum3); + +enum Enum4 { + Foo(u64), + Bar(!), +} +assert_non_empty!(Enum4); + +struct Struct1(empty::EmptyForeignEnum); +assert_empty!(Struct1); + +struct Struct2 { + x: u64, + y: !, +} +assert_empty!(Struct2); + +union Union { + foo: !, +} +assert_non_empty!(Union); + +assert_empty!((!, String)); + +assert_non_empty!(&'static !); +assert_non_empty!(&'static Struct1); +assert_non_empty!(&'static &'static &'static !); + +assert_empty!([!; 1]); +assert_empty!([Void; 2]); +assert_non_empty!([!; 0]); +assert_non_empty!(&'static [!]); + +mod visibility { + /// This struct can only be seen to be inhabited in modules `b`, `c` or `d`, because otherwise + /// the uninhabitedness of both `SecretlyUninhabited` structs is hidden. + struct SometimesEmptyStruct { + x: a::b::SecretlyUninhabited, + y: c::AlsoSecretlyUninhabited, + } + + /// This enum can only be seen to be inhabited in module `d`. + enum SometimesEmptyEnum { + X(c::AlsoSecretlyUninhabited), + Y(c::d::VerySecretlyUninhabited), + } + + mod a { + use super::*; + pub mod b { + use super::*; + pub struct SecretlyUninhabited { + _priv: !, + } + assert_empty!(SometimesEmptyStruct); + } + + assert_non_empty!(SometimesEmptyStruct); + assert_non_empty!(SometimesEmptyEnum); + } + + mod c { + use super::*; + pub struct AlsoSecretlyUninhabited { + _priv: ::Struct1, + } + assert_empty!(SometimesEmptyStruct); + assert_non_empty!(SometimesEmptyEnum); + + pub mod d { + use super::*; + pub struct VerySecretlyUninhabited { + _priv: !, + } + assert_empty!(SometimesEmptyStruct); + assert_empty!(SometimesEmptyEnum); + } + } + + assert_non_empty!(SometimesEmptyStruct); + assert_non_empty!(SometimesEmptyEnum); +} + +fn main() {} diff --git a/tests/ui/pattern/usefulness/unstable-gated-fields.rs b/tests/ui/pattern/usefulness/unstable-gated-fields.rs new file mode 100644 index 000000000..2b473ae98 --- /dev/null +++ b/tests/ui/pattern/usefulness/unstable-gated-fields.rs @@ -0,0 +1,18 @@ +#![feature(unstable_test_feature)] + +// aux-build:unstable.rs + +extern crate unstable; + +use unstable::UnstableStruct; + +fn main() { + let UnstableStruct { stable, stable2, } = UnstableStruct::default(); + //~^ pattern does not mention field `unstable` + + let UnstableStruct { stable, unstable, } = UnstableStruct::default(); + //~^ pattern does not mention field `stable2` + + // OK: stable field is matched + let UnstableStruct { stable, stable2, unstable } = UnstableStruct::default(); +} diff --git a/tests/ui/pattern/usefulness/unstable-gated-fields.stderr b/tests/ui/pattern/usefulness/unstable-gated-fields.stderr new file mode 100644 index 000000000..e4f5fa06b --- /dev/null +++ b/tests/ui/pattern/usefulness/unstable-gated-fields.stderr @@ -0,0 +1,33 @@ +error[E0027]: pattern does not mention field `unstable` + --> $DIR/unstable-gated-fields.rs:10:9 + | +LL | let UnstableStruct { stable, stable2, } = UnstableStruct::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing field `unstable` + | +help: include the missing field in the pattern + | +LL | let UnstableStruct { stable, stable2, unstable } = UnstableStruct::default(); + | ~~~~~~~~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | let UnstableStruct { stable, stable2, .. } = UnstableStruct::default(); + | ~~~~~~ + +error[E0027]: pattern does not mention field `stable2` + --> $DIR/unstable-gated-fields.rs:13:9 + | +LL | let UnstableStruct { stable, unstable, } = UnstableStruct::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing field `stable2` + | +help: include the missing field in the pattern + | +LL | let UnstableStruct { stable, unstable, stable2 } = UnstableStruct::default(); + | ~~~~~~~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | let UnstableStruct { stable, unstable, .. } = UnstableStruct::default(); + | ~~~~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0027`. diff --git a/tests/ui/pattern/usefulness/unstable-gated-patterns.rs b/tests/ui/pattern/usefulness/unstable-gated-patterns.rs new file mode 100644 index 000000000..7046555e0 --- /dev/null +++ b/tests/ui/pattern/usefulness/unstable-gated-patterns.rs @@ -0,0 +1,22 @@ +#![feature(unstable_test_feature)] + +// aux-build:unstable.rs + +extern crate unstable; + +use unstable::UnstableEnum; + +fn main() { + match UnstableEnum::Stable { + UnstableEnum::Stable => {} + UnstableEnum::Stable2 => {} + } + //~^^^^ non-exhaustive patterns: `UnstableEnum::Unstable` not covered + + // Ok: all variants are explicitly matched + match UnstableEnum::Stable { + UnstableEnum::Stable => {} + UnstableEnum::Stable2 => {} + UnstableEnum::Unstable => {} + } +} diff --git a/tests/ui/pattern/usefulness/unstable-gated-patterns.stderr b/tests/ui/pattern/usefulness/unstable-gated-patterns.stderr new file mode 100644 index 000000000..6dc9a4058 --- /dev/null +++ b/tests/ui/pattern/usefulness/unstable-gated-patterns.stderr @@ -0,0 +1,24 @@ +error[E0004]: non-exhaustive patterns: `UnstableEnum::Unstable` not covered + --> $DIR/unstable-gated-patterns.rs:10:11 + | +LL | match UnstableEnum::Stable { + | ^^^^^^^^^^^^^^^^^^^^ pattern `UnstableEnum::Unstable` not covered + | +note: `UnstableEnum` defined here + --> $DIR/auxiliary/unstable.rs:11:5 + | +LL | pub enum UnstableEnum { + | --------------------- +... +LL | Unstable, + | ^^^^^^^^ not covered + = note: the matched value is of type `UnstableEnum` +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 ~ UnstableEnum::Stable2 => {} +LL + UnstableEnum::Unstable => todo!() + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. |