forked from rust-lang/rust
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rollup merge of rust-lang#120009 - Nadrieril:never_patterns_tyck, r=compiler-errors never_patterns: typecheck never patterns This checks that a `!` pattern is only used on an uninhabited type (modulo match ergonomics, i.e. `!` is allowed on `&Void`). r? `@compiler-errors`
- Loading branch information
Showing
8 changed files
with
223 additions
and
92 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
error: mismatched types | ||
--> $DIR/typeck.rs:25:9 | ||
| | ||
LL | !, | ||
| ^ a never pattern must be used on an uninhabited type | ||
| | ||
= note: the matched value is of type `()` | ||
|
||
error: mismatched types | ||
--> $DIR/typeck.rs:29:9 | ||
| | ||
LL | !, | ||
| ^ a never pattern must be used on an uninhabited type | ||
| | ||
= note: the matched value is of type `(i32, bool)` | ||
|
||
error: mismatched types | ||
--> $DIR/typeck.rs:33:13 | ||
| | ||
LL | (_, !), | ||
| ^ a never pattern must be used on an uninhabited type | ||
| | ||
= note: the matched value is of type `bool` | ||
|
||
error: mismatched types | ||
--> $DIR/typeck.rs:38:14 | ||
| | ||
LL | Some(!), | ||
| ^ a never pattern must be used on an uninhabited type | ||
| | ||
= note: the matched value is of type `i32` | ||
|
||
error: mismatched types | ||
--> $DIR/typeck.rs:45:9 | ||
| | ||
LL | !, | ||
| ^ a never pattern must be used on an uninhabited type | ||
| | ||
= note: the matched value is of type `()` | ||
|
||
error: mismatched types | ||
--> $DIR/typeck.rs:52:9 | ||
| | ||
LL | !, | ||
| ^ a never pattern must be used on an uninhabited type | ||
| | ||
= note: the matched value is of type `Option<Void>` | ||
|
||
error: mismatched types | ||
--> $DIR/typeck.rs:57:9 | ||
| | ||
LL | !, | ||
| ^ a never pattern must be used on an uninhabited type | ||
| | ||
= note: the matched value is of type `[Void]` | ||
|
||
error: mismatched types | ||
--> $DIR/typeck.rs:63:9 | ||
| | ||
LL | !, | ||
| ^ a never pattern must be used on an uninhabited type | ||
| | ||
= note: the matched value is of type `Option<&Void>` | ||
|
||
error: aborting due to 8 previous errors | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
// revisions: pass fail | ||
//[pass] check-pass | ||
//[fail] check-fail | ||
#![feature(never_patterns)] | ||
#![feature(exhaustive_patterns)] | ||
#![allow(incomplete_features)] | ||
|
||
#[derive(Copy, Clone)] | ||
enum Void {} | ||
|
||
fn main() {} | ||
|
||
// The classic use for empty types. | ||
fn safe_unwrap_result<T: Copy>(res: Result<T, Void>) { | ||
let Ok(_x) = res; | ||
let (Ok(_x) | Err(!)) = &res; | ||
let (Ok(_x) | Err(!)) = res.as_ref(); | ||
} | ||
|
||
// Check we only accept `!` where we want to. | ||
#[cfg(fail)] | ||
fn never_pattern_typeck_fail(void: Void) { | ||
// Don't accept on a non-empty type. | ||
match () { | ||
!, | ||
//[fail]~^ ERROR: mismatched types | ||
} | ||
match (0, false) { | ||
!, | ||
//[fail]~^ ERROR: mismatched types | ||
} | ||
match (0, false) { | ||
(_, !), | ||
//[fail]~^ ERROR: mismatched types | ||
} | ||
match Some(0) { | ||
None => {} | ||
Some(!), | ||
//[fail]~^ ERROR: mismatched types | ||
} | ||
|
||
// Don't accept on an arbitrary type, even if there are no more branches. | ||
match () { | ||
() => {} | ||
!, | ||
//[fail]~^ ERROR: mismatched types | ||
} | ||
|
||
// Don't accept even on an empty branch. | ||
match None::<Void> { | ||
None => {} | ||
!, | ||
//[fail]~^ ERROR: mismatched types | ||
} | ||
match (&[] as &[Void]) { | ||
[] => {} | ||
!, | ||
//[fail]~^ ERROR: mismatched types | ||
} | ||
// Let alone if the emptiness is behind a reference. | ||
match None::<&Void> { | ||
None => {} | ||
!, | ||
//[fail]~^ ERROR: mismatched types | ||
} | ||
} | ||
|
||
#[cfg(pass)] | ||
fn never_pattern_typeck_pass(void: Void) { | ||
// Participate in match ergonomics. | ||
match &void { | ||
!, | ||
} | ||
match &&void { | ||
!, | ||
} | ||
match &&void { | ||
&!, | ||
} | ||
match &None::<Void> { | ||
None => {} | ||
Some(!), | ||
} | ||
match None::<&Void> { | ||
None => {} | ||
Some(!), | ||
} | ||
|
||
// Accept on a directly empty type. | ||
match void { | ||
!, | ||
} | ||
match &void { | ||
&!, | ||
} | ||
match None::<Void> { | ||
None => {} | ||
Some(!), | ||
} | ||
match None::<&Void> { | ||
None => {} | ||
Some(&!), | ||
} | ||
match None::<&(u32, Void)> { | ||
None => {} | ||
Some(&(_, !)), | ||
} | ||
match (&[] as &[Void]) { | ||
[] => {} | ||
[!], | ||
} | ||
// Accept on a composite empty type. | ||
match None::<&(u32, Void)> { | ||
None => {} | ||
Some(&!), | ||
} | ||
match None::<&(u32, Void)> { | ||
None => {} | ||
Some(!), | ||
} | ||
match None::<&Result<Void, Void>> { | ||
None => {} | ||
Some(!), | ||
} | ||
} |