Skip to content

Commit f50755b

Browse files
committed
fix: redundant_closure suggests wrongly with deref overload
1 parent 19c1c70 commit f50755b

File tree

4 files changed

+91
-5
lines changed

4 files changed

+91
-5
lines changed

clippy_lints/src/eta_reduction.rs

Lines changed: 12 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
};
@@ -147,10 +148,9 @@ fn check_closure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tcx
147148
{
148149
return;
149150
}
150-
let callee_ty_adjusted = typeck
151-
.expr_adjustments(callee)
152-
.last()
153-
.map_or(callee_ty, |a| a.target.peel_refs());
151+
152+
let callee_ty_adjustments = typeck.expr_adjustments(callee);
153+
let callee_ty_adjusted = callee_ty_adjustments.last().map_or(callee_ty, |a| a.target.peel_refs());
154154

155155
let sig = match callee_ty_adjusted.kind() {
156156
ty::FnDef(def, _) => {
@@ -223,7 +223,15 @@ fn check_closure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tcx
223223
},
224224
_ => (),
225225
}
226+
} else if let Some((n_refs, _)) = callee_ty_adjustments
227+
.iter()
228+
.filter(|adjust| matches!(adjust.kind, Adjust::Deref(_)))
229+
.enumerate()
230+
.find(|(_, adjust)| matches!(adjust.kind, Adjust::Deref(Some(_))))
231+
{
232+
snippet = format!("{}{snippet}", "*".repeat(n_refs + 1));
226233
}
234+
227235
diag.span_suggestion(
228236
expr.span,
229237
"replace the closure with the function itself",

tests/ui/eta.fixed

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,3 +543,36 @@ mod issue_13073 {
543543
//~^ redundant_closure
544544
}
545545
}
546+
547+
fn issue_15072() {
548+
use std::ops::Deref;
549+
550+
struct Foo;
551+
552+
impl Deref for Foo {
553+
type Target = fn() -> &'static str;
554+
555+
fn deref(&self) -> &Self::Target {
556+
fn hello() -> &'static str {
557+
"Hello, world!"
558+
}
559+
&(hello as fn() -> &'static str)
560+
}
561+
}
562+
563+
fn accepts_fn(f: impl Fn() -> &'static str) {
564+
println!("{}", f());
565+
}
566+
567+
fn some_fn() -> &'static str {
568+
todo!()
569+
}
570+
571+
let f = &Foo;
572+
accepts_fn(**f);
573+
//~^ redundant_closure
574+
575+
let g = &some_fn;
576+
accepts_fn(g);
577+
//~^ redundant_closure
578+
}

tests/ui/eta.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,3 +543,36 @@ mod issue_13073 {
543543
//~^ redundant_closure
544544
}
545545
}
546+
547+
fn issue_15072() {
548+
use std::ops::Deref;
549+
550+
struct Foo;
551+
552+
impl Deref for Foo {
553+
type Target = fn() -> &'static str;
554+
555+
fn deref(&self) -> &Self::Target {
556+
fn hello() -> &'static str {
557+
"Hello, world!"
558+
}
559+
&(hello as fn() -> &'static str)
560+
}
561+
}
562+
563+
fn accepts_fn(f: impl Fn() -> &'static str) {
564+
println!("{}", f());
565+
}
566+
567+
fn some_fn() -> &'static str {
568+
todo!()
569+
}
570+
571+
let f = &Foo;
572+
accepts_fn(|| f());
573+
//~^ redundant_closure
574+
575+
let g = &some_fn;
576+
accepts_fn(|| g());
577+
//~^ redundant_closure
578+
}

tests/ui/eta.stderr

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,5 +214,17 @@ 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:572: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:576:16
225+
|
226+
LL | accepts_fn(|| g());
227+
| ^^^^^^ help: replace the closure with the function itself: `g`
228+
229+
error: aborting due to 37 previous errors
218230

0 commit comments

Comments
 (0)