about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-01-26 05:38:39 +0000
committerbors <bors@rust-lang.org>2024-01-26 05:38:39 +0000
commited74c22f33da446eb91d2069b3fdc8e3d93bff16 (patch)
tree30d10af9c09b0adc285fb6214babfb3063d89d53
parent66c29b973b3b10278bd39f4e26b08522a379c2c9 (diff)
parentfd3e966bdded5d556d01f1db5c3d6a78539661f8 (diff)
downloadrust-ed74c22f33da446eb91d2069b3fdc8e3d93bff16.tar.gz
rust-ed74c22f33da446eb91d2069b3fdc8e3d93bff16.zip
Auto merge of #12202 - y21:issue12199, r=Jarcho
Avoid linting redundant closure when callee is marked `#[track_caller]`

Fixes #12199

Not sure if there's a nicer way to detect functions marked `#[track_caller]` other than by just looking at its attributes 🤔

changelog: [`redundant_closure`]: [`redundant_closure_for_method_calls`]: avoid linting closures where the function being called is marked `#[track_caller]`
-rw-r--r--clippy_lints/src/eta_reduction.rs14
-rw-r--r--tests/ui/eta.fixed17
-rw-r--r--tests/ui/eta.rs17
-rw-r--r--tests/ui/eta.stderr2
4 files changed, 46 insertions, 4 deletions
diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs
index 450cee4007c..1ea5b789805 100644
--- a/clippy_lints/src/eta_reduction.rs
+++ b/clippy_lints/src/eta_reduction.rs
@@ -21,8 +21,8 @@ use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
 declare_clippy_lint! {
     /// ### What it does
     /// Checks for closures which just call another function where
-    /// the function can be called directly. `unsafe` functions or calls where types
-    /// get adjusted are ignored.
+    /// the function can be called directly. `unsafe` functions, calls where types
+    /// get adjusted or where the callee is marked `#[track_caller]` are ignored.
     ///
     /// ### Why is this bad?
     /// Needlessly creating a closure adds code for no benefit
@@ -136,7 +136,14 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
                     .map_or(callee_ty, |a| a.target.peel_refs());
 
                 let sig = match callee_ty_adjusted.kind() {
-                    ty::FnDef(def, _) => cx.tcx.fn_sig(def).skip_binder().skip_binder(),
+                    ty::FnDef(def, _) => {
+                        // Rewriting `x(|| f())` to `x(f)` where f is marked `#[track_caller]` moves the `Location`
+                        if cx.tcx.has_attr(*def, sym::track_caller) {
+                            return;
+                        }
+
+                        cx.tcx.fn_sig(def).skip_binder().skip_binder()
+                    },
                     ty::FnPtr(sig) => sig.skip_binder(),
                     ty::Closure(_, subs) => cx
                         .tcx
@@ -186,6 +193,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
             },
             ExprKind::MethodCall(path, self_, args, _) if check_inputs(typeck, body.params, Some(self_), args) => {
                 if let Some(method_def_id) = typeck.type_dependent_def_id(body.value.hir_id)
+                    && !cx.tcx.has_attr(method_def_id, sym::track_caller)
                     && check_sig(cx, closure, cx.tcx.fn_sig(method_def_id).skip_binder().skip_binder())
                 {
                     span_lint_and_then(
diff --git a/tests/ui/eta.fixed b/tests/ui/eta.fixed
index 32c7499bf73..3aeb4dae30b 100644
--- a/tests/ui/eta.fixed
+++ b/tests/ui/eta.fixed
@@ -346,6 +346,23 @@ fn angle_brackets_and_args() {
     dyn_opt.map(<dyn TestTrait>::method_on_dyn);
 }
 
+// https://github.com/rust-lang/rust-clippy/issues/12199
+fn track_caller_fp() {
+    struct S;
+    impl S {
+        #[track_caller]
+        fn add_location(self) {}
+    }
+
+    #[track_caller]
+    fn add_location() {}
+
+    fn foo(_: fn()) {}
+    fn foo2(_: fn(S)) {}
+    foo(|| add_location());
+    foo2(|s| s.add_location());
+}
+
 fn _late_bound_to_early_bound_regions() {
     struct Foo<'a>(&'a u32);
     impl<'a> Foo<'a> {
diff --git a/tests/ui/eta.rs b/tests/ui/eta.rs
index 25b7431ba8c..b9b3303b371 100644
--- a/tests/ui/eta.rs
+++ b/tests/ui/eta.rs
@@ -346,6 +346,23 @@ fn angle_brackets_and_args() {
     dyn_opt.map(|d| d.method_on_dyn());
 }
 
+// https://github.com/rust-lang/rust-clippy/issues/12199
+fn track_caller_fp() {
+    struct S;
+    impl S {
+        #[track_caller]
+        fn add_location(self) {}
+    }
+
+    #[track_caller]
+    fn add_location() {}
+
+    fn foo(_: fn()) {}
+    fn foo2(_: fn(S)) {}
+    foo(|| add_location());
+    foo2(|s| s.add_location());
+}
+
 fn _late_bound_to_early_bound_regions() {
     struct Foo<'a>(&'a u32);
     impl<'a> Foo<'a> {
diff --git a/tests/ui/eta.stderr b/tests/ui/eta.stderr
index 951e4ac749c..7c4d2d7093e 100644
--- a/tests/ui/eta.stderr
+++ b/tests/ui/eta.stderr
@@ -161,7 +161,7 @@ LL |     dyn_opt.map(|d| d.method_on_dyn());
    |                 ^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `<dyn TestTrait>::method_on_dyn`
 
 error: redundant closure
-  --> $DIR/eta.rs:389:19
+  --> $DIR/eta.rs:406:19
    |
 LL |     let _ = f(&0, |x, y| f2(x, y));
    |                   ^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `f2`