about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-02-14 15:55:12 +0000
committerbors <bors@rust-lang.org>2021-02-14 15:55:12 +0000
commit2f19f5f0d71833d450f8290bb154c3572ac58d9d (patch)
tree63b4874525bd49fbb9672ce0d9a110554dec9dde
parent9c3b43efddcdfd848a5d51948d3de6046cb208d2 (diff)
parent12025506d61bc05a10455ae96a623515663c09fe (diff)
downloadrust-2f19f5f0d71833d450f8290bb154c3572ac58d9d.tar.gz
rust-2f19f5f0d71833d450f8290bb154c3572ac58d9d.zip
Auto merge of #6741 - ThibsG:BlockInIfConditions1141, r=flip1995
Do not lint when the closure is called using an iterator

Fix FP when the closure is used in an iterator for `blocks_in_if_conditions` lint

FIxes: #1141

changelog: none
-rw-r--r--clippy_lints/src/blocks_in_if_conditions.rs18
-rw-r--r--tests/ui/blocks_in_if_conditions_closure.rs11
2 files changed, 27 insertions, 2 deletions
diff --git a/clippy_lints/src/blocks_in_if_conditions.rs b/clippy_lints/src/blocks_in_if_conditions.rs
index 4efca10bcdf..b53f80fd8bc 100644
--- a/clippy_lints/src/blocks_in_if_conditions.rs
+++ b/clippy_lints/src/blocks_in_if_conditions.rs
@@ -1,4 +1,8 @@
-use crate::utils::{differing_macro_contexts, snippet_block_with_applicability, span_lint, span_lint_and_sugg};
+use crate::utils::{
+    differing_macro_contexts, get_parent_expr, get_trait_def_id, implements_trait, paths,
+    snippet_block_with_applicability, span_lint, span_lint_and_sugg,
+};
+use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
 use rustc_hir::{BlockCheckMode, Expr, ExprKind};
@@ -52,6 +56,18 @@ impl<'a, 'tcx> Visitor<'tcx> for ExVisitor<'a, 'tcx> {
 
     fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
         if let ExprKind::Closure(_, _, eid, _, _) = expr.kind {
+            // do not lint if the closure is called using an iterator (see #1141)
+            if_chain! {
+                if let Some(parent) = get_parent_expr(self.cx, expr);
+                if let ExprKind::MethodCall(_, _, args, _) = parent.kind;
+                let caller = self.cx.typeck_results().expr_ty(&args[0]);
+                if let Some(iter_id) = get_trait_def_id(self.cx, &paths::ITERATOR);
+                if implements_trait(self.cx, caller, iter_id, &[]);
+                then {
+                    return;
+                }
+            }
+
             let body = self.cx.tcx.hir().body(eid);
             let ex = &body.value;
             if matches!(ex.kind, ExprKind::Block(_, _)) && !body.value.span.from_expansion() {
diff --git a/tests/ui/blocks_in_if_conditions_closure.rs b/tests/ui/blocks_in_if_conditions_closure.rs
index acbabfa20d7..2856943b9be 100644
--- a/tests/ui/blocks_in_if_conditions_closure.rs
+++ b/tests/ui/blocks_in_if_conditions_closure.rs
@@ -44,4 +44,13 @@ fn macro_in_closure() {
     }
 }
 
-fn main() {}
+#[rustfmt::skip]
+fn main() {
+    let mut range = 0..10;
+    range.all(|i| {i < 10} );
+
+    let v = vec![1, 2, 3];
+    if v.into_iter().any(|x| {x == 4}) {
+        println!("contains 4!");
+    }
+}