Skip to content

Commit 197867e

Browse files
committed
fix: redundant_closure suggests wrongly with deref overload
1 parent 7546381 commit 197867e

File tree

4 files changed

+126
-5
lines changed

4 files changed

+126
-5
lines changed

clippy_lints/src/eta_reduction.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use rustc_errors::Applicability;
1111
use rustc_hir::{BindingMode, Expr, ExprKind, FnRetTy, GenericArgs, Param, PatKind, QPath, Safety, TyKind};
1212
use rustc_infer::infer::TyCtxtInferExt;
1313
use rustc_lint::{LateContext, LateLintPass};
14+
use rustc_middle::ty::adjustment::Adjust;
1415
use rustc_middle::ty::{
1516
self, Binder, ClosureKind, FnSig, GenericArg, GenericArgKind, List, Region, Ty, TypeVisitableExt, TypeckResults,
1617
};
@@ -153,10 +154,9 @@ fn check_closure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tcx
153154
{
154155
return;
155156
}
156-
let callee_ty_adjusted = typeck
157-
.expr_adjustments(callee)
158-
.last()
159-
.map_or(callee_ty, |a| a.target.peel_refs());
157+
158+
let callee_ty_adjustments = typeck.expr_adjustments(callee);
159+
let callee_ty_adjusted = callee_ty_adjustments.last().map_or(callee_ty, |a| a.target);
160160

161161
let sig = match callee_ty_adjusted.kind() {
162162
ty::FnDef(def, _) => {
@@ -235,7 +235,20 @@ fn check_closure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tcx
235235
},
236236
_ => (),
237237
}
238+
} else if let n_refs =
239+
callee_ty_adjustments
240+
.iter()
241+
.rev()
242+
.fold(0, |acc, adjustment| match adjustment.kind {
243+
Adjust::Deref(Some(_)) => acc + 1,
244+
Adjust::Deref(_) if acc > 0 => acc + 1,
245+
_ => acc,
246+
})
247+
&& n_refs > 0
248+
{
249+
snippet = format!("{}{snippet}", "*".repeat(n_refs));
238250
}
251+
239252
diag.span_suggestion(
240253
expr.span,
241254
"replace the closure with the function itself",

tests/ui/eta.fixed

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,3 +561,48 @@ fn issue_14789() {
561561
std::convert::identity,
562562
);
563563
}
564+
565+
fn issue_15072() {
566+
use std::ops::Deref;
567+
568+
struct Foo;
569+
impl Deref for Foo {
570+
type Target = fn() -> &'static str;
571+
572+
fn deref(&self) -> &Self::Target {
573+
fn hello() -> &'static str {
574+
"Hello, world!"
575+
}
576+
&(hello as fn() -> &'static str)
577+
}
578+
}
579+
580+
fn accepts_fn(f: impl Fn() -> &'static str) {
581+
println!("{}", f());
582+
}
583+
584+
fn some_fn() -> &'static str {
585+
todo!()
586+
}
587+
588+
let f = &Foo;
589+
accepts_fn(**f);
590+
//~^ redundant_closure
591+
592+
let g = &some_fn;
593+
accepts_fn(g);
594+
//~^ redundant_closure
595+
596+
struct Bar(Foo);
597+
impl Deref for Bar {
598+
type Target = Foo;
599+
600+
fn deref(&self) -> &Self::Target {
601+
&self.0
602+
}
603+
}
604+
605+
let b = &Bar(Foo);
606+
accepts_fn(***b);
607+
//~^ redundant_closure
608+
}

tests/ui/eta.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,3 +561,48 @@ fn issue_14789() {
561561
std::convert::identity,
562562
);
563563
}
564+
565+
fn issue_15072() {
566+
use std::ops::Deref;
567+
568+
struct Foo;
569+
impl Deref for Foo {
570+
type Target = fn() -> &'static str;
571+
572+
fn deref(&self) -> &Self::Target {
573+
fn hello() -> &'static str {
574+
"Hello, world!"
575+
}
576+
&(hello as fn() -> &'static str)
577+
}
578+
}
579+
580+
fn accepts_fn(f: impl Fn() -> &'static str) {
581+
println!("{}", f());
582+
}
583+
584+
fn some_fn() -> &'static str {
585+
todo!()
586+
}
587+
588+
let f = &Foo;
589+
accepts_fn(|| f());
590+
//~^ redundant_closure
591+
592+
let g = &some_fn;
593+
accepts_fn(|| g());
594+
//~^ redundant_closure
595+
596+
struct Bar(Foo);
597+
impl Deref for Bar {
598+
type Target = Foo;
599+
600+
fn deref(&self) -> &Self::Target {
601+
&self.0
602+
}
603+
}
604+
605+
let b = &Bar(Foo);
606+
accepts_fn(|| b());
607+
//~^ redundant_closure
608+
}

tests/ui/eta.stderr

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,5 +214,23 @@ error: redundant closure
214214
LL | let _field = bind.or_else(|| get_default()).unwrap();
215215
| ^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `get_default`
216216

217-
error: aborting due to 35 previous errors
217+
error: redundant closure
218+
--> tests/ui/eta.rs:589:16
219+
|
220+
LL | accepts_fn(|| f());
221+
| ^^^^^^ help: replace the closure with the function itself: `**f`
222+
223+
error: redundant closure
224+
--> tests/ui/eta.rs:593:16
225+
|
226+
LL | accepts_fn(|| g());
227+
| ^^^^^^ help: replace the closure with the function itself: `g`
228+
229+
error: redundant closure
230+
--> tests/ui/eta.rs:606:16
231+
|
232+
LL | accepts_fn(|| b());
233+
| ^^^^^^ help: replace the closure with the function itself: `***b`
234+
235+
error: aborting due to 38 previous errors
218236

0 commit comments

Comments
 (0)