about summary refs log tree commit diff
diff options
context:
space:
mode:
authorElliot Bobrow <elliotgreybobrow@gmail.com>2021-12-29 08:52:40 -0800
committerElliot Bobrow <elliotgreybobrow@gmail.com>2021-12-29 09:05:04 -0800
commit828ddbe414d77d61292a72ffb9ade85cd6e72cda (patch)
treed4e182b94283b06fa6b72967d9c58cf3583554c2
parentc1cd64b9c6b29ed2a577fc174a50c76267a966e2 (diff)
downloadrust-828ddbe414d77d61292a72ffb9ade85cd6e72cda.tar.gz
rust-828ddbe414d77d61292a72ffb9ade85cd6e72cda.zip
fix [`redundant_closure`] fp with `Arc`
-rw-r--r--clippy_lints/src/eta_reduction.rs5
-rw-r--r--tests/ui/eta.fixed11
-rw-r--r--tests/ui/eta.rs11
3 files changed, 27 insertions, 0 deletions
diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs
index 5a4b4247104..b22515a3907 100644
--- a/clippy_lints/src/eta_reduction.rs
+++ b/clippy_lints/src/eta_reduction.rs
@@ -1,6 +1,7 @@
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 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::{get_enclosing_loop_or_closure, higher, path_to_local, path_to_local_id};
 use if_chain::if_chain;
@@ -12,6 +13,7 @@ use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
 use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::{self, ClosureKind, Ty, TypeFoldable};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::symbol::sym;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -113,6 +115,9 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
             // A type param function ref like `T::f` is not 'static, however
             // it is if cast like `T::f as fn()`. This seems like a rustc bug.
             if !substs.types().any(|t| matches!(t.kind(), ty::Param(_)));
+            let callee_ty_unadjusted = cx.typeck_results().expr_ty(callee).peel_refs();
+            if !is_type_diagnostic_item(cx, callee_ty_unadjusted, sym::Arc);
+            if !is_type_diagnostic_item(cx, callee_ty_unadjusted, sym::Rc);
             then {
                 span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure", |diag| {
                     if let Some(mut snippet) = snippet_opt(cx, callee.span) {
diff --git a/tests/ui/eta.fixed b/tests/ui/eta.fixed
index 1de79667f55..f938f710688 100644
--- a/tests/ui/eta.fixed
+++ b/tests/ui/eta.fixed
@@ -248,3 +248,14 @@ mod type_param_bound {
         take(X::fun as fn());
     }
 }
+
+// #8073 Don't replace closure with `Arc<F>` or `Rc<F>`
+fn arc_fp() {
+    let rc = std::rc::Rc::new(|| 7);
+    let arc = std::sync::Arc::new(|n| n + 1);
+    let ref_arc = &std::sync::Arc::new(|_| 5);
+
+    true.then(|| rc());
+    (0..5).map(|n| arc(n));
+    Some(4).map(|n| ref_arc(n));
+}
diff --git a/tests/ui/eta.rs b/tests/ui/eta.rs
index 86abd347baa..075bbc74922 100644
--- a/tests/ui/eta.rs
+++ b/tests/ui/eta.rs
@@ -248,3 +248,14 @@ mod type_param_bound {
         take(X::fun as fn());
     }
 }
+
+// #8073 Don't replace closure with `Arc<F>` or `Rc<F>`
+fn arc_fp() {
+    let rc = std::rc::Rc::new(|| 7);
+    let arc = std::sync::Arc::new(|n| n + 1);
+    let ref_arc = &std::sync::Arc::new(|_| 5);
+
+    true.then(|| rc());
+    (0..5).map(|n| arc(n));
+    Some(4).map(|n| ref_arc(n));
+}