about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCameron Steffen <cam.steffen94@gmail.com>2021-07-30 17:14:34 -0500
committerCameron Steffen <cam.steffen94@gmail.com>2021-08-30 20:18:43 -0500
commitdf9a2e0687895731e12f4a2651e8d70acd08872d (patch)
treea9a16047e1707928ee90f6d2f49cc817725972a8
parentdc028f65688da4d56315bab9f6ed6cfa29e4af84 (diff)
downloadrust-df9a2e0687895731e12f4a2651e8d70acd08872d.tar.gz
rust-df9a2e0687895731e12f4a2651e8d70acd08872d.zip
Handle irrufutable or unreachable let-else
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs21
-rw-r--r--src/test/ui/pattern/usefulness/top-level-alternation.rs3
-rw-r--r--src/test/ui/pattern/usefulness/top-level-alternation.stderr30
3 files changed, 41 insertions, 13 deletions
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index 90c451517c0..b34c1e07be7 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -17,7 +17,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_session::lint::builtin::BINDINGS_WITH_VARIANT_NAME;
 use rustc_session::lint::builtin::{IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS};
 use rustc_session::Session;
-use rustc_span::Span;
+use rustc_span::{DesugaringKind, ExpnKind, Span};
 use std::slice;
 
 crate fn check_match(tcx: TyCtxt<'_>, def_id: DefId) {
@@ -381,6 +381,10 @@ fn irrefutable_let_pattern(tcx: TyCtxt<'_>, id: HirId, span: Span) {
     }
 
     let source = let_source(tcx, id);
+    let span = match source {
+        LetSource::LetElse(span) => span,
+        _ => span,
+    };
     tcx.struct_span_lint_hir(IRREFUTABLE_LET_PATTERNS, id, span, |lint| match source {
         LetSource::GenericLet => {
             emit_diag!(lint, "`let`", "`let` is useless", "removing `let`");
@@ -401,6 +405,14 @@ fn irrefutable_let_pattern(tcx: TyCtxt<'_>, id: HirId, span: Span) {
                 "removing the guard and adding a `let` inside the match arm"
             );
         }
+        LetSource::LetElse(..) => {
+            emit_diag!(
+                lint,
+                "`let...else`",
+                "`else` clause is useless",
+                "removing the `else` clause"
+            );
+        }
         LetSource::WhileLet => {
             emit_diag!(
                 lint,
@@ -755,6 +767,7 @@ pub enum LetSource {
     GenericLet,
     IfLet,
     IfLetGuard,
+    LetElse(Span),
     WhileLet,
 }
 
@@ -768,6 +781,12 @@ fn let_source(tcx: TyCtxt<'_>, pat_id: HirId) -> LetSource {
         }) if hir_id == pat_id => {
             return LetSource::IfLetGuard;
         }
+        hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Let(..), span, .. }) => {
+            let expn_data = span.ctxt().outer_expn_data();
+            if let ExpnKind::Desugaring(DesugaringKind::LetElse) = expn_data.kind {
+                return LetSource::LetElse(expn_data.call_site);
+            }
+        }
         _ => {}
     }
     let parent_parent = hir.get_parent_node(parent);
diff --git a/src/test/ui/pattern/usefulness/top-level-alternation.rs b/src/test/ui/pattern/usefulness/top-level-alternation.rs
index 4b47b978930..076de846129 100644
--- a/src/test/ui/pattern/usefulness/top-level-alternation.rs
+++ b/src/test/ui/pattern/usefulness/top-level-alternation.rs
@@ -1,3 +1,5 @@
+#![feature(let_else)]
+
 #![deny(unreachable_patterns)]
 
 fn main() {
@@ -53,4 +55,5 @@ fn main() {
         1..=2 => {}, //~ ERROR unreachable pattern
         _ => {},
     }
+    let (0 | 0) = 0 else { return }; //~ ERROR unreachable pattern
 }
diff --git a/src/test/ui/pattern/usefulness/top-level-alternation.stderr b/src/test/ui/pattern/usefulness/top-level-alternation.stderr
index 76bc4f8d091..dd5936fdcc4 100644
--- a/src/test/ui/pattern/usefulness/top-level-alternation.stderr
+++ b/src/test/ui/pattern/usefulness/top-level-alternation.stderr
@@ -1,68 +1,74 @@
 error: unreachable pattern
-  --> $DIR/top-level-alternation.rs:4:23
+  --> $DIR/top-level-alternation.rs:6:23
    |
 LL |     while let 0..=2 | 1 = 0 {}
    |                       ^
    |
 note: the lint level is defined here
-  --> $DIR/top-level-alternation.rs:1:9
+  --> $DIR/top-level-alternation.rs:3:9
    |
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/top-level-alternation.rs:5:20
+  --> $DIR/top-level-alternation.rs:7:20
    |
 LL |     if let 0..=2 | 1 = 0 {}
    |                    ^
 
 error: unreachable pattern
-  --> $DIR/top-level-alternation.rs:9:15
+  --> $DIR/top-level-alternation.rs:11:15
    |
 LL |             | 0 => {}
    |               ^
 
 error: unreachable pattern
-  --> $DIR/top-level-alternation.rs:14:15
+  --> $DIR/top-level-alternation.rs:16:15
    |
 LL |             | Some(0) => {}
    |               ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/top-level-alternation.rs:19:9
+  --> $DIR/top-level-alternation.rs:21:9
    |
 LL |         (0, 0) => {}
    |         ^^^^^^
 
 error: unreachable pattern
-  --> $DIR/top-level-alternation.rs:39:9
+  --> $DIR/top-level-alternation.rs:41:9
    |
 LL |         _ => {}
    |         ^
 
 error: unreachable pattern
-  --> $DIR/top-level-alternation.rs:43:9
+  --> $DIR/top-level-alternation.rs:45:9
    |
 LL |         Some(_) => {}
    |         ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/top-level-alternation.rs:44:9
+  --> $DIR/top-level-alternation.rs:46:9
    |
 LL |         None => {}
    |         ^^^^
 
 error: unreachable pattern
-  --> $DIR/top-level-alternation.rs:49:9
+  --> $DIR/top-level-alternation.rs:51:9
    |
 LL |         None | Some(_) => {}
    |         ^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/top-level-alternation.rs:53:9
+  --> $DIR/top-level-alternation.rs:55:9
    |
 LL |         1..=2 => {},
    |         ^^^^^
 
-error: aborting due to 10 previous errors
+error: unreachable pattern
+  --> $DIR/top-level-alternation.rs:58:14
+   |
+LL |     let (0 | 0) = 0 else { return };
+   |              ^
+
+error: aborting due to 11 previous errors