Skip to content

Commit 0b598b6

Browse files
committed
Auto merge of rust-lang#12865 - J-ZhengLi:issue12853, r=y21
fix [`redundant_closure`] suggesting incorrect code with `F: Fn()` fixes: rust-lang#12853 --- changelog: fix [`redundant_closure`] suggesting incorrect code with `F: Fn()`
2 parents e7efe43 + db30f6c commit 0b598b6

File tree

4 files changed

+54
-9
lines changed

4 files changed

+54
-9
lines changed

clippy_lints/src/eta_reduction.rs

+19-8
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
123123
ExprKind::Path(QPath::Resolved(..) | QPath::TypeRelative(..))
124124
) =>
125125
{
126-
let callee_ty = typeck.expr_ty(callee).peel_refs();
126+
let callee_ty_raw = typeck.expr_ty(callee);
127+
let callee_ty = callee_ty_raw.peel_refs();
127128
if matches!(type_diagnostic_name(cx, callee_ty), Some(sym::Arc | sym::Rc))
128129
|| !check_inputs(typeck, body.params, None, args)
129130
{
@@ -170,15 +171,25 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
170171
{
171172
span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure", |diag| {
172173
if let Some(mut snippet) = snippet_opt(cx, callee.span) {
173-
if let Ok((ClosureKind::FnMut, _)) = cx.tcx.infer_ctxt().build().type_implements_fn_trait(
174-
cx.param_env,
175-
Binder::bind_with_vars(callee_ty_adjusted, List::empty()),
176-
ty::PredicatePolarity::Positive,
177-
) && path_to_local(callee).map_or(false, |l| {
174+
if path_to_local(callee).map_or(false, |l| {
175+
// FIXME: Do we really need this `local_used_in` check?
176+
// Isn't it checking something like... `callee(callee)`?
177+
// If somehow this check is needed, add some test for it,
178+
// 'cuz currently nothing changes after deleting this check.
178179
local_used_in(cx, l, args) || local_used_after_expr(cx, l, expr)
179180
}) {
180-
// Mutable closure is used after current expr; we cannot consume it.
181-
snippet = format!("&mut {snippet}");
181+
match cx.tcx.infer_ctxt().build().type_implements_fn_trait(
182+
cx.param_env,
183+
Binder::bind_with_vars(callee_ty_adjusted, List::empty()),
184+
ty::PredicatePolarity::Positive,
185+
) {
186+
// Mutable closure is used after current expr; we cannot consume it.
187+
Ok((ClosureKind::FnMut, _)) => snippet = format!("&mut {snippet}"),
188+
Ok((ClosureKind::Fn, _)) if !callee_ty_raw.is_ref() => {
189+
snippet = format!("&{snippet}");
190+
},
191+
_ => (),
192+
}
182193
}
183194
diag.span_suggestion(
184195
expr.span,

tests/ui/eta.fixed

+11
Original file line numberDiff line numberDiff line change
@@ -471,3 +471,14 @@ mod issue_10854 {
471471
}
472472
}
473473
}
474+
475+
mod issue_12853 {
476+
fn f_by_value<F: Fn(u32)>(f: F) {
477+
let x = Box::new(|| None.map(&f));
478+
x();
479+
}
480+
fn f_by_ref<F: Fn(u32)>(f: &F) {
481+
let x = Box::new(|| None.map(f));
482+
x();
483+
}
484+
}

tests/ui/eta.rs

+11
Original file line numberDiff line numberDiff line change
@@ -471,3 +471,14 @@ mod issue_10854 {
471471
}
472472
}
473473
}
474+
475+
mod issue_12853 {
476+
fn f_by_value<F: Fn(u32)>(f: F) {
477+
let x = Box::new(|| None.map(|x| f(x)));
478+
x();
479+
}
480+
fn f_by_ref<F: Fn(u32)>(f: &F) {
481+
let x = Box::new(|| None.map(|x| f(x)));
482+
x();
483+
}
484+
}

tests/ui/eta.stderr

+13-1
Original file line numberDiff line numberDiff line change
@@ -190,5 +190,17 @@ error: redundant closure
190190
LL | test.map(|t| t.method())
191191
| ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `crate::issue_10854::d::Test::method`
192192

193-
error: aborting due to 31 previous errors
193+
error: redundant closure
194+
--> tests/ui/eta.rs:477:38
195+
|
196+
LL | let x = Box::new(|| None.map(|x| f(x)));
197+
| ^^^^^^^^ help: replace the closure with the function itself: `&f`
198+
199+
error: redundant closure
200+
--> tests/ui/eta.rs:481:38
201+
|
202+
LL | let x = Box::new(|| None.map(|x| f(x)));
203+
| ^^^^^^^^ help: replace the closure with the function itself: `f`
204+
205+
error: aborting due to 33 previous errors
194206

0 commit comments

Comments
 (0)