From fd3e966bdded5d556d01f1db5c3d6a78539661f8 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Fri, 26 Jan 2024 00:23:13 +0100 Subject: [PATCH] avoid linting on `#[track_caller]` functions in `redundant_closure` --- clippy_lints/src/eta_reduction.rs | 14 +++++++++++--- tests/ui/eta.fixed | 17 +++++++++++++++++ tests/ui/eta.rs | 17 +++++++++++++++++ tests/ui/eta.stderr | 2 +- 4 files changed, 46 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 450cee4007c72..1ea5b78980589 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 32c7499bf73f6..3aeb4dae30b26 100644 --- a/tests/ui/eta.fixed +++ b/tests/ui/eta.fixed @@ -346,6 +346,23 @@ fn angle_brackets_and_args() { dyn_opt.map(::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 25b7431ba8cd7..b9b3303b371de 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 951e4ac749c25..7c4d2d7093edc 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: `::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`