fix: redundant_closure_call lint for closures with block (#15144)

Fixes rust-lang/rust-clippy#9583

When a closure with no parameters is called immediately after being
defined, clippy can now suggest replacing the entire expression with
just the closure's body.

----

changelog: [`redundant_closure_call`]: add fixes for closures with block
This commit is contained in:
llogiq 2025-07-06 15:10:25 +00:00 committed by GitHub
commit 2713c509de
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 61 additions and 15 deletions

View file

@ -5,9 +5,7 @@ use hir::Param;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::intravisit::{Visitor as HirVisitor, Visitor};
use rustc_hir::{
ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, ExprKind, Node, intravisit as hir_visit,
};
use rustc_hir::{ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, ExprKind, intravisit as hir_visit};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::hir::nested_filter;
use rustc_middle::ty;
@ -198,15 +196,15 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
hint = hint.asyncify();
}
let is_in_fn_call_arg = if let Node::Expr(expr) = cx.tcx.parent_hir_node(expr.hir_id) {
matches!(expr.kind, ExprKind::Call(_, _))
} else {
false
};
// avoid clippy::double_parens
if !is_in_fn_call_arg {
hint = hint.maybe_paren();
// If the closure body is a block with a single expression, suggest just the inner expression,
// not the block. Example: `(|| { Some(true) })()` should suggest
// `Some(true)`
if let ExprKind::Block(block, _) = body.kind
&& block.stmts.is_empty()
&& let Some(expr) = block.expr
{
hint = Sugg::hir_with_context(cx, expr, full_expr.span.ctxt(), "..", &mut applicability)
.maybe_paren();
}
diag.span_suggestion(full_expr.span, "try doing something like", hint, applicability);

View file

@ -60,7 +60,7 @@ fn issue9956() {
//~^ redundant_closure_call
// immediately calling only one closure, so we can't remove the other ones
let a = (|| || 123);
let a = || || 123;
//~^ redundant_closure_call
dbg!(a()());
@ -144,3 +144,15 @@ fn issue_12358() {
// different.
make_closure!(x)();
}
#[rustfmt::skip]
fn issue_9583() {
Some(true) == Some(true);
//~^ redundant_closure_call
Some(true) == Some(true);
//~^ redundant_closure_call
Some(if 1 > 2 {1} else {2}) == Some(2);
//~^ redundant_closure_call
Some( 1 > 2 ) == Some(true);
//~^ redundant_closure_call
}

View file

@ -144,3 +144,15 @@ fn issue_12358() {
// different.
make_closure!(x)();
}
#[rustfmt::skip]
fn issue_9583() {
(|| { Some(true) })() == Some(true);
//~^ redundant_closure_call
(|| Some(true))() == Some(true);
//~^ redundant_closure_call
(|| { Some(if 1 > 2 {1} else {2}) })() == Some(2);
//~^ redundant_closure_call
(|| { Some( 1 > 2 ) })() == Some(true);
//~^ redundant_closure_call
}

View file

@ -95,7 +95,7 @@ error: try not to call a closure in the expression where it is declared
--> tests/ui/redundant_closure_call_fixable.rs:63:13
|
LL | let a = (|| || || 123)();
| ^^^^^^^^^^^^^^^^ help: try doing something like: `(|| || 123)`
| ^^^^^^^^^^^^^^^^ help: try doing something like: `|| || 123`
error: try not to call a closure in the expression where it is declared
--> tests/ui/redundant_closure_call_fixable.rs:68:13
@ -145,5 +145,29 @@ error: try not to call a closure in the expression where it is declared
LL | std::convert::identity((|| 13_i32 + 36_i32)()).leading_zeros();
| ^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `13_i32 + 36_i32`
error: aborting due to 17 previous errors
error: try not to call a closure in the expression where it is declared
--> tests/ui/redundant_closure_call_fixable.rs:150:5
|
LL | (|| { Some(true) })() == Some(true);
| ^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `Some(true)`
error: try not to call a closure in the expression where it is declared
--> tests/ui/redundant_closure_call_fixable.rs:152:5
|
LL | (|| Some(true))() == Some(true);
| ^^^^^^^^^^^^^^^^^ help: try doing something like: `Some(true)`
error: try not to call a closure in the expression where it is declared
--> tests/ui/redundant_closure_call_fixable.rs:154:5
|
LL | (|| { Some(if 1 > 2 {1} else {2}) })() == Some(2);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `Some(if 1 > 2 {1} else {2})`
error: try not to call a closure in the expression where it is declared
--> tests/ui/redundant_closure_call_fixable.rs:156:5
|
LL | (|| { Some( 1 > 2 ) })() == Some(true);
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `Some( 1 > 2 )`
error: aborting due to 21 previous errors