summaryrefslogtreecommitdiffstats
path: root/src/test/ui/uninhabited
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/ui/uninhabited')
-rw-r--r--src/test/ui/uninhabited/exhaustive-wo-nevertype-issue-51221.rs9
-rw-r--r--src/test/ui/uninhabited/privately-uninhabited-dead-code.rs20
-rw-r--r--src/test/ui/uninhabited/privately-uninhabited-mir-call.rs29
-rw-r--r--src/test/ui/uninhabited/privately-uninhabited-mir-call.stderr12
-rw-r--r--src/test/ui/uninhabited/uninhabited-enum-cast.rs9
-rw-r--r--src/test/ui/uninhabited/uninhabited-irrefutable.rs28
-rw-r--r--src/test/ui/uninhabited/uninhabited-irrefutable.stderr28
-rw-r--r--src/test/ui/uninhabited/uninhabited-matches-feature-gated.rs39
-rw-r--r--src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr133
-rw-r--r--src/test/ui/uninhabited/uninhabited-patterns.rs47
-rw-r--r--src/test/ui/uninhabited/uninhabited-patterns.stderr38
11 files changed, 392 insertions, 0 deletions
diff --git a/src/test/ui/uninhabited/exhaustive-wo-nevertype-issue-51221.rs b/src/test/ui/uninhabited/exhaustive-wo-nevertype-issue-51221.rs
new file mode 100644
index 000000000..b59432078
--- /dev/null
+++ b/src/test/ui/uninhabited/exhaustive-wo-nevertype-issue-51221.rs
@@ -0,0 +1,9 @@
+// check-pass
+
+#![feature(exhaustive_patterns)]
+
+enum Void {}
+fn main() {
+ let a: Option<Void> = None;
+ let None = a;
+}
diff --git a/src/test/ui/uninhabited/privately-uninhabited-dead-code.rs b/src/test/ui/uninhabited/privately-uninhabited-dead-code.rs
new file mode 100644
index 000000000..f476704cd
--- /dev/null
+++ b/src/test/ui/uninhabited/privately-uninhabited-dead-code.rs
@@ -0,0 +1,20 @@
+// build-pass (FIXME(62277): could be check-pass?)
+
+#![deny(unused_variables)]
+
+mod foo {
+ enum Bar {}
+
+ #[allow(dead_code)]
+ pub struct Foo {
+ value: Bar, // "privately" uninhabited
+ }
+
+ pub fn give_foo() -> Foo { panic!() }
+}
+
+fn main() {
+ let a = 42;
+ foo::give_foo();
+ println!("Hello, {}", a); // ok: we can't tell that this code is dead
+}
diff --git a/src/test/ui/uninhabited/privately-uninhabited-mir-call.rs b/src/test/ui/uninhabited/privately-uninhabited-mir-call.rs
new file mode 100644
index 000000000..2764bb563
--- /dev/null
+++ b/src/test/ui/uninhabited/privately-uninhabited-mir-call.rs
@@ -0,0 +1,29 @@
+// Verifies that MIR building for a call expression respects
+// privacy when checking if a call return type is uninhabited.
+
+pub mod widget {
+ enum Unimplemented {}
+ pub struct Widget(Unimplemented);
+
+ impl Widget {
+ pub fn new() -> Widget {
+ todo!();
+ }
+ }
+
+ pub fn f() {
+ let x: &mut u32;
+ Widget::new();
+ // Ok. Widget type returned from new is known to be uninhabited
+ // and the following code is considered unreachable.
+ *x = 1;
+ }
+}
+
+fn main() {
+ let y: &mut u32;
+ widget::Widget::new();
+ // Error. Widget type is not known to be uninhabited here,
+ // so the following code is considered reachable.
+ *y = 2; //~ ERROR E0381
+}
diff --git a/src/test/ui/uninhabited/privately-uninhabited-mir-call.stderr b/src/test/ui/uninhabited/privately-uninhabited-mir-call.stderr
new file mode 100644
index 000000000..95c209f47
--- /dev/null
+++ b/src/test/ui/uninhabited/privately-uninhabited-mir-call.stderr
@@ -0,0 +1,12 @@
+error[E0381]: used binding `y` isn't initialized
+ --> $DIR/privately-uninhabited-mir-call.rs:28:5
+ |
+LL | let y: &mut u32;
+ | - binding declared here but left uninitialized
+...
+LL | *y = 2;
+ | ^^^^^^ `y` used here but it isn't initialized
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/uninhabited/uninhabited-enum-cast.rs b/src/test/ui/uninhabited/uninhabited-enum-cast.rs
new file mode 100644
index 000000000..5a75c94c4
--- /dev/null
+++ b/src/test/ui/uninhabited/uninhabited-enum-cast.rs
@@ -0,0 +1,9 @@
+// check-pass
+
+enum E {}
+
+fn f(e: E) {
+ println!("{}", (e as isize).to_string());
+}
+
+fn main() {}
diff --git a/src/test/ui/uninhabited/uninhabited-irrefutable.rs b/src/test/ui/uninhabited/uninhabited-irrefutable.rs
new file mode 100644
index 000000000..661b5486a
--- /dev/null
+++ b/src/test/ui/uninhabited/uninhabited-irrefutable.rs
@@ -0,0 +1,28 @@
+#![feature(never_type)]
+#![feature(exhaustive_patterns)]
+
+mod foo {
+ pub struct SecretlyEmpty {
+ _priv: !,
+ }
+
+ pub struct NotSoSecretlyEmpty {
+ pub _pub: !,
+ }
+}
+
+struct NotSoSecretlyEmpty {
+ _priv: !,
+}
+
+enum Foo {
+ A(foo::SecretlyEmpty),
+ B(foo::NotSoSecretlyEmpty),
+ C(NotSoSecretlyEmpty),
+ D(u32, u32),
+}
+
+fn main() {
+ let x: Foo = Foo::D(123, 456);
+ let Foo::D(_y, _z) = x; //~ ERROR refutable pattern in local binding: `A(_)` not covered
+}
diff --git a/src/test/ui/uninhabited/uninhabited-irrefutable.stderr b/src/test/ui/uninhabited/uninhabited-irrefutable.stderr
new file mode 100644
index 000000000..c571e17a7
--- /dev/null
+++ b/src/test/ui/uninhabited/uninhabited-irrefutable.stderr
@@ -0,0 +1,28 @@
+error[E0005]: refutable pattern in local binding: `A(_)` not covered
+ --> $DIR/uninhabited-irrefutable.rs:27:9
+ |
+LL | let Foo::D(_y, _z) = x;
+ | ^^^^^^^^^^^^^^ pattern `A(_)` 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: `Foo` defined here
+ --> $DIR/uninhabited-irrefutable.rs:19:5
+ |
+LL | enum Foo {
+ | ---
+LL | A(foo::SecretlyEmpty),
+ | ^ not covered
+ = note: the matched value is of type `Foo`
+help: you might want to use `if let` to ignore the variant that isn't matched
+ |
+LL | let (_y, _z) = if let Foo::D(_y, _z) = x { (_y, _z) } else { todo!() };
+ | +++++++++++++++++ +++++++++++++++++++++++++++++
+help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched
+ |
+LL | let Foo::D(_y, _z) = x else { todo!() };
+ | ++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0005`.
diff --git a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.rs b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.rs
new file mode 100644
index 000000000..e804afcf9
--- /dev/null
+++ b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.rs
@@ -0,0 +1,39 @@
+use std::mem::zeroed;
+enum Void {}
+
+fn main() {
+ let x: Result<u32, &'static Void> = Ok(23);
+ let _ = match x { //~ ERROR non-exhaustive
+ Ok(n) => n,
+ };
+
+ // This is pretty much instant UB. However, we have no choice -- we need to
+ // test matching on a reference to `&Void`; we cannot do anything other than
+ // just accept the fact that this is UB if `main` did run, but it doesn't;
+ // this test only checks that these are feature-gated.
+ let x: &Void = unsafe { zeroed() };
+ let _ = match x {}; //~ ERROR non-exhaustive
+
+ let x: (Void,) = unsafe { zeroed() };
+ let _ = match x {}; //~ ERROR non-exhaustive
+
+ let x: [Void; 1] = unsafe { zeroed() };
+ let _ = match x {}; //~ ERROR non-exhaustive
+
+ let x: &[Void] = unsafe { zeroed() };
+ let _ = match x { //~ ERROR non-exhaustive
+ &[] => (),
+ };
+
+ let x: Void = unsafe { zeroed() };
+ let _ = match x {}; // okay
+
+ let x: Result<u32, Void> = Ok(23);
+ let _ = match x { //~ ERROR non-exhaustive
+ Ok(x) => x,
+ };
+
+ let x: Result<u32, Void> = Ok(23);
+ let Ok(x) = x;
+ //~^ ERROR refutable
+}
diff --git a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
new file mode 100644
index 000000000..2c107b1f7
--- /dev/null
+++ b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
@@ -0,0 +1,133 @@
+error[E0004]: non-exhaustive patterns: `Err(_)` not covered
+ --> $DIR/uninhabited-matches-feature-gated.rs:6:19
+ |
+LL | let _ = match x {
+ | ^ pattern `Err(_)` not covered
+ |
+note: `Result<u32, &Void>` defined here
+ --> $SRC_DIR/core/src/result.rs:LL:COL
+ |
+LL | pub enum Result<T, E> {
+ | ---------------------
+...
+LL | Err(#[stable(feature = "rust1", since = "1.0.0")] E),
+ | ^^^ not covered
+ = note: the matched value is of type `Result<u32, &Void>`
+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 ~ Ok(n) => n,
+LL ~ Err(_) => todo!(),
+ |
+
+error[E0004]: non-exhaustive patterns: type `&Void` is non-empty
+ --> $DIR/uninhabited-matches-feature-gated.rs:15:19
+ |
+LL | let _ = match x {};
+ | ^
+ |
+note: `Void` defined here
+ --> $DIR/uninhabited-matches-feature-gated.rs:2:6
+ |
+LL | enum Void {}
+ | ^^^^
+ = note: the matched value is of type `&Void`
+ = 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 ~ let _ = match x {
+LL + _ => todo!(),
+LL ~ };
+ |
+
+error[E0004]: non-exhaustive patterns: type `(Void,)` is non-empty
+ --> $DIR/uninhabited-matches-feature-gated.rs:18:19
+ |
+LL | let _ = match x {};
+ | ^
+ |
+ = note: the matched value is of type `(Void,)`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ let _ = match x {
+LL + _ => todo!(),
+LL ~ };
+ |
+
+error[E0004]: non-exhaustive patterns: type `[Void; 1]` is non-empty
+ --> $DIR/uninhabited-matches-feature-gated.rs:21:19
+ |
+LL | let _ = match x {};
+ | ^
+ |
+ = note: the matched value is of type `[Void; 1]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ let _ = match x {
+LL + _ => todo!(),
+LL ~ };
+ |
+
+error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered
+ --> $DIR/uninhabited-matches-feature-gated.rs:24:19
+ |
+LL | let _ = match x {
+ | ^ pattern `&[_, ..]` not covered
+ |
+ = note: the matched value is of type `&[Void]`
+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: `Err(_)` not covered
+ --> $DIR/uninhabited-matches-feature-gated.rs:32:19
+ |
+LL | let _ = match x {
+ | ^ pattern `Err(_)` not covered
+ |
+note: `Result<u32, Void>` defined here
+ --> $SRC_DIR/core/src/result.rs:LL:COL
+ |
+LL | pub enum Result<T, E> {
+ | ---------------------
+...
+LL | Err(#[stable(feature = "rust1", since = "1.0.0")] E),
+ | ^^^ not covered
+ = note: the matched value is of type `Result<u32, Void>`
+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 ~ Ok(x) => x,
+LL ~ Err(_) => todo!(),
+ |
+
+error[E0005]: refutable pattern in local binding: `Err(_)` not covered
+ --> $DIR/uninhabited-matches-feature-gated.rs:37:9
+ |
+LL | let Ok(x) = x;
+ | ^^^^^ pattern `Err(_)` 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: `Result<u32, Void>` defined here
+ --> $SRC_DIR/core/src/result.rs:LL:COL
+ |
+LL | pub enum Result<T, E> {
+ | ---------------------
+...
+LL | Err(#[stable(feature = "rust1", since = "1.0.0")] E),
+ | ^^^ not covered
+ = note: the matched value is of type `Result<u32, Void>`
+help: you might want to use `if let` to ignore the variant that isn't matched
+ |
+LL | let x = if let Ok(x) = x { x } else { todo!() };
+ | ++++++++++ ++++++++++++++++++++++
+help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched
+ |
+LL | let Ok(x) = x else { todo!() };
+ | ++++++++++++++++
+
+error: aborting due to 7 previous errors
+
+Some errors have detailed explanations: E0004, E0005.
+For more information about an error, try `rustc --explain E0004`.
diff --git a/src/test/ui/uninhabited/uninhabited-patterns.rs b/src/test/ui/uninhabited/uninhabited-patterns.rs
new file mode 100644
index 000000000..f1573b6ad
--- /dev/null
+++ b/src/test/ui/uninhabited/uninhabited-patterns.rs
@@ -0,0 +1,47 @@
+#![feature(box_patterns)]
+#![feature(never_type)]
+#![feature(exhaustive_patterns)]
+
+
+#![deny(unreachable_patterns)]
+
+mod foo {
+ pub struct SecretlyEmpty {
+ _priv: !,
+ }
+}
+
+struct NotSoSecretlyEmpty {
+ _priv: !,
+}
+
+fn foo() -> Option<NotSoSecretlyEmpty> {
+ None
+}
+
+fn main() {
+ let x: &[!] = &[];
+
+ match x {
+ &[] => (),
+ &[..] => (), //~ ERROR unreachable pattern
+ };
+
+ let x: Result<Box<NotSoSecretlyEmpty>, &[Result<!, !>]> = Err(&[]);
+ match x {
+ Ok(box _) => (), //~ ERROR unreachable pattern
+ Err(&[]) => (),
+ Err(&[..]) => (), //~ ERROR unreachable pattern
+ }
+
+ let x: Result<foo::SecretlyEmpty, Result<NotSoSecretlyEmpty, u32>> = Err(Err(123));
+ match x {
+ Ok(_y) => (),
+ Err(Err(_y)) => (),
+ Err(Ok(_y)) => (), //~ ERROR unreachable pattern
+ }
+
+ while let Some(_y) = foo() {
+ //~^ ERROR unreachable pattern
+ }
+}
diff --git a/src/test/ui/uninhabited/uninhabited-patterns.stderr b/src/test/ui/uninhabited/uninhabited-patterns.stderr
new file mode 100644
index 000000000..655569ad6
--- /dev/null
+++ b/src/test/ui/uninhabited/uninhabited-patterns.stderr
@@ -0,0 +1,38 @@
+error: unreachable pattern
+ --> $DIR/uninhabited-patterns.rs:27:9
+ |
+LL | &[..] => (),
+ | ^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/uninhabited-patterns.rs:6:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/uninhabited-patterns.rs:32:9
+ |
+LL | Ok(box _) => (),
+ | ^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/uninhabited-patterns.rs:34:9
+ |
+LL | Err(&[..]) => (),
+ | ^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/uninhabited-patterns.rs:41:9
+ |
+LL | Err(Ok(_y)) => (),
+ | ^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/uninhabited-patterns.rs:44:15
+ |
+LL | while let Some(_y) = foo() {
+ | ^^^^^^^^
+
+error: aborting due to 5 previous errors
+