about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNadrieril <nadrieril+git@gmail.com>2023-11-27 03:47:49 +0100
committerNadrieril <nadrieril+git@gmail.com>2023-12-03 12:25:46 +0100
commit06a8ed10b627d04c9e91c41064c38745374acc71 (patch)
tree628ff5eae9837097b2949a7f510493dc2a866817
parenta2dcb3a6d9aead3964b3b1cdf814dc7eb9c5d8ed (diff)
downloadrust-06a8ed10b627d04c9e91c41064c38745374acc71.tar.gz
rust-06a8ed10b627d04c9e91c41064c38745374acc71.zip
Disallow guards on never patterns
-rw-r--r--compiler/rustc_ast_lowering/messages.ftl4
-rw-r--r--compiler/rustc_ast_lowering/src/errors.rs8
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs7
-rw-r--r--tests/ui/never_patterns/check.rs3
-rw-r--r--tests/ui/never_patterns/check.stderr41
-rw-r--r--tests/ui/never_patterns/parse.rs3
-rw-r--r--tests/ui/never_patterns/parse.stderr24
7 files changed, 47 insertions, 43 deletions
diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl
index 2a519b418e6..ecbe8cc6aec 100644
--- a/compiler/rustc_ast_lowering/messages.ftl
+++ b/compiler/rustc_ast_lowering/messages.ftl
@@ -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
 
diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs
index 1bcf4a07eb0..c6a4166f537 100644
--- a/compiler/rustc_ast_lowering/src/errors.rs
+++ b/compiler/rustc_ast_lowering/src/errors.rs
@@ -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 {
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 4a32fa7f929..4913f9cd12d 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -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};
@@ -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(),
@@ -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.
diff --git a/tests/ui/never_patterns/check.rs b/tests/ui/never_patterns/check.rs
index 9b02fc7996d..1f55ef11242 100644
--- a/tests/ui/never_patterns/check.rs
+++ b/tests/ui/never_patterns/check.rs
@@ -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 => {}
     }
diff --git a/tests/ui/never_patterns/check.stderr b/tests/ui/never_patterns/check.stderr
index 945812225c4..a25ee1b0a2a 100644
--- a/tests/ui/never_patterns/check.stderr
+++ b/tests/ui/never_patterns/check.stderr
@@ -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`.
diff --git a/tests/ui/never_patterns/parse.rs b/tests/ui/never_patterns/parse.rs
index 850416d723a..1b23e60e0ca 100644
--- a/tests/ui/never_patterns/parse.rs
+++ b/tests/ui/never_patterns/parse.rs
@@ -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> {
@@ -45,6 +47,7 @@ fn parse(x: Void) {
     }
     match x {
         never!() if true,
+        //~^ ERROR guard on a never pattern
     }
     match x {
         never!()
diff --git a/tests/ui/never_patterns/parse.stderr b/tests/ui/never_patterns/parse.stderr
index 7ea33540c5e..e81a13a3967 100644
--- a/tests/ui/never_patterns/parse.stderr
+++ b/tests/ui/never_patterns/parse.stderr
@@ -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