From 33bf9e9a54697bcdaba30291f2d4e357ee84777f Mon Sep 17 00:00:00 2001
From: dswij <dswijj@gmail.com>
Date: Wed, 23 Feb 2022 23:04:06 +0800
Subject: [PATCH] `redundant_closure` ignore coerced closure

---
 clippy_lints/src/eta_reduction.rs |  4 +++-
 tests/ui/eta.fixed                | 16 ++++++++++++++--
 tests/ui/eta.rs                   | 12 ++++++++++++
 tests/ui/eta.stderr               | 14 +-------------
 4 files changed, 30 insertions(+), 16 deletions(-)

diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs
index c2e32f1d9a2..1b19868e4c7 100644
--- a/clippy_lints/src/eta_reduction.rs
+++ b/clippy_lints/src/eta_reduction.rs
@@ -3,7 +3,7 @@ use clippy_utils::higher::VecArgs;
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::usage::local_used_after_expr;
-use clippy_utils::{higher, path_to_local, path_to_local_id};
+use clippy_utils::{higher, is_adjusted, path_to_local, path_to_local_id};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::def_id::DefId;
@@ -103,6 +103,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
         let closure_ty = cx.typeck_results().expr_ty(expr);
 
         if_chain!(
+            if !is_adjusted(cx, &body.value);
             if let ExprKind::Call(callee, args) = body.value.kind;
             if let ExprKind::Path(_) = callee.kind;
             if check_inputs(cx, body.params, args);
@@ -144,6 +145,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
         );
 
         if_chain!(
+            if !is_adjusted(cx, &body.value);
             if let ExprKind::MethodCall(path, args, _) = body.value.kind;
             if check_inputs(cx, body.params, args);
             let method_def_id = cx.typeck_results().type_dependent_def_id(body.value.hir_id).unwrap();
diff --git a/tests/ui/eta.fixed b/tests/ui/eta.fixed
index 873ed689a5b..6c2272f4dff 100644
--- a/tests/ui/eta.fixed
+++ b/tests/ui/eta.fixed
@@ -37,7 +37,7 @@ fn main() {
     }
 
     // See #815
-    let e = Some(1u8).map(divergent);
+    let e = Some(1u8).map(|a| divergent(a));
     let e = Some(1u8).map(generic);
     let e = Some(1u8).map(generic);
     // See #515
@@ -233,7 +233,7 @@ fn late_bound_lifetimes() {
     {
     }
     map_str(|s| take_asref_path(s));
-    map_str_to_path(std::convert::AsRef::as_ref);
+    map_str_to_path(|s| s.as_ref());
 }
 
 mod type_param_bound {
@@ -279,3 +279,15 @@ mod bind_by_ref {
         Some(A).map(|ref a| B::from(a));
     }
 }
+
+// #7812 False positive on coerced closure
+fn coerced_closure() {
+    fn function_returning_unit<F: FnMut(i32)>(f: F) {}
+    function_returning_unit(|x| std::process::exit(x));
+
+    fn arr() -> &'static [u8; 0] {
+        &[]
+    }
+    fn slice_fn(_: impl FnOnce() -> &'static [u8]) {}
+    slice_fn(|| arr());
+}
diff --git a/tests/ui/eta.rs b/tests/ui/eta.rs
index 4cb58eec94c..a1a9c0dfbf3 100644
--- a/tests/ui/eta.rs
+++ b/tests/ui/eta.rs
@@ -279,3 +279,15 @@ mod bind_by_ref {
         Some(A).map(|ref a| B::from(a));
     }
 }
+
+// #7812 False positive on coerced closure
+fn coerced_closure() {
+    fn function_returning_unit<F: FnMut(i32)>(f: F) {}
+    function_returning_unit(|x| std::process::exit(x));
+
+    fn arr() -> &'static [u8; 0] {
+        &[]
+    }
+    fn slice_fn(_: impl FnOnce() -> &'static [u8]) {}
+    slice_fn(|| arr());
+}
diff --git a/tests/ui/eta.stderr b/tests/ui/eta.stderr
index d1ae889d6f3..bf2e97e744a 100644
--- a/tests/ui/eta.stderr
+++ b/tests/ui/eta.stderr
@@ -24,12 +24,6 @@ error: redundant closure
 LL |     all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted
    |                          ^^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `below`
 
-error: redundant closure
-  --> $DIR/eta.rs:40:27
-   |
-LL |     let e = Some(1u8).map(|a| divergent(a));
-   |                           ^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `divergent`
-
 error: redundant closure
   --> $DIR/eta.rs:41:27
    |
@@ -122,11 +116,5 @@ error: redundant closure
 LL |         Some(1).map(|n| in_loop(n));
    |                     ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `in_loop`
 
-error: redundant closure
-  --> $DIR/eta.rs:236:21
-   |
-LL |     map_str_to_path(|s| s.as_ref());
-   |                     ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::convert::AsRef::as_ref`
-
-error: aborting due to 21 previous errors
+error: aborting due to 19 previous errors