about summary refs log tree commit diff
diff options
context:
space:
mode:
authorYuki Okushi <huyuumi.dev@gmail.com>2020-12-17 11:43:55 +0900
committerGitHub <noreply@github.com>2020-12-17 11:43:55 +0900
commit286e492343239c7dc90fa1b44316ef5d8be6aad5 (patch)
tree508d26106aa85d13cbc00a375ce80517641c34b9
parent39aca5ff9f5317fa1a66eb71772219575e05ba0f (diff)
parent93c6135c153cdb67a7c39c671d85a76576a081b6 (diff)
downloadrust-286e492343239c7dc90fa1b44316ef5d8be6aad5.tar.gz
rust-286e492343239c7dc90fa1b44316ef5d8be6aad5.zip
Rollup merge of #79051 - LeSeulArtichaut:if-let-guard, r=matthewjasper
Implement if-let match guards

Implements rust-lang/rfcs#2294 (tracking issue: #51114).

I probably should do a few more things before this can be merged:
- [x] Add tests (added basic tests, more advanced tests could be done in the future?)
- [x] Add lint for exhaustive if-let guard (comparable to normal if-let statements)
- [x] Fix clippy

However since this is a nightly feature maybe it's fine to land this and do those steps in follow-up PRs.

Thanks a lot `@matthewjasper` :heart: for helping me with lowering to MIR! Would you be interested in reviewing this?
r? `@ghost` for now
-rw-r--r--clippy_lints/src/shadow.rs4
-rw-r--r--clippy_lints/src/utils/author.rs13
-rw-r--r--clippy_lints/src/utils/hir_utils.rs4
-rw-r--r--clippy_lints/src/utils/inspector.rs5
4 files changed, 25 insertions, 1 deletions
diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs
index 225fe58906f..f8396592678 100644
--- a/clippy_lints/src/shadow.rs
+++ b/clippy_lints/src/shadow.rs
@@ -342,6 +342,10 @@ fn check_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, bindings: &mut
                 if let Some(ref guard) = arm.guard {
                     match guard {
                         Guard::If(if_expr) => check_expr(cx, if_expr, bindings),
+                        Guard::IfLet(guard_pat, guard_expr) => {
+                            check_pat(cx, guard_pat, Some(*guard_expr), guard_pat.span, bindings);
+                            check_expr(cx, guard_expr, bindings);
+                        },
                     }
                 }
                 check_expr(cx, &arm.body, bindings);
diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs
index 7250de3a41c..4249dbb4e65 100644
--- a/clippy_lints/src/utils/author.rs
+++ b/clippy_lints/src/utils/author.rs
@@ -372,6 +372,18 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
                                 self.current = if_expr_pat;
                                 self.visit_expr(if_expr);
                             },
+                            hir::Guard::IfLet(ref if_let_pat, ref if_let_expr) => {
+                                let if_let_pat_pat = self.next("pat");
+                                let if_let_expr_pat = self.next("expr");
+                                println!(
+                                    "    if let Guard::IfLet(ref {}, ref {}) = {};",
+                                    if_let_pat_pat, if_let_expr_pat, guard_pat
+                                );
+                                self.current = if_let_expr_pat;
+                                self.visit_expr(if_let_expr);
+                                self.current = if_let_pat_pat;
+                                self.visit_pat(if_let_pat);
+                            },
                         }
                     }
                     self.current = format!("{}[{}].pat", arms_pat, i);
@@ -730,6 +742,7 @@ fn desugaring_name(des: hir::MatchSource) -> String {
             "MatchSource::IfLetDesugar {{ contains_else_clause: {} }}",
             contains_else_clause
         ),
+        hir::MatchSource::IfLetGuardDesugar => "MatchSource::IfLetGuardDesugar".to_string(),
         hir::MatchSource::IfDesugar { contains_else_clause } => format!(
             "MatchSource::IfDesugar {{ contains_else_clause: {} }}",
             contains_else_clause
diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs
index d942d4e12b1..a8fbb2ffaf0 100644
--- a/clippy_lints/src/utils/hir_utils.rs
+++ b/clippy_lints/src/utils/hir_utils.rs
@@ -169,6 +169,8 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> {
     fn eq_guard(&mut self, left: &Guard<'_>, right: &Guard<'_>) -> bool {
         match (left, right) {
             (Guard::If(l), Guard::If(r)) => self.eq_expr(l, r),
+            (Guard::IfLet(lp, le), Guard::IfLet(rp, re)) => self.eq_pat(lp, rp) && self.eq_expr(le, re),
+            _ => false,
         }
     }
 
@@ -669,7 +671,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
 
     pub fn hash_guard(&mut self, g: &Guard<'_>) {
         match g {
-            Guard::If(ref expr) => {
+            Guard::If(ref expr) | Guard::IfLet(_, ref expr) => {
                 self.hash_expr(expr);
             },
         }
diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs
index 323d8745538..5d946e4bd49 100644
--- a/clippy_lints/src/utils/inspector.rs
+++ b/clippy_lints/src/utils/inspector.rs
@@ -560,5 +560,10 @@ fn print_guard(cx: &LateContext<'_>, guard: &hir::Guard<'_>, indent: usize) {
             println!("{}If", ind);
             print_expr(cx, expr, indent + 1);
         },
+        hir::Guard::IfLet(pat, expr) => {
+            println!("{}IfLet", ind);
+            print_pat(cx, pat, indent + 1);
+            print_expr(cx, expr, indent + 1);
+        },
     }
 }