Rollup merge of #118157 - Nadrieril:never_pat-feature-gate, r=compiler-errors
Add `never_patterns` feature gate This PR adds the feature gate and most basic parsing for the experimental `never_patterns` feature. See the tracking issue (https://github.com/rust-lang/rust/issues/118155) for details on the experiment. `@scottmcm` has agreed to be my lang-team liaison for this experiment.
This commit is contained in:
commit
c03f8917ee
40 changed files with 325 additions and 18 deletions
27
tests/ui/feature-gates/feature-gate-never_patterns.rs
Normal file
27
tests/ui/feature-gates/feature-gate-never_patterns.rs
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
// Check that never patterns require the feature gate.
|
||||
use std::ptr::NonNull;
|
||||
|
||||
enum Void {}
|
||||
|
||||
fn main() {
|
||||
let res: Result<u32, Void> = Ok(0);
|
||||
let (Ok(_x) | Err(&!)) = res.as_ref();
|
||||
//~^ ERROR `!` patterns are experimental
|
||||
//~| ERROR: is not bound in all patterns
|
||||
|
||||
unsafe {
|
||||
let ptr: *const Void = NonNull::dangling().as_ptr();
|
||||
match *ptr {
|
||||
! => {} //~ ERROR `!` patterns are experimental
|
||||
}
|
||||
}
|
||||
|
||||
// Check that the gate operates even behind `cfg`.
|
||||
#[cfg(FALSE)]
|
||||
unsafe {
|
||||
let ptr: *const Void = NonNull::dangling().as_ptr();
|
||||
match *ptr {
|
||||
! => {} //~ ERROR `!` patterns are experimental
|
||||
}
|
||||
}
|
||||
}
|
||||
39
tests/ui/feature-gates/feature-gate-never_patterns.stderr
Normal file
39
tests/ui/feature-gates/feature-gate-never_patterns.stderr
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
error[E0408]: variable `_x` is not bound in all patterns
|
||||
--> $DIR/feature-gate-never_patterns.rs:8:19
|
||||
|
|
||||
LL | let (Ok(_x) | Err(&!)) = res.as_ref();
|
||||
| -- ^^^^^^^ pattern doesn't bind `_x`
|
||||
| |
|
||||
| variable not in all patterns
|
||||
|
||||
error[E0658]: `!` patterns are experimental
|
||||
--> $DIR/feature-gate-never_patterns.rs:8:24
|
||||
|
|
||||
LL | let (Ok(_x) | Err(&!)) = res.as_ref();
|
||||
| ^
|
||||
|
|
||||
= note: see issue #118155 <https://github.com/rust-lang/rust/issues/118155> for more information
|
||||
= help: add `#![feature(never_patterns)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: `!` patterns are experimental
|
||||
--> $DIR/feature-gate-never_patterns.rs:15:13
|
||||
|
|
||||
LL | ! => {}
|
||||
| ^
|
||||
|
|
||||
= note: see issue #118155 <https://github.com/rust-lang/rust/issues/118155> for more information
|
||||
= help: add `#![feature(never_patterns)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: `!` patterns are experimental
|
||||
--> $DIR/feature-gate-never_patterns.rs:24:13
|
||||
|
|
||||
LL | ! => {}
|
||||
| ^
|
||||
|
|
||||
= note: see issue #118155 <https://github.com/rust-lang/rust/issues/118155> for more information
|
||||
= help: add `#![feature(never_patterns)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0408, E0658.
|
||||
For more information about an error, try `rustc --explain E0408`.
|
||||
|
|
@ -11,6 +11,7 @@
|
|||
#![feature(decl_macro)]
|
||||
#![feature(explicit_tail_calls)]
|
||||
#![feature(more_qualified_paths)]
|
||||
#![feature(never_patterns)]
|
||||
#![feature(raw_ref_op)]
|
||||
#![feature(trait_alias)]
|
||||
#![feature(try_blocks)]
|
||||
|
|
@ -635,6 +636,10 @@ fn test_pat() {
|
|||
// PatKind::Rest
|
||||
c1!(pat, [ .. ], "..");
|
||||
|
||||
// PatKind::Never
|
||||
c1!(pat, [ Some(!) ], "Some(!)");
|
||||
c1!(pat, [ None | Some(!) ], "None | Some(!)");
|
||||
|
||||
// PatKind::Paren
|
||||
c1!(pat, [ (pat) ], "(pat)");
|
||||
|
||||
|
|
|
|||
99
tests/ui/pattern/never_patterns.rs
Normal file
99
tests/ui/pattern/never_patterns.rs
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
#![feature(never_patterns)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
enum Void {}
|
||||
|
||||
fn main() {}
|
||||
|
||||
// The classic use for empty types.
|
||||
fn safe_unwrap_result<T>(res: Result<T, Void>) {
|
||||
let Ok(_x) = res;
|
||||
// FIXME(never_patterns): These should be allowed
|
||||
let (Ok(_x) | Err(!)) = &res;
|
||||
//~^ ERROR: is not bound in all patterns
|
||||
let (Ok(_x) | Err(&!)) = res.as_ref();
|
||||
//~^ ERROR: is not bound in all patterns
|
||||
}
|
||||
|
||||
// Check we only accept `!` where we want to.
|
||||
fn never_pattern_location(void: Void) {
|
||||
// FIXME(never_patterns): Don't accept on a non-empty type.
|
||||
match Some(0) {
|
||||
None => {}
|
||||
Some(!) => {}
|
||||
}
|
||||
// FIXME(never_patterns): Don't accept on an arbitrary type, even if there are no more branches.
|
||||
match () {
|
||||
() => {}
|
||||
! => {}
|
||||
}
|
||||
// FIXME(never_patterns): Don't accept even on an empty branch.
|
||||
match None::<Void> {
|
||||
None => {}
|
||||
! => {}
|
||||
}
|
||||
// FIXME(never_patterns): Let alone if the emptiness is behind a reference.
|
||||
match None::<&Void> {
|
||||
None => {}
|
||||
! => {}
|
||||
}
|
||||
// Participate in match ergonomics.
|
||||
match &void {
|
||||
! => {}
|
||||
}
|
||||
match &&void {
|
||||
! => {}
|
||||
}
|
||||
match &&void {
|
||||
&! => {}
|
||||
}
|
||||
match &None::<Void> {
|
||||
None => {}
|
||||
Some(!) => {}
|
||||
}
|
||||
match None::<&Void> {
|
||||
None => {}
|
||||
Some(!) => {}
|
||||
}
|
||||
// Accept on a composite empty type.
|
||||
match None::<&(u32, Void)> {
|
||||
None => {}
|
||||
Some(&!) => {}
|
||||
}
|
||||
// Accept on an simple empty type.
|
||||
match None::<Void> {
|
||||
None => {}
|
||||
Some(!) => {}
|
||||
}
|
||||
match None::<&Void> {
|
||||
None => {}
|
||||
Some(&!) => {}
|
||||
}
|
||||
match None::<&(u32, Void)> {
|
||||
None => {}
|
||||
Some(&(_, !)) => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn never_and_bindings() {
|
||||
let x: Result<bool, &(u32, Void)> = Ok(false);
|
||||
|
||||
// FIXME(never_patterns): Never patterns in or-patterns don't need to share the same bindings.
|
||||
match x {
|
||||
Ok(_x) | Err(&!) => {}
|
||||
//~^ ERROR: is not bound in all patterns
|
||||
}
|
||||
let (Ok(_x) | Err(&!)) = x;
|
||||
//~^ ERROR: is not bound in all patterns
|
||||
|
||||
// FIXME(never_patterns): A never pattern mustn't have bindings.
|
||||
match x {
|
||||
Ok(_) => {}
|
||||
Err(&(_b, !)) => {}
|
||||
}
|
||||
match x {
|
||||
Ok(_a) | Err(&(_b, !)) => {}
|
||||
//~^ ERROR: is not bound in all patterns
|
||||
//~| ERROR: is not bound in all patterns
|
||||
}
|
||||
}
|
||||
51
tests/ui/pattern/never_patterns.stderr
Normal file
51
tests/ui/pattern/never_patterns.stderr
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
error[E0408]: variable `_x` is not bound in all patterns
|
||||
--> $DIR/never_patterns.rs:12:19
|
||||
|
|
||||
LL | let (Ok(_x) | Err(!)) = &res;
|
||||
| -- ^^^^^^ pattern doesn't bind `_x`
|
||||
| |
|
||||
| variable not in all patterns
|
||||
|
||||
error[E0408]: variable `_x` is not bound in all patterns
|
||||
--> $DIR/never_patterns.rs:14:19
|
||||
|
|
||||
LL | let (Ok(_x) | Err(&!)) = res.as_ref();
|
||||
| -- ^^^^^^^ pattern doesn't bind `_x`
|
||||
| |
|
||||
| variable not in all patterns
|
||||
|
||||
error[E0408]: variable `_x` is not bound in all patterns
|
||||
--> $DIR/never_patterns.rs:83:18
|
||||
|
|
||||
LL | Ok(_x) | Err(&!) => {}
|
||||
| -- ^^^^^^^ pattern doesn't bind `_x`
|
||||
| |
|
||||
| variable not in all patterns
|
||||
|
||||
error[E0408]: variable `_x` is not bound in all patterns
|
||||
--> $DIR/never_patterns.rs:86:19
|
||||
|
|
||||
LL | let (Ok(_x) | Err(&!)) = x;
|
||||
| -- ^^^^^^^ pattern doesn't bind `_x`
|
||||
| |
|
||||
| variable not in all patterns
|
||||
|
||||
error[E0408]: variable `_b` is not bound in all patterns
|
||||
--> $DIR/never_patterns.rs:95:9
|
||||
|
|
||||
LL | Ok(_a) | Err(&(_b, !)) => {}
|
||||
| ^^^^^^ -- variable not in all patterns
|
||||
| |
|
||||
| pattern doesn't bind `_b`
|
||||
|
||||
error[E0408]: variable `_a` is not bound in all patterns
|
||||
--> $DIR/never_patterns.rs:95:18
|
||||
|
|
||||
LL | Ok(_a) | Err(&(_b, !)) => {}
|
||||
| -- ^^^^^^^^^^^^^ pattern doesn't bind `_a`
|
||||
| |
|
||||
| variable not in all patterns
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0408`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue