Skip to content

Commit bc31c39

Browse files
committed
Review
1 parent ac23b66 commit bc31c39

File tree

7 files changed

+72
-40
lines changed

7 files changed

+72
-40
lines changed

compiler/rustc_hir_typeck/src/pat.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
178178

179179
let ty = match pat.kind {
180180
PatKind::Wild => expected,
181-
PatKind::Never => expected, // FIXME(never_patterns): check the type is uninhabited
181+
// FIXME(never_patterns): check the type is uninhabited. If that is not possible within
182+
// typeck, do that in a later phase.
183+
PatKind::Never => expected,
182184
PatKind::Lit(lt) => self.check_pat_lit(pat.span, lt, expected, ti),
183185
PatKind::Range(lhs, rhs, _) => self.check_pat_range(pat.span, lhs, rhs, expected, ti),
184186
PatKind::Binding(ba, var_id, _, sub) => {
@@ -288,6 +290,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
288290
| PatKind::Box(_)
289291
| PatKind::Range(..)
290292
| PatKind::Slice(..) => AdjustMode::Peel,
293+
// A never pattern behaves somewhat like a literal or unit variant.
294+
PatKind::Never => AdjustMode::Peel,
291295
// String and byte-string literals result in types `&str` and `&[u8]` respectively.
292296
// All other literals result in non-reference types.
293297
// As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo" {}`.
@@ -308,8 +312,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
308312
// a reference type wherefore peeling doesn't give up any expressiveness.
309313
_ => AdjustMode::Peel,
310314
},
311-
// A never pattern behaves somewhat like a literal or unit variant.
312-
PatKind::Never => AdjustMode::Peel,
313315
// When encountering a `& mut? pat` pattern, reset to "by value".
314316
// This is so that `x` and `y` here are by value, as they appear to be:
315317
//

compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1558,7 +1558,9 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
15581558
fields = Fields::from_iter(cx, pats.into_iter().map(mkpat));
15591559
}
15601560
PatKind::Never => {
1561-
ctor = Wildcard; // FIXME(never_patterns)
1561+
// FIXME(never_patterns): handle `!` in exhaustiveness. This is a sane default
1562+
// in the meantime.
1563+
ctor = Wildcard;
15621564
fields = Fields::empty();
15631565
}
15641566
PatKind::Error(_) => {

src/tools/rustfmt/src/patterns.rs

+14-18
Original file line numberDiff line numberDiff line change
@@ -40,21 +40,23 @@ pub(crate) fn is_short_pattern(pat: &ast::Pat, pat_str: &str) -> bool {
4040

4141
fn is_short_pattern_inner(pat: &ast::Pat) -> bool {
4242
match pat.kind {
43-
PatKind::Rest | PatKind::Never | PatKind::Wild | PatKind::Lit(_) => true,
44-
PatKind::Ident(_, _, ref pat) => pat.is_none(),
45-
PatKind::Struct(..)
46-
| PatKind::MacCall(..)
47-
| PatKind::Slice(..)
48-
| PatKind::Path(..)
49-
| PatKind::Range(..) => false,
50-
PatKind::Tuple(ref subpats) => subpats.len() <= 1,
51-
PatKind::TupleStruct(_, ref path, ref subpats) => {
43+
ast::PatKind::Rest | ast::PatKind::Never | ast::PatKind::Wild | ast::PatKind::Lit(_) => {
44+
true
45+
}
46+
ast::PatKind::Ident(_, _, ref pat) => pat.is_none(),
47+
ast::PatKind::Struct(..)
48+
| ast::PatKind::MacCall(..)
49+
| ast::PatKind::Slice(..)
50+
| ast::PatKind::Path(..)
51+
| ast::PatKind::Range(..) => false,
52+
ast::PatKind::Tuple(ref subpats) => subpats.len() <= 1,
53+
ast::PatKind::TupleStruct(_, ref path, ref subpats) => {
5254
path.segments.len() <= 1 && subpats.len() <= 1
5355
}
54-
PatKind::Box(ref p) | PatKind::Ref(ref p, _) | PatKind::Paren(ref p) => {
56+
ast::PatKind::Box(ref p) | ast::PatKind::Ref(ref p, _) | ast::PatKind::Paren(ref p) => {
5557
is_short_pattern_inner(&*p)
5658
}
57-
PatKind::Or(ref pats) => pats.iter().all(|p| is_short_pattern_inner(p)),
59+
ast::PatKind::Or(ref pats) => pats.iter().all(|p| is_short_pattern_inner(p)),
5860
}
5961
}
6062

@@ -193,13 +195,7 @@ impl Rewrite for Pat {
193195
None
194196
}
195197
}
196-
PatKind::Never => {
197-
if 1 <= shape.width {
198-
Some("!".to_owned())
199-
} else {
200-
None
201-
}
202-
}
198+
PatKind::Never => None,
203199
PatKind::Range(ref lhs, ref rhs, ref end_kind) => {
204200
let infix = match end_kind.node {
205201
RangeEnd::Included(RangeSyntax::DotDotDot) => "...",

tests/ui/feature-gates/feature-gate-never_patterns.rs

+9
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,13 @@ fn main() {
1515
! => {} //~ ERROR `!` patterns are experimental
1616
}
1717
}
18+
19+
// Check that the gate operates even behind `cfg`.
20+
#[cfg(FALSE)]
21+
unsafe {
22+
let ptr: *const Void = NonNull::dangling().as_ptr();
23+
match *ptr {
24+
! => {} //~ ERROR `!` patterns are experimental
25+
}
26+
}
1827
}

tests/ui/feature-gates/feature-gate-never_patterns.stderr

+10-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,16 @@ LL | ! => {}
2424
= note: see issue #118155 <https://github.com/rust-lang/rust/issues/118155> for more information
2525
= help: add `#![feature(never_patterns)]` to the crate attributes to enable
2626

27-
error: aborting due to 3 previous errors
27+
error[E0658]: `!` patterns are experimental
28+
--> $DIR/feature-gate-never_patterns.rs:24:13
29+
|
30+
LL | ! => {}
31+
| ^
32+
|
33+
= note: see issue #118155 <https://github.com/rust-lang/rust/issues/118155> for more information
34+
= help: add `#![feature(never_patterns)]` to the crate attributes to enable
35+
36+
error: aborting due to 4 previous errors
2837

2938
Some errors have detailed explanations: E0408, E0658.
3039
For more information about an error, try `rustc --explain E0408`.

tests/ui/pattern/never_patterns.rs

+25-11
Original file line numberDiff line numberDiff line change
@@ -8,45 +8,59 @@ fn main() {}
88
// The classic use for empty types.
99
fn safe_unwrap_result<T>(res: Result<T, Void>) {
1010
let Ok(_x) = res;
11+
// FIXME(never_patterns): These should be allowed
1112
let (Ok(_x) | Err(!)) = &res;
1213
//~^ ERROR: is not bound in all patterns
1314
let (Ok(_x) | Err(&!)) = res.as_ref();
1415
//~^ ERROR: is not bound in all patterns
1516
}
1617

17-
// Check we only accept `!` where we want.
18-
fn never_pattern_location() {
19-
// Don't accept on a non-empty type.
18+
// Check we only accept `!` where we want to.
19+
fn never_pattern_location(void: Void) {
20+
// FIXME(never_patterns): Don't accept on a non-empty type.
2021
match Some(0) {
2122
None => {}
2223
Some(!) => {}
2324
}
24-
// Don't accept on an arbitrary type, even if there are no more branches.
25+
// FIXME(never_patterns): Don't accept on an arbitrary type, even if there are no more branches.
2526
match () {
2627
() => {}
2728
! => {}
2829
}
29-
// Don't accept even on an empty branch.
30+
// FIXME(never_patterns): Don't accept even on an empty branch.
3031
match None::<Void> {
3132
None => {}
3233
! => {}
3334
}
34-
// Let alone if the emptiness is behind a reference.
35+
// FIXME(never_patterns): Let alone if the emptiness is behind a reference.
3536
match None::<&Void> {
3637
None => {}
3738
! => {}
3839
}
39-
// Don't participate in match ergonomics.
40+
// Participate in match ergonomics.
41+
match &void {
42+
! => {}
43+
}
44+
match &&void {
45+
! => {}
46+
}
47+
match &&void {
48+
&! => {}
49+
}
50+
match &None::<Void> {
51+
None => {}
52+
Some(!) => {}
53+
}
4054
match None::<&Void> {
4155
None => {}
4256
Some(!) => {}
4357
}
44-
// Accept on a nested empty type.
58+
// Accept on a composite empty type.
4559
match None::<&(u32, Void)> {
4660
None => {}
4761
Some(&!) => {}
4862
}
49-
// Accept on an basic empty type.
63+
// Accept on an simple empty type.
5064
match None::<Void> {
5165
None => {}
5266
Some(!) => {}
@@ -64,15 +78,15 @@ fn never_pattern_location() {
6478
fn never_and_bindings() {
6579
let x: Result<bool, &(u32, Void)> = Ok(false);
6680

67-
// Never patterns in or-patterns don't need to share the same bindings.
81+
// FIXME(never_patterns): Never patterns in or-patterns don't need to share the same bindings.
6882
match x {
6983
Ok(_x) | Err(&!) => {}
7084
//~^ ERROR: is not bound in all patterns
7185
}
7286
let (Ok(_x) | Err(&!)) = x;
7387
//~^ ERROR: is not bound in all patterns
7488

75-
// A never pattern mustn't have bindings.
89+
// FIXME(never_patterns): A never pattern mustn't have bindings.
7690
match x {
7791
Ok(_) => {}
7892
Err(&(_b, !)) => {}

tests/ui/pattern/never_patterns.stderr

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,45 @@
11
error[E0408]: variable `_x` is not bound in all patterns
2-
--> $DIR/never_patterns.rs:11:19
2+
--> $DIR/never_patterns.rs:12:19
33
|
44
LL | let (Ok(_x) | Err(!)) = &res;
55
| -- ^^^^^^ pattern doesn't bind `_x`
66
| |
77
| variable not in all patterns
88

99
error[E0408]: variable `_x` is not bound in all patterns
10-
--> $DIR/never_patterns.rs:13:19
10+
--> $DIR/never_patterns.rs:14:19
1111
|
1212
LL | let (Ok(_x) | Err(&!)) = res.as_ref();
1313
| -- ^^^^^^^ pattern doesn't bind `_x`
1414
| |
1515
| variable not in all patterns
1616

1717
error[E0408]: variable `_x` is not bound in all patterns
18-
--> $DIR/never_patterns.rs:69:18
18+
--> $DIR/never_patterns.rs:83:18
1919
|
2020
LL | Ok(_x) | Err(&!) => {}
2121
| -- ^^^^^^^ pattern doesn't bind `_x`
2222
| |
2323
| variable not in all patterns
2424

2525
error[E0408]: variable `_x` is not bound in all patterns
26-
--> $DIR/never_patterns.rs:72:19
26+
--> $DIR/never_patterns.rs:86:19
2727
|
2828
LL | let (Ok(_x) | Err(&!)) = x;
2929
| -- ^^^^^^^ pattern doesn't bind `_x`
3030
| |
3131
| variable not in all patterns
3232

3333
error[E0408]: variable `_b` is not bound in all patterns
34-
--> $DIR/never_patterns.rs:81:9
34+
--> $DIR/never_patterns.rs:95:9
3535
|
3636
LL | Ok(_a) | Err(&(_b, !)) => {}
3737
| ^^^^^^ -- variable not in all patterns
3838
| |
3939
| pattern doesn't bind `_b`
4040

4141
error[E0408]: variable `_a` is not bound in all patterns
42-
--> $DIR/never_patterns.rs:81:18
42+
--> $DIR/never_patterns.rs:95:18
4343
|
4444
LL | Ok(_a) | Err(&(_b, !)) => {}
4545
| -- ^^^^^^^^^^^^^ pattern doesn't bind `_a`

0 commit comments

Comments
 (0)