about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/methods/mod.rs18
-rw-r--r--tests/ui/unnecessary_fold.rs7
2 files changed, 25 insertions, 0 deletions
diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs
index 7c15eb677cc..66c94746f5a 100644
--- a/clippy_lints/src/methods/mod.rs
+++ b/clippy_lints/src/methods/mod.rs
@@ -9,6 +9,7 @@
 
 
 use crate::rustc::hir;
+use crate::rustc::hir::{ExprKind, Guard, Node};
 use crate::rustc::hir::def::Def;
 use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, Lint, LintArray, LintContext, LintPass};
 use crate::rustc::ty::{self, Ty};
@@ -1428,6 +1429,23 @@ fn lint_unnecessary_fold(cx: &LateContext<'_, '_>, expr: &hir::Expr, fold_args:
         return;
     }
 
+    // `Iterator::any` cannot be used within a pattern guard
+    // See https://github.com/rust-lang-nursery/rust-clippy/issues/3069
+    if_chain! {
+        if let Some(fold_parent) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(expr.id));
+        if let Node::Expr(fold_parent) = fold_parent;
+        if let ExprKind::Match(_, ref arms, _) = fold_parent.node;
+        if arms.iter().any(|arm| {
+            if let Some(Guard::If(ref guard)) = arm.guard {
+                return guard.id == expr.id;
+            }
+            false
+        });
+        then {
+            return;
+        }
+    }
+
     assert!(fold_args.len() == 3,
         "Expected fold_args to have three entries - the receiver, the initial value and the closure");
 
diff --git a/tests/ui/unnecessary_fold.rs b/tests/ui/unnecessary_fold.rs
index e8d84ecea8c..3b70602d4ad 100644
--- a/tests/ui/unnecessary_fold.rs
+++ b/tests/ui/unnecessary_fold.rs
@@ -45,6 +45,13 @@ fn unnecessary_fold_should_ignore() {
 
     let _ = [(0..2), (0..3)].iter().fold(0, |a, b| a + b.len());
     let _ = [(0..2), (0..3)].iter().fold(1, |a, b| a * b.len());
+
+    // Because `any` takes the iterator as a mutable reference,
+    // it cannot be used in a pattern guard, and we must use `fold`.
+    match 1 {
+        _ if (0..3).fold(false, |acc, x| acc || x > 2) => {}
+        _ => {}
+    }
 }
 
 fn main() {}