about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--tests/ui/pattern/deref-patterns/usefulness/empty-types.rs47
-rw-r--r--tests/ui/pattern/deref-patterns/usefulness/empty-types.stderr38
-rw-r--r--tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.rs28
-rw-r--r--tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.stderr63
-rw-r--r--tests/ui/pattern/deref-patterns/usefulness/unreachable-patterns.rs33
-rw-r--r--tests/ui/pattern/deref-patterns/usefulness/unreachable-patterns.stderr60
6 files changed, 269 insertions, 0 deletions
diff --git a/tests/ui/pattern/deref-patterns/usefulness/empty-types.rs b/tests/ui/pattern/deref-patterns/usefulness/empty-types.rs
new file mode 100644
index 00000000000..03419030e72
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/usefulness/empty-types.rs
@@ -0,0 +1,47 @@
+//! Test that the place behind a deref pattern is treated as maybe-invalid, and thus empty arms
+//! cannot be omitted. This is handled the same as for refs and union fields, so this leaves the
+//! bulk of the testing to `tests/ui/pattern/usefulness/empty-types.rs`.
+// FIXME(deref_patterns): On stabilization, cases for deref patterns could be worked into that file
+// to keep the tests for empty types in one place and test more thoroughly.
+#![feature(deref_patterns)]
+#![expect(incomplete_features)]
+#![deny(unreachable_patterns)]
+
+enum Void {}
+
+fn main() {
+    // Sanity check: matching on an empty type without pointer indirection lets us omit arms.
+    let opt_void: Option<Void> = None;
+    match opt_void {
+        None => {}
+    }
+
+    // But if we hide it behind a smart pointer, we need an arm.
+    let box_opt_void: Box<Option<Void>> = Box::new(None);
+    match box_opt_void {
+        //~^ ERROR non-exhaustive patterns: `deref!(Some(_))` not covered
+        None => {}
+    }
+    match box_opt_void {
+        None => {}
+        Some(_) => {}
+    }
+    match box_opt_void {
+        None => {}
+        _ => {}
+    }
+
+    // For consistency, this behaves the same as if we manually dereferenced the scrutinee.
+    match *box_opt_void {
+        //~^ ERROR non-exhaustive patterns: `Some(_)` not covered
+        None => {}
+    }
+    match *box_opt_void {
+        None => {}
+        Some(_) => {}
+    }
+    match *box_opt_void {
+        None => {}
+        _ => {}
+    }
+}
diff --git a/tests/ui/pattern/deref-patterns/usefulness/empty-types.stderr b/tests/ui/pattern/deref-patterns/usefulness/empty-types.stderr
new file mode 100644
index 00000000000..e3247708566
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/usefulness/empty-types.stderr
@@ -0,0 +1,38 @@
+error[E0004]: non-exhaustive patterns: `deref!(Some(_))` not covered
+  --> $DIR/empty-types.rs:21:11
+   |
+LL |     match box_opt_void {
+   |           ^^^^^^^^^^^^ pattern `deref!(Some(_))` not covered
+   |
+note: `Box<Option<Void>>` defined here
+  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
+   = note: the matched value is of type `Box<Option<Void>>`
+   = note: `Void` is uninhabited but is not being matched by value, so a wildcard `_` is required
+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 +         deref!(Some(_)) => todo!()
+   |
+
+error[E0004]: non-exhaustive patterns: `Some(_)` not covered
+  --> $DIR/empty-types.rs:35:11
+   |
+LL |     match *box_opt_void {
+   |           ^^^^^^^^^^^^^ pattern `Some(_)` not covered
+   |
+note: `Option<Void>` 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<Void>`
+   = note: `Void` is uninhabited but is not being matched by value, so a wildcard `_` is required
+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: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.rs b/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.rs
new file mode 100644
index 00000000000..704cae8bdbc
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.rs
@@ -0,0 +1,28 @@
+//! Test non-exhaustive matches involving deref patterns.
+#![feature(deref_patterns)]
+#![expect(incomplete_features)]
+#![deny(unreachable_patterns)]
+
+fn main() {
+    match Box::new(false) {
+        //~^ ERROR non-exhaustive patterns: `deref!(true)` not covered
+        false => {}
+    }
+
+    match Box::new(Box::new(false)) {
+        //~^ ERROR non-exhaustive patterns: `deref!(deref!(false))` not covered
+        true => {}
+    }
+
+    match Box::new((true, Box::new(false))) {
+        //~^ ERROR non-exhaustive patterns: `deref!((false, deref!(false)))` and `deref!((true, deref!(true)))` not covered
+        (true, false) => {}
+        (false, true) => {}
+    }
+
+    enum T { A, B, C }
+    match Box::new((Box::new(T::A), Box::new(T::A))) {
+        //~^ ERROR non-exhaustive patterns: `deref!((deref!(T::C), _))` not covered
+        (T::A | T::B, T::C) => {}
+    }
+}
diff --git a/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.stderr b/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.stderr
new file mode 100644
index 00000000000..55fa84bafde
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.stderr
@@ -0,0 +1,63 @@
+error[E0004]: non-exhaustive patterns: `deref!(true)` not covered
+  --> $DIR/non-exhaustive.rs:7:11
+   |
+LL |     match Box::new(false) {
+   |           ^^^^^^^^^^^^^^^ pattern `deref!(true)` not covered
+   |
+note: `Box<bool>` defined here
+  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
+   = note: the matched value is of type `Box<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 +         deref!(true) => todo!()
+   |
+
+error[E0004]: non-exhaustive patterns: `deref!(deref!(false))` not covered
+  --> $DIR/non-exhaustive.rs:12:11
+   |
+LL |     match Box::new(Box::new(false)) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `deref!(deref!(false))` not covered
+   |
+note: `Box<Box<bool>>` defined here
+  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
+   = note: the matched value is of type `Box<Box<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 +         deref!(deref!(false)) => todo!()
+   |
+
+error[E0004]: non-exhaustive patterns: `deref!((false, deref!(false)))` and `deref!((true, deref!(true)))` not covered
+  --> $DIR/non-exhaustive.rs:17:11
+   |
+LL |     match Box::new((true, Box::new(false))) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ patterns `deref!((false, deref!(false)))` and `deref!((true, deref!(true)))` not covered
+   |
+note: `Box<(bool, Box<bool>)>` defined here
+  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
+   = note: the matched value is of type `Box<(bool, Box<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, true) => {},
+LL +         deref!((false, deref!(false))) | deref!((true, deref!(true))) => todo!()
+   |
+
+error[E0004]: non-exhaustive patterns: `deref!((deref!(T::C), _))` not covered
+  --> $DIR/non-exhaustive.rs:24:11
+   |
+LL |     match Box::new((Box::new(T::A), Box::new(T::A))) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `deref!((deref!(T::C), _))` not covered
+   |
+note: `Box<(Box<T>, Box<T>)>` defined here
+  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
+   = note: the matched value is of type `Box<(Box<T>, Box<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 | T::B, T::C) => {},
+LL +         deref!((deref!(T::C), _)) => todo!()
+   |
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/deref-patterns/usefulness/unreachable-patterns.rs b/tests/ui/pattern/deref-patterns/usefulness/unreachable-patterns.rs
new file mode 100644
index 00000000000..2677fc54ded
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/usefulness/unreachable-patterns.rs
@@ -0,0 +1,33 @@
+//! Test unreachable patterns involving deref patterns.
+#![feature(deref_patterns)]
+#![expect(incomplete_features)]
+#![deny(unreachable_patterns)]
+
+fn main() {
+    match Box::new(false) {
+        true => {}
+        false => {}
+        false => {} //~ ERROR unreachable pattern
+    }
+
+    match Box::new(Box::new(false)) {
+        true => {}
+        false => {}
+        true => {} //~ ERROR unreachable pattern
+    }
+
+    match Box::new((true, Box::new(false))) {
+        (true, _) => {}
+        (_, true) => {}
+        (false, false) => {}
+        _ => {} //~ ERROR unreachable pattern
+    }
+
+    enum T { A, B, C }
+    match Box::new((Box::new(T::A), Box::new(T::A))) {
+        (T::A | T::B, T::A | T::C) => {}
+        (T::A, T::C) => {} //~ ERROR unreachable pattern
+        (T::B, T::A) => {} //~ ERROR unreachable pattern
+        _ => {}
+    }
+}
diff --git a/tests/ui/pattern/deref-patterns/usefulness/unreachable-patterns.stderr b/tests/ui/pattern/deref-patterns/usefulness/unreachable-patterns.stderr
new file mode 100644
index 00000000000..045e11be319
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/usefulness/unreachable-patterns.stderr
@@ -0,0 +1,60 @@
+error: unreachable pattern
+  --> $DIR/unreachable-patterns.rs:10:9
+   |
+LL |         false => {}
+   |         ----- matches all the relevant values
+LL |         false => {}
+   |         ^^^^^ no value can reach this
+   |
+note: the lint level is defined here
+  --> $DIR/unreachable-patterns.rs:4:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/unreachable-patterns.rs:16:9
+   |
+LL |         true => {}
+   |         ---- matches all the relevant values
+LL |         false => {}
+LL |         true => {}
+   |         ^^^^ no value can reach this
+
+error: unreachable pattern
+  --> $DIR/unreachable-patterns.rs:23:9
+   |
+LL |         _ => {}
+   |         ^ no value can reach this
+   |
+note: multiple earlier patterns match some of the same values
+  --> $DIR/unreachable-patterns.rs:23:9
+   |
+LL |         (true, _) => {}
+   |         --------- matches some of the same values
+LL |         (_, true) => {}
+   |         --------- matches some of the same values
+LL |         (false, false) => {}
+   |         -------------- matches some of the same values
+LL |         _ => {}
+   |         ^ collectively making this unreachable
+
+error: unreachable pattern
+  --> $DIR/unreachable-patterns.rs:29:9
+   |
+LL |         (T::A | T::B, T::A | T::C) => {}
+   |         -------------------------- matches all the relevant values
+LL |         (T::A, T::C) => {}
+   |         ^^^^^^^^^^^^ no value can reach this
+
+error: unreachable pattern
+  --> $DIR/unreachable-patterns.rs:30:9
+   |
+LL |         (T::A | T::B, T::A | T::C) => {}
+   |         -------------------------- matches all the relevant values
+LL |         (T::A, T::C) => {}
+LL |         (T::B, T::A) => {}
+   |         ^^^^^^^^^^^^ no value can reach this
+
+error: aborting due to 5 previous errors
+