Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 714b29a

Browse files
committedJan 15, 2024
Auto merge of rust-lang#119610 - Nadrieril:never_pattern_bindings, r=compiler-errors
never patterns: Check bindings wrt never patterns Never patterns: - Shouldn't contain bindings since they never match anything; - Don't count when checking that or-patterns have consistent bindings. r? `@compiler-errors`
2 parents bfcc027 + 5ccd29d commit 714b29a

File tree

13 files changed

+243
-130
lines changed

13 files changed

+243
-130
lines changed
 

‎compiler/rustc_resolve/messages.ftl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ resolve_attempt_to_use_non_constant_value_in_constant_with_suggestion =
3636
resolve_attempt_to_use_non_constant_value_in_constant_without_suggestion =
3737
this would need to be a `{$suggestion}`
3838
39+
resolve_binding_in_never_pattern =
40+
never patterns cannot contain variable bindings
41+
.suggestion = use a wildcard `_` instead
42+
3943
resolve_binding_shadows_something_unacceptable =
4044
{$shadowing_binding}s cannot shadow {$shadowed_binding}s
4145
.label = cannot be named the same as {$article} {$shadowed_binding}

‎compiler/rustc_resolve/src/diagnostics.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -959,6 +959,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
959959
.create_err(errs::TraitImplDuplicate { span, name, trait_item_span, old_span }),
960960
ResolutionError::InvalidAsmSym => self.dcx().create_err(errs::InvalidAsmSym { span }),
961961
ResolutionError::LowercaseSelf => self.dcx().create_err(errs::LowercaseSelf { span }),
962+
ResolutionError::BindingInNeverPattern => {
963+
self.dcx().create_err(errs::BindingInNeverPattern { span })
964+
}
962965
}
963966
}
964967

‎compiler/rustc_resolve/src/errors.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,15 @@ pub(crate) struct LowercaseSelf {
486486
pub(crate) span: Span,
487487
}
488488

489+
#[derive(Debug)]
490+
#[derive(Diagnostic)]
491+
#[diag(resolve_binding_in_never_pattern)]
492+
pub(crate) struct BindingInNeverPattern {
493+
#[primary_span]
494+
#[suggestion(code = "_", applicability = "machine-applicable", style = "short")]
495+
pub(crate) span: Span,
496+
}
497+
489498
#[derive(Diagnostic)]
490499
#[diag(resolve_trait_impl_duplicate, code = "E0201")]
491500
pub(crate) struct TraitImplDuplicate {

‎compiler/rustc_resolve/src/late.rs

Lines changed: 94 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ enum IsRepeatExpr {
6565
Yes,
6666
}
6767

68+
struct IsNeverPattern;
69+
6870
/// Describes whether an `AnonConst` is a type level const arg or
6971
/// some other form of anon const (i.e. inline consts or enum discriminants)
7072
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -3246,12 +3248,31 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
32463248
self.resolve_pattern_top(&local.pat, PatternSource::Let);
32473249
}
32483250

3249-
/// build a map from pattern identifiers to binding-info's.
3250-
/// this is done hygienically. This could arise for a macro
3251-
/// that expands into an or-pattern where one 'x' was from the
3252-
/// user and one 'x' came from the macro.
3253-
fn binding_mode_map(&mut self, pat: &Pat) -> FxIndexMap<Ident, BindingInfo> {
3251+
/// Build a map from pattern identifiers to binding-info's, and check the bindings are
3252+
/// consistent when encountering or-patterns and never patterns.
3253+
/// This is done hygienically: this could arise for a macro that expands into an or-pattern
3254+
/// where one 'x' was from the user and one 'x' came from the macro.
3255+
///
3256+
/// A never pattern by definition indicates an unreachable case. For example, matching on
3257+
/// `Result<T, &!>` could look like:
3258+
/// ```rust
3259+
/// # #![feature(never_type)]
3260+
/// # #![feature(never_patterns)]
3261+
/// # fn bar(_x: u32) {}
3262+
/// let foo: Result<u32, &!> = Ok(0);
3263+
/// match foo {
3264+
/// Ok(x) => bar(x),
3265+
/// Err(&!),
3266+
/// }
3267+
/// ```
3268+
/// This extends to product types: `(x, !)` is likewise unreachable. So it doesn't make sense to
3269+
/// have a binding here, and we tell the user to use `_` instead.
3270+
fn compute_and_check_binding_map(
3271+
&mut self,
3272+
pat: &Pat,
3273+
) -> Result<FxIndexMap<Ident, BindingInfo>, IsNeverPattern> {
32543274
let mut binding_map = FxIndexMap::default();
3275+
let mut is_never_pat = false;
32553276

32563277
pat.walk(&mut |pat| {
32573278
match pat.kind {
@@ -3263,18 +3284,27 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
32633284
PatKind::Or(ref ps) => {
32643285
// Check the consistency of this or-pattern and
32653286
// then add all bindings to the larger map.
3266-
for bm in self.check_consistent_bindings(ps) {
3267-
binding_map.extend(bm);
3287+
match self.compute_and_check_or_pat_binding_map(ps) {
3288+
Ok(bm) => binding_map.extend(bm),
3289+
Err(IsNeverPattern) => is_never_pat = true,
32683290
}
32693291
return false;
32703292
}
3293+
PatKind::Never => is_never_pat = true,
32713294
_ => {}
32723295
}
32733296

32743297
true
32753298
});
32763299

3277-
binding_map
3300+
if is_never_pat {
3301+
for (_, binding) in binding_map {
3302+
self.report_error(binding.span, ResolutionError::BindingInNeverPattern);
3303+
}
3304+
Err(IsNeverPattern)
3305+
} else {
3306+
Ok(binding_map)
3307+
}
32783308
}
32793309

32803310
fn is_base_res_local(&self, nid: NodeId) -> bool {
@@ -3284,33 +3314,52 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
32843314
)
32853315
}
32863316

3287-
/// Checks that all of the arms in an or-pattern have exactly the
3288-
/// same set of bindings, with the same binding modes for each.
3289-
fn check_consistent_bindings(
3317+
/// Compute the binding map for an or-pattern. Checks that all of the arms in the or-pattern
3318+
/// have exactly the same set of bindings, with the same binding modes for each.
3319+
/// Returns the computed binding map and a boolean indicating whether the pattern is a never
3320+
/// pattern.
3321+
///
3322+
/// A never pattern by definition indicates an unreachable case. For example, destructuring a
3323+
/// `Result<T, &!>` could look like:
3324+
/// ```rust
3325+
/// # #![feature(never_type)]
3326+
/// # #![feature(never_patterns)]
3327+
/// # fn foo() -> Result<bool, &'static !> { Ok(true) }
3328+
/// let (Ok(x) | Err(&!)) = foo();
3329+
/// # let _ = x;
3330+
/// ```
3331+
/// Because the `Err(&!)` branch is never reached, it does not need to have the same bindings as
3332+
/// the other branches of the or-pattern. So we must ignore never pattern when checking the
3333+
/// bindings of an or-pattern.
3334+
/// Moreover, if all the subpatterns are never patterns (e.g. `Ok(!) | Err(!)`), then the
3335+
/// pattern as a whole counts as a never pattern (since it's definitionallly unreachable).
3336+
fn compute_and_check_or_pat_binding_map(
32903337
&mut self,
32913338
pats: &[P<Pat>],
3292-
) -> Vec<FxIndexMap<Ident, BindingInfo>> {
3293-
// pats is consistent.
3339+
) -> Result<FxIndexMap<Ident, BindingInfo>, IsNeverPattern> {
32943340
let mut missing_vars = FxIndexMap::default();
32953341
let mut inconsistent_vars = FxIndexMap::default();
32963342

3297-
// 1) Compute the binding maps of all arms.
3298-
let maps = pats.iter().map(|pat| self.binding_mode_map(pat)).collect::<Vec<_>>();
3343+
// 1) Compute the binding maps of all arms; we must ignore never patterns here.
3344+
let not_never_pats = pats
3345+
.iter()
3346+
.filter_map(|pat| {
3347+
let binding_map = self.compute_and_check_binding_map(pat).ok()?;
3348+
Some((binding_map, pat))
3349+
})
3350+
.collect::<Vec<_>>();
32993351

33003352
// 2) Record any missing bindings or binding mode inconsistencies.
3301-
for (map_outer, pat_outer) in maps.iter().zip(pats.iter()) {
3353+
for (map_outer, pat_outer) in not_never_pats.iter() {
33023354
// Check against all arms except for the same pattern which is always self-consistent.
3303-
let inners = maps
3355+
let inners = not_never_pats
33043356
.iter()
3305-
.zip(pats.iter())
33063357
.filter(|(_, pat)| pat.id != pat_outer.id)
3307-
.flat_map(|(map, _)| map)
3308-
.map(|(key, binding)| (key.name, map_outer.get(key), binding));
3309-
3310-
let inners = inners.collect::<Vec<_>>();
3358+
.flat_map(|(map, _)| map);
33113359

3312-
for (name, info, &binding_inner) in inners {
3313-
match info {
3360+
for (key, binding_inner) in inners {
3361+
let name = key.name;
3362+
match map_outer.get(key) {
33143363
None => {
33153364
// The inner binding is missing in the outer.
33163365
let binding_error =
@@ -3351,19 +3400,32 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
33513400
self.report_error(v.0, ResolutionError::VariableBoundWithDifferentMode(name, v.1));
33523401
}
33533402

3354-
// 5) Finally bubble up all the binding maps.
3355-
maps
3403+
// 5) Bubble up the final binding map.
3404+
if not_never_pats.is_empty() {
3405+
// All the patterns are never patterns, so the whole or-pattern is one too.
3406+
Err(IsNeverPattern)
3407+
} else {
3408+
let mut binding_map = FxIndexMap::default();
3409+
for (bm, _) in not_never_pats {
3410+
binding_map.extend(bm);
3411+
}
3412+
Ok(binding_map)
3413+
}
33563414
}
33573415

3358-
/// Check the consistency of the outermost or-patterns.
3359-
fn check_consistent_bindings_top(&mut self, pat: &'ast Pat) {
3416+
/// Check the consistency of bindings wrt or-patterns and never patterns.
3417+
fn check_consistent_bindings(&mut self, pat: &'ast Pat) {
3418+
let mut is_or_or_never = false;
33603419
pat.walk(&mut |pat| match pat.kind {
3361-
PatKind::Or(ref ps) => {
3362-
self.check_consistent_bindings(ps);
3420+
PatKind::Or(..) | PatKind::Never => {
3421+
is_or_or_never = true;
33633422
false
33643423
}
33653424
_ => true,
3366-
})
3425+
});
3426+
if is_or_or_never {
3427+
let _ = self.compute_and_check_binding_map(pat);
3428+
}
33673429
}
33683430

33693431
fn resolve_arm(&mut self, arm: &'ast Arm) {
@@ -3392,7 +3454,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
33923454
visit::walk_pat(self, pat);
33933455
self.resolve_pattern_inner(pat, pat_src, bindings);
33943456
// This has to happen *after* we determine which pat_idents are variants:
3395-
self.check_consistent_bindings_top(pat);
3457+
self.check_consistent_bindings(pat);
33963458
}
33973459

33983460
/// Resolve bindings in a pattern. This is a helper to `resolve_pattern`.

‎compiler/rustc_resolve/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,8 @@ enum ResolutionError<'a> {
265265
InvalidAsmSym,
266266
/// `self` used instead of `Self` in a generic parameter
267267
LowercaseSelf,
268+
/// A never pattern has a binding.
269+
BindingInNeverPattern,
268270
}
269271

270272
enum VisResolutionError<'a> {

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ fn main() {
77
let res: Result<u32, Void> = Ok(0);
88
let (Ok(_x) | Err(&!)) = res.as_ref();
99
//~^ ERROR `!` patterns are experimental
10-
//~| ERROR: is not bound in all patterns
1110

1211
unsafe {
1312
let ptr: *const Void = NonNull::dangling().as_ptr();
Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: unexpected `,` in pattern
2-
--> $DIR/feature-gate-never_patterns.rs:34:16
2+
--> $DIR/feature-gate-never_patterns.rs:33:16
33
|
44
LL | Some(_),
55
| ^
@@ -13,14 +13,6 @@ help: ...or a vertical bar to match on multiple alternatives
1313
LL | Some(_) |
1414
|
1515

16-
error[E0408]: variable `_x` is not bound in all patterns
17-
--> $DIR/feature-gate-never_patterns.rs:8:19
18-
|
19-
LL | let (Ok(_x) | Err(&!)) = res.as_ref();
20-
| -- ^^^^^^^ pattern doesn't bind `_x`
21-
| |
22-
| variable not in all patterns
23-
2416
error[E0658]: `!` patterns are experimental
2517
--> $DIR/feature-gate-never_patterns.rs:8:24
2618
|
@@ -32,7 +24,7 @@ LL | let (Ok(_x) | Err(&!)) = res.as_ref();
3224
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
3325

3426
error[E0658]: `!` patterns are experimental
35-
--> $DIR/feature-gate-never_patterns.rs:15:13
27+
--> $DIR/feature-gate-never_patterns.rs:14:13
3628
|
3729
LL | !
3830
| ^
@@ -42,7 +34,7 @@ LL | !
4234
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
4335

4436
error[E0658]: `!` patterns are experimental
45-
--> $DIR/feature-gate-never_patterns.rs:21:13
37+
--> $DIR/feature-gate-never_patterns.rs:20:13
4638
|
4739
LL | !
4840
| ^
@@ -52,7 +44,7 @@ LL | !
5244
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
5345

5446
error[E0658]: `!` patterns are experimental
55-
--> $DIR/feature-gate-never_patterns.rs:26:13
47+
--> $DIR/feature-gate-never_patterns.rs:25:13
5648
|
5749
LL | ! => {}
5850
| ^
@@ -62,25 +54,25 @@ LL | ! => {}
6254
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
6355

6456
error: `match` arm with no body
65-
--> $DIR/feature-gate-never_patterns.rs:39:9
57+
--> $DIR/feature-gate-never_patterns.rs:38:9
6658
|
6759
LL | Some(_)
6860
| ^^^^^^^- help: add a body after the pattern: `=> todo!(),`
6961

7062
error: `match` arm with no body
71-
--> $DIR/feature-gate-never_patterns.rs:44:9
63+
--> $DIR/feature-gate-never_patterns.rs:43:9
7264
|
7365
LL | Some(_) if false,
7466
| ^^^^^^^- help: add a body after the pattern: `=> todo!(),`
7567

7668
error: `match` arm with no body
77-
--> $DIR/feature-gate-never_patterns.rs:46:9
69+
--> $DIR/feature-gate-never_patterns.rs:45:9
7870
|
7971
LL | Some(_) if false
8072
| ^^^^^^^- help: add a body after the pattern: `=> todo!(),`
8173

8274
error[E0658]: `!` patterns are experimental
83-
--> $DIR/feature-gate-never_patterns.rs:51:13
75+
--> $DIR/feature-gate-never_patterns.rs:50:13
8476
|
8577
LL | Err(!),
8678
| ^
@@ -90,7 +82,7 @@ LL | Err(!),
9082
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
9183

9284
error[E0658]: `!` patterns are experimental
93-
--> $DIR/feature-gate-never_patterns.rs:55:13
85+
--> $DIR/feature-gate-never_patterns.rs:54:13
9486
|
9587
LL | Err(!) if false,
9688
| ^
@@ -100,24 +92,23 @@ LL | Err(!) if false,
10092
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
10193

10294
error: `match` arm with no body
103-
--> $DIR/feature-gate-never_patterns.rs:65:9
95+
--> $DIR/feature-gate-never_patterns.rs:64:9
10496
|
10597
LL | Some(_)
10698
| ^^^^^^^- help: add a body after the pattern: `=> todo!(),`
10799

108100
error: `match` arm with no body
109-
--> $DIR/feature-gate-never_patterns.rs:71:9
101+
--> $DIR/feature-gate-never_patterns.rs:70:9
110102
|
111103
LL | Some(_) if false
112104
| ^^^^^^^- help: add a body after the pattern: `=> todo!(),`
113105

114106
error: a guard on a never pattern will never be run
115-
--> $DIR/feature-gate-never_patterns.rs:55:19
107+
--> $DIR/feature-gate-never_patterns.rs:54:19
116108
|
117109
LL | Err(!) if false,
118110
| ^^^^^ help: remove this guard
119111

120-
error: aborting due to 14 previous errors
112+
error: aborting due to 13 previous errors
121113

122-
Some errors have detailed explanations: E0408, E0658.
123-
For more information about an error, try `rustc --explain E0408`.
114+
For more information about this error, try `rustc --explain E0658`.

‎tests/ui/pattern/never_patterns.rs

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,9 @@ fn main() {}
77

88
// The classic use for empty types.
99
fn safe_unwrap_result<T>(res: Result<T, Void>) {
10-
let Ok(_x) = res;
11-
// FIXME(never_patterns): These should be allowed
10+
let Ok(_x) = res; //~ ERROR refutable pattern in local binding
1211
let (Ok(_x) | Err(!)) = &res;
13-
//~^ ERROR: is not bound in all patterns
1412
let (Ok(_x) | Err(&!)) = res.as_ref();
15-
//~^ ERROR: is not bound in all patterns
1613
}
1714

1815
// Check we only accept `!` where we want to.
@@ -74,26 +71,3 @@ fn never_pattern_location(void: Void) {
7471
Some(&(_, !)),
7572
}
7673
}
77-
78-
fn never_and_bindings() {
79-
let x: Result<bool, &(u32, Void)> = Ok(false);
80-
81-
// FIXME(never_patterns): Never patterns in or-patterns don't need to share the same bindings.
82-
match x {
83-
Ok(_x) | Err(&!) => {}
84-
//~^ ERROR: is not bound in all patterns
85-
}
86-
let (Ok(_x) | Err(&!)) = x;
87-
//~^ ERROR: is not bound in all patterns
88-
89-
// FIXME(never_patterns): A never pattern mustn't have bindings.
90-
match x {
91-
Ok(_) => {}
92-
Err(&(_b, !)),
93-
}
94-
match x {
95-
Ok(_a) | Err(&(_b, !)) => {}
96-
//~^ ERROR: is not bound in all patterns
97-
//~| ERROR: is not bound in all patterns
98-
}
99-
}
Lines changed: 12 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,17 @@
1-
error[E0408]: variable `_x` is not bound in all patterns
2-
--> $DIR/never_patterns.rs:12:19
1+
error[E0005]: refutable pattern in local binding
2+
--> $DIR/never_patterns.rs:10:9
33
|
4-
LL | let (Ok(_x) | Err(!)) = &res;
5-
| -- ^^^^^^ pattern doesn't bind `_x`
6-
| |
7-
| variable not in all patterns
8-
9-
error[E0408]: variable `_x` is not bound in all patterns
10-
--> $DIR/never_patterns.rs:14:19
11-
|
12-
LL | let (Ok(_x) | Err(&!)) = res.as_ref();
13-
| -- ^^^^^^^ pattern doesn't bind `_x`
14-
| |
15-
| variable not in all patterns
16-
17-
error[E0408]: variable `_x` is not bound in all patterns
18-
--> $DIR/never_patterns.rs:83:18
19-
|
20-
LL | Ok(_x) | Err(&!) => {}
21-
| -- ^^^^^^^ pattern doesn't bind `_x`
22-
| |
23-
| variable not in all patterns
24-
25-
error[E0408]: variable `_x` is not bound in all patterns
26-
--> $DIR/never_patterns.rs:86:19
27-
|
28-
LL | let (Ok(_x) | Err(&!)) = x;
29-
| -- ^^^^^^^ pattern doesn't bind `_x`
30-
| |
31-
| variable not in all patterns
32-
33-
error[E0408]: variable `_b` is not bound in all patterns
34-
--> $DIR/never_patterns.rs:95:9
4+
LL | let Ok(_x) = res;
5+
| ^^^^^^ pattern `Err(_)` not covered
356
|
36-
LL | Ok(_a) | Err(&(_b, !)) => {}
37-
| ^^^^^^ -- variable not in all patterns
38-
| |
39-
| pattern doesn't bind `_b`
40-
41-
error[E0408]: variable `_a` is not bound in all patterns
42-
--> $DIR/never_patterns.rs:95:18
7+
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
8+
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
9+
= note: the matched value is of type `Result<T, Void>`
10+
help: you might want to use `let else` to handle the variant that isn't matched
4311
|
44-
LL | Ok(_a) | Err(&(_b, !)) => {}
45-
| -- ^^^^^^^^^^^^^ pattern doesn't bind `_a`
46-
| |
47-
| variable not in all patterns
12+
LL | let Ok(_x) = res else { todo!() };
13+
| ++++++++++++++++
4814

49-
error: aborting due to 6 previous errors
15+
error: aborting due to 1 previous error
5016

51-
For more information about this error, try `rustc --explain E0408`.
17+
For more information about this error, try `rustc --explain E0005`.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#![feature(never_patterns)]
2+
#![allow(incomplete_features)]
3+
4+
enum Void {}
5+
6+
fn main() {
7+
let x: Result<bool, &(u32, u32, Void)> = Ok(false);
8+
9+
match x {
10+
Ok(_x) | Err(&!) => {}
11+
}
12+
let (Ok(_x) | Err(&!)) = x;
13+
14+
match x {
15+
Ok(_) => {}
16+
Err(&(_a, _b, !)),
17+
//~^ ERROR: never patterns cannot contain variable bindings
18+
//~| ERROR: never patterns cannot contain variable bindings
19+
}
20+
match x {
21+
Ok(_ok) | Err(&(_a, _b, !)) => {}
22+
//~^ ERROR: never patterns cannot contain variable bindings
23+
//~| ERROR: never patterns cannot contain variable bindings
24+
}
25+
}
26+
27+
fn void(void: Void) {
28+
let (_a | !) = void;
29+
let (! | _a) = void;
30+
let ((_a, _) | (_a, _ | !)) = (true, void);
31+
let (_a | (! | !,)) = (void,);
32+
let ((_a,) | (!,)) = (void,);
33+
34+
let (_a, (! | !)) = (true, void);
35+
//~^ ERROR: never patterns cannot contain variable bindings
36+
let (_a, (_b | !)) = (true, void);
37+
38+
let _a @ ! = void;
39+
//~^ ERROR: never patterns cannot contain variable bindings
40+
let _a @ (_b | !) = void;
41+
let (_a @ (), !) = ((), void);
42+
//~^ ERROR: never patterns cannot contain variable bindings
43+
let (_a |
44+
(_b @ (_, !))) = (true, void);
45+
//~^ ERROR: never patterns cannot contain variable bindings
46+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
error: never patterns cannot contain variable bindings
2+
--> $DIR/bindings.rs:16:15
3+
|
4+
LL | Err(&(_a, _b, !)),
5+
| ^^ help: use a wildcard `_` instead
6+
7+
error: never patterns cannot contain variable bindings
8+
--> $DIR/bindings.rs:16:19
9+
|
10+
LL | Err(&(_a, _b, !)),
11+
| ^^ help: use a wildcard `_` instead
12+
13+
error: never patterns cannot contain variable bindings
14+
--> $DIR/bindings.rs:21:25
15+
|
16+
LL | Ok(_ok) | Err(&(_a, _b, !)) => {}
17+
| ^^ help: use a wildcard `_` instead
18+
19+
error: never patterns cannot contain variable bindings
20+
--> $DIR/bindings.rs:21:29
21+
|
22+
LL | Ok(_ok) | Err(&(_a, _b, !)) => {}
23+
| ^^ help: use a wildcard `_` instead
24+
25+
error: never patterns cannot contain variable bindings
26+
--> $DIR/bindings.rs:34:10
27+
|
28+
LL | let (_a, (! | !)) = (true, void);
29+
| ^^ help: use a wildcard `_` instead
30+
31+
error: never patterns cannot contain variable bindings
32+
--> $DIR/bindings.rs:38:9
33+
|
34+
LL | let _a @ ! = void;
35+
| ^^ help: use a wildcard `_` instead
36+
37+
error: never patterns cannot contain variable bindings
38+
--> $DIR/bindings.rs:41:10
39+
|
40+
LL | let (_a @ (), !) = ((), void);
41+
| ^^ help: use a wildcard `_` instead
42+
43+
error: never patterns cannot contain variable bindings
44+
--> $DIR/bindings.rs:44:14
45+
|
46+
LL | (_b @ (_, !))) = (true, void);
47+
| ^^ help: use a wildcard `_` instead
48+
49+
error: aborting due to 8 previous errors
50+

‎tests/ui/rfcs/rfc-0000-never_patterns/parse.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ fn parse(x: Void) {
7171

7272
let ! = x;
7373
let y @ ! = x;
74+
//~^ ERROR: never patterns cannot contain variable bindings
7475
}
7576

7677
fn foo(!: Void) {}

‎tests/ui/rfcs/rfc-0000-never_patterns/parse.stderr

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ error: top-level or-patterns are not allowed in `let` bindings
2222
LL | let Ok(_) | Err(!) = &res; // Disallowed; see #82048.
2323
| ^^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(Ok(_) | Err(!))`
2424

25+
error: never patterns cannot contain variable bindings
26+
--> $DIR/parse.rs:73:9
27+
|
28+
LL | let y @ ! = x;
29+
| ^ help: use a wildcard `_` instead
30+
2531
error: a guard on a never pattern will never be run
2632
--> $DIR/parse.rs:31:20
2733
|
@@ -40,5 +46,5 @@ error: a guard on a never pattern will never be run
4046
LL | never!() if true,
4147
| ^^^^ help: remove this guard
4248

43-
error: aborting due to 7 previous errors
49+
error: aborting due to 8 previous errors
4450

0 commit comments

Comments
 (0)
Please sign in to comment.