about summary refs log tree commit diff
diff options
context:
space:
mode:
authorxFrednet <xFrednet@gmail.com>2021-04-10 14:45:51 +0200
committerxFrednet <xFrednet@gmail.com>2021-04-14 20:06:26 +0200
commitcbde4f2c67667c717adecf3fac9df84954154fe0 (patch)
tree1c070d7f696cda2f6f14e45576604e09c98d1b3b
parentb1c675f3fc682201cdb28719133285b878e2d157 (diff)
downloadrust-cbde4f2c67667c717adecf3fac9df84954154fe0.tar.gz
rust-cbde4f2c67667c717adecf3fac9df84954154fe0.zip
parent_node_is_if_expr now also recognizes if let as parent if
-rw-r--r--clippy_lints/src/copies.rs7
-rw-r--r--clippy_utils/src/lib.rs30
-rw-r--r--tests/ui/branches_sharing_code/shared_at_bottom.rs14
3 files changed, 44 insertions, 7 deletions
diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs
index 8b503c9a030..dfc79ac365b 100644
--- a/clippy_lints/src/copies.rs
+++ b/clippy_lints/src/copies.rs
@@ -290,6 +290,13 @@ fn lint_same_then_else<'tcx>(
     }
 }
 
+/// The return tuple is structured as follows:
+/// 1. The amount of equal statements from the start
+/// 2. The amount of equal statements from the end
+/// 3. An indication if the block expressions are the same. This will also be true if both are `None`
+///
+/// This function can also trigger the `IF_SAME_THEN_ELSE` in which case it'll return `(0, 0, false)`
+/// to aboard any further processing and avoid duplicate lint triggers.
 fn scan_block_for_eq(cx: &LateContext<'tcx>, blocks: &[&Block<'tcx>]) -> (usize, usize, bool) {
     let mut start_eq = usize::MAX;
     let mut end_eq = usize::MAX;
diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs
index 8e1a2105b96..1ef5d9d32c5 100644
--- a/clippy_utils/src/lib.rs
+++ b/clippy_utils/src/lib.rs
@@ -1212,13 +1212,29 @@ pub fn parent_node_is_if_expr(expr: &Expr<'_>, cx: &LateContext<'_>) -> bool {
     let map = cx.tcx.hir();
     let parent_id = map.get_parent_node(expr.hir_id);
     let parent_node = map.get(parent_id);
-    matches!(
-        parent_node,
-        Node::Expr(Expr {
-            kind: ExprKind::If(_, _, _),
-            ..
-        })
-    )
+    
+    // Check for `if`
+    if_chain! {
+        if let Node::Expr(expr) = parent_node;
+        if let ExprKind::If(_, _, _) = expr.kind;
+        then {
+            return true;
+        }
+    }
+
+    // Check for `if let`
+    if_chain! {
+        if let Node::Arm(arm) = parent_node;
+        let arm_parent_id = map.get_parent_node(arm.hir_id);
+        let arm_parent_node = map.get(arm_parent_id);
+        if let Node::Expr(expr) = arm_parent_node;
+        if let ExprKind::Match(_, _, MatchSource::IfLetDesugar { .. }) = expr.kind;
+        then {
+            return true;
+        }
+    }
+
+    false
 }
 
 // Finds the `#[must_use]` attribute, if any
diff --git a/tests/ui/branches_sharing_code/shared_at_bottom.rs b/tests/ui/branches_sharing_code/shared_at_bottom.rs
index c389c243d44..ce2040bdeb8 100644
--- a/tests/ui/branches_sharing_code/shared_at_bottom.rs
+++ b/tests/ui/branches_sharing_code/shared_at_bottom.rs
@@ -206,4 +206,18 @@ fn fp_test() {
     }
 }
 
+fn fp_if_let_issue7054() {
+    // This shouldn't trigger the lint
+    let string;
+    let _x = if let true = true {
+        ""
+    } else if true {
+        string = "x".to_owned();
+        &string
+    } else {
+        string = "y".to_owned();
+        &string
+    };
+}
+
 fn main() {}