Skip to content

Commit

Permalink
Disallow guards on never patterns
Browse files Browse the repository at this point in the history
  • Loading branch information
Nadrieril committed Dec 3, 2023
1 parent a2dcb3a commit 06a8ed1
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 43 deletions.
4 changes: 4 additions & 0 deletions compiler/rustc_ast_lowering/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ ast_lowering_misplaced_impl_trait =
ast_lowering_misplaced_relax_trait_bound =
`?Trait` bounds are only permitted at the point where a type parameter is declared
ast_lowering_never_pattern_with_guard =
a guard on a never pattern will never be run
.suggestion = remove this guard
ast_lowering_not_supported_for_lifetime_binder_async_closure =
`for<...>` binders on `async` closures are not currently supported
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_ast_lowering/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,14 @@ pub struct MatchArmWithNoBody {
pub suggestion: Span,
}

#[derive(Diagnostic)]
#[diag(ast_lowering_never_pattern_with_guard)]
pub struct NeverPatternWithGuard {
#[primary_span]
#[suggestion(code = "", applicability = "maybe-incorrect")]
pub span: Span,
}

#[derive(Diagnostic, Clone, Copy)]
#[diag(ast_lowering_arbitrary_expression_in_pattern)]
pub struct ArbitraryExpressionInPattern {
Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use super::errors::{
AsyncCoroutinesNotSupported, AsyncNonMoveClosureNotSupported, AwaitOnlyInAsyncFnAndBlocks,
BaseExpressionDoubleDot, ClosureCannotBeStatic, CoroutineTooManyParameters,
FunctionalRecordUpdateDestructuringAssignment, InclusiveRangeWithNoEnd, MatchArmWithNoBody,
NotSupportedForLifetimeBinderAsyncClosure, UnderscoreExprLhsAssign,
NeverPatternWithGuard, NotSupportedForLifetimeBinderAsyncClosure, UnderscoreExprLhsAssign,
};
use super::ResolverAstLoweringExt;
use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs};
Expand Down Expand Up @@ -550,7 +550,7 @@ impl<'hir> LoweringContext<'_, 'hir> {

fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> {
let pat = self.lower_pat(&arm.pat);
let guard = arm.guard.as_ref().map(|cond| {
let mut guard = arm.guard.as_ref().map(|cond| {
if let ExprKind::Let(pat, scrutinee, span, is_recovered) = &cond.kind {
hir::Guard::IfLet(self.arena.alloc(hir::Let {
hir_id: self.next_id(),
Expand All @@ -575,6 +575,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.tcx
.sess
.emit_err(MatchArmWithNoBody { span, suggestion: span.shrink_to_hi() });
} else if let Some(g) = &arm.guard {
self.tcx.sess.emit_err(NeverPatternWithGuard { span: g.span });
guard = None;
}

// An arm without a body, meant for never patterns.
Expand Down
3 changes: 1 addition & 2 deletions tests/ui/never_patterns/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,11 @@ fn no_arms_or_guards(x: Void) {
None => {}
}
match None::<Void> {
//~^ ERROR non-exhaustive
Some(!) if true,
//~^ ERROR guard on a never pattern
None => {}
}
match None::<Void> {
//~^ ERROR non-exhaustive
Some(!) if true => {}
None => {}
}
Expand Down
41 changes: 5 additions & 36 deletions tests/ui/never_patterns/check.stderr
Original file line number Diff line number Diff line change
@@ -1,39 +1,8 @@
error[E0004]: non-exhaustive patterns: `Some(_)` not covered
--> $DIR/check.rs:17:11
|
LL | match None::<Void> {
| ^^^^^^^^^^^^ pattern `Some(_)` not covered
|
note: `Option<Void>` defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
::: $SRC_DIR/core/src/option.rs:LL:COL
|
= note: not covered
= note: the matched value is of type `Option<Void>`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL ~ None => {},
LL + Some(_) => todo!()
|

error[E0004]: non-exhaustive patterns: `Some(_)` not covered
--> $DIR/check.rs:22:11
|
LL | match None::<Void> {
| ^^^^^^^^^^^^ pattern `Some(_)` not covered
|
note: `Option<Void>` defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
::: $SRC_DIR/core/src/option.rs:LL:COL
|
= note: not covered
= note: the matched value is of type `Option<Void>`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL ~ None => {},
LL + Some(_) => todo!()
error: a guard on a never pattern will never be run
--> $DIR/check.rs:18:20
|
LL | Some(!) if true,
| ^^^^ help: remove this guard

error: aborting due to 2 previous errors
error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0004`.
3 changes: 3 additions & 0 deletions tests/ui/never_patterns/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@ fn parse(x: Void) {
match None::<Void> {
Some(!) if true
//~^ ERROR expected `,` following `match` arm
//~| ERROR guard on a never pattern
None => {}
}
match None::<Void> {
Some(!) if true,
//~^ ERROR guard on a never pattern
None => {}
}
match None::<Void> {
Expand All @@ -45,6 +47,7 @@ fn parse(x: Void) {
}
match x {
never!() if true,
//~^ ERROR guard on a never pattern
}
match x {
never!()
Expand Down
24 changes: 21 additions & 3 deletions tests/ui/never_patterns/parse.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,34 @@ LL | Some(!) if true
| ^ help: missing a comma here to end this `match` arm: `,`

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

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

error: aborting due to 4 previous errors
error: a guard on a never pattern will never be run
--> $DIR/parse.rs:31:20
|
LL | Some(!) if true
| ^^^^ help: remove this guard

error: a guard on a never pattern will never be run
--> $DIR/parse.rs:37:20
|
LL | Some(!) if true,
| ^^^^ help: remove this guard

error: a guard on a never pattern will never be run
--> $DIR/parse.rs:49:21
|
LL | never!() if true,
| ^^^^ help: remove this guard

error: aborting due to 7 previous errors

0 comments on commit 06a8ed1

Please sign in to comment.