Skip to content

Commit 06a8ed1

Browse files
committed
Disallow guards on never patterns
1 parent a2dcb3a commit 06a8ed1

File tree

7 files changed

+47
-43
lines changed

7 files changed

+47
-43
lines changed

compiler/rustc_ast_lowering/messages.ftl

+4
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ ast_lowering_misplaced_impl_trait =
108108
ast_lowering_misplaced_relax_trait_bound =
109109
`?Trait` bounds are only permitted at the point where a type parameter is declared
110110
111+
ast_lowering_never_pattern_with_guard =
112+
a guard on a never pattern will never be run
113+
.suggestion = remove this guard
114+
111115
ast_lowering_not_supported_for_lifetime_binder_async_closure =
112116
`for<...>` binders on `async` closures are not currently supported
113117

compiler/rustc_ast_lowering/src/errors.rs

+8
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,14 @@ pub struct MatchArmWithNoBody {
349349
pub suggestion: Span,
350350
}
351351

352+
#[derive(Diagnostic)]
353+
#[diag(ast_lowering_never_pattern_with_guard)]
354+
pub struct NeverPatternWithGuard {
355+
#[primary_span]
356+
#[suggestion(code = "", applicability = "maybe-incorrect")]
357+
pub span: Span,
358+
}
359+
352360
#[derive(Diagnostic, Clone, Copy)]
353361
#[diag(ast_lowering_arbitrary_expression_in_pattern)]
354362
pub struct ArbitraryExpressionInPattern {

compiler/rustc_ast_lowering/src/expr.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use super::errors::{
22
AsyncCoroutinesNotSupported, AsyncNonMoveClosureNotSupported, AwaitOnlyInAsyncFnAndBlocks,
33
BaseExpressionDoubleDot, ClosureCannotBeStatic, CoroutineTooManyParameters,
44
FunctionalRecordUpdateDestructuringAssignment, InclusiveRangeWithNoEnd, MatchArmWithNoBody,
5-
NotSupportedForLifetimeBinderAsyncClosure, UnderscoreExprLhsAssign,
5+
NeverPatternWithGuard, NotSupportedForLifetimeBinderAsyncClosure, UnderscoreExprLhsAssign,
66
};
77
use super::ResolverAstLoweringExt;
88
use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs};
@@ -550,7 +550,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
550550

551551
fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> {
552552
let pat = self.lower_pat(&arm.pat);
553-
let guard = arm.guard.as_ref().map(|cond| {
553+
let mut guard = arm.guard.as_ref().map(|cond| {
554554
if let ExprKind::Let(pat, scrutinee, span, is_recovered) = &cond.kind {
555555
hir::Guard::IfLet(self.arena.alloc(hir::Let {
556556
hir_id: self.next_id(),
@@ -575,6 +575,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
575575
self.tcx
576576
.sess
577577
.emit_err(MatchArmWithNoBody { span, suggestion: span.shrink_to_hi() });
578+
} else if let Some(g) = &arm.guard {
579+
self.tcx.sess.emit_err(NeverPatternWithGuard { span: g.span });
580+
guard = None;
578581
}
579582

580583
// An arm without a body, meant for never patterns.

tests/ui/never_patterns/check.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,11 @@ fn no_arms_or_guards(x: Void) {
1515
None => {}
1616
}
1717
match None::<Void> {
18-
//~^ ERROR non-exhaustive
1918
Some(!) if true,
19+
//~^ ERROR guard on a never pattern
2020
None => {}
2121
}
2222
match None::<Void> {
23-
//~^ ERROR non-exhaustive
2423
Some(!) if true => {}
2524
None => {}
2625
}

tests/ui/never_patterns/check.stderr

+5-36
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,8 @@
1-
error[E0004]: non-exhaustive patterns: `Some(_)` not covered
2-
--> $DIR/check.rs:17:11
3-
|
4-
LL | match None::<Void> {
5-
| ^^^^^^^^^^^^ pattern `Some(_)` not covered
6-
|
7-
note: `Option<Void>` defined here
8-
--> $SRC_DIR/core/src/option.rs:LL:COL
9-
::: $SRC_DIR/core/src/option.rs:LL:COL
10-
|
11-
= note: not covered
12-
= note: the matched value is of type `Option<Void>`
13-
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
14-
|
15-
LL ~ None => {},
16-
LL + Some(_) => todo!()
17-
|
18-
19-
error[E0004]: non-exhaustive patterns: `Some(_)` not covered
20-
--> $DIR/check.rs:22:11
21-
|
22-
LL | match None::<Void> {
23-
| ^^^^^^^^^^^^ pattern `Some(_)` not covered
24-
|
25-
note: `Option<Void>` defined here
26-
--> $SRC_DIR/core/src/option.rs:LL:COL
27-
::: $SRC_DIR/core/src/option.rs:LL:COL
28-
|
29-
= note: not covered
30-
= note: the matched value is of type `Option<Void>`
31-
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
32-
|
33-
LL ~ None => {},
34-
LL + Some(_) => todo!()
1+
error: a guard on a never pattern will never be run
2+
--> $DIR/check.rs:18:20
353
|
4+
LL | Some(!) if true,
5+
| ^^^^ help: remove this guard
366

37-
error: aborting due to 2 previous errors
7+
error: aborting due to 1 previous error
388

39-
For more information about this error, try `rustc --explain E0004`.

tests/ui/never_patterns/parse.rs

+3
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,12 @@ fn parse(x: Void) {
3030
match None::<Void> {
3131
Some(!) if true
3232
//~^ ERROR expected `,` following `match` arm
33+
//~| ERROR guard on a never pattern
3334
None => {}
3435
}
3536
match None::<Void> {
3637
Some(!) if true,
38+
//~^ ERROR guard on a never pattern
3739
None => {}
3840
}
3941
match None::<Void> {
@@ -45,6 +47,7 @@ fn parse(x: Void) {
4547
}
4648
match x {
4749
never!() if true,
50+
//~^ ERROR guard on a never pattern
4851
}
4952
match x {
5053
never!()

tests/ui/never_patterns/parse.stderr

+21-3
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,34 @@ LL | Some(!) if true
1111
| ^ help: missing a comma here to end this `match` arm: `,`
1212

1313
error: expected one of `,`, `=>`, `if`, `|`, or `}`, found `<=`
14-
--> $DIR/parse.rs:40:17
14+
--> $DIR/parse.rs:42:17
1515
|
1616
LL | Some(!) <=
1717
| ^^ expected one of `,`, `=>`, `if`, `|`, or `}`
1818

1919
error: top-level or-patterns are not allowed in `let` bindings
20-
--> $DIR/parse.rs:64:9
20+
--> $DIR/parse.rs:67:9
2121
|
2222
LL | let Ok(_) | Err(!) = &res; // Disallowed; see #82048.
2323
| ^^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(Ok(_) | Err(!))`
2424

25-
error: aborting due to 4 previous errors
25+
error: a guard on a never pattern will never be run
26+
--> $DIR/parse.rs:31:20
27+
|
28+
LL | Some(!) if true
29+
| ^^^^ help: remove this guard
30+
31+
error: a guard on a never pattern will never be run
32+
--> $DIR/parse.rs:37:20
33+
|
34+
LL | Some(!) if true,
35+
| ^^^^ help: remove this guard
36+
37+
error: a guard on a never pattern will never be run
38+
--> $DIR/parse.rs:49:21
39+
|
40+
LL | never!() if true,
41+
| ^^^^ help: remove this guard
42+
43+
error: aborting due to 7 previous errors
2644

0 commit comments

Comments
 (0)