Skip to content

Commit 57397a5

Browse files
committed
Auto merge of rust-lang#11363 - KisaragiEffective:fix_redundant_closure_call_on_closure_returns_async_block, r=llogiq
[`redundant_closure_call`]: avoid duplicated `async` keyword when triggering on closure that returns `async` block close rust-lang#11357 ---- *Please write a short comment explaining your change (or "none" for internal only changes)* changelog: [`redundant_closure_call`]: avoid duplicated `async` keyword when triggering on closure that returns `async` block
2 parents 91c5653 + 0426913 commit 57397a5

4 files changed

+77
-14
lines changed

clippy_lints/src/redundant_closure_call.rs

+22-13
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ use clippy_utils::get_parent_expr;
44
use clippy_utils::sugg::Sugg;
55
use rustc_errors::Applicability;
66
use rustc_hir as hir;
7-
use rustc_hir::intravisit as hir_visit;
87
use rustc_hir::intravisit::{Visitor as HirVisitor, Visitor};
8+
use rustc_hir::{intravisit as hir_visit, CoroutineKind, CoroutineSource, Node};
99
use rustc_lint::{LateContext, LateLintPass};
1010
use rustc_middle::hir::nested_filter;
1111
use rustc_middle::lint::in_external_macro;
@@ -60,11 +60,14 @@ impl<'tcx> Visitor<'tcx> for ReturnVisitor {
6060
}
6161
}
6262

63-
/// Checks if the body is owned by an async closure
64-
fn is_async_closure(body: &hir::Body<'_>) -> bool {
65-
if let hir::ExprKind::Closure(closure) = body.value.kind
66-
&& let [resume_ty] = closure.fn_decl.inputs
67-
&& let hir::TyKind::Path(hir::QPath::LangItem(hir::LangItem::ResumeTy, ..)) = resume_ty.kind
63+
/// Checks if the body is owned by an async closure.
64+
/// Returns true for `async || whatever_expression`, but false for `|| async { whatever_expression
65+
/// }`.
66+
fn is_async_closure(cx: &LateContext<'_>, body: &hir::Body<'_>) -> bool {
67+
if let hir::ExprKind::Closure(innermost_closure_generated_by_desugar) = body.value.kind
68+
&& let desugared_inner_closure_body = cx.tcx.hir().body(innermost_closure_generated_by_desugar.body)
69+
// checks whether it is `async || whatever_expression`
70+
&& let Some(CoroutineKind::Async(CoroutineSource::Closure)) = desugared_inner_closure_body.coroutine_kind
6871
{
6972
true
7073
} else {
@@ -100,7 +103,7 @@ fn find_innermost_closure<'tcx>(
100103
data = Some((
101104
body.value,
102105
closure.fn_decl,
103-
if is_async_closure(body) {
106+
if is_async_closure(cx, body) {
104107
ty::Asyncness::Yes
105108
} else {
106109
ty::Asyncness::No
@@ -173,12 +176,18 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
173176
hint = hint.asyncify();
174177
}
175178

176-
diag.span_suggestion(
177-
full_expr.span,
178-
"try doing something like",
179-
hint.maybe_par(),
180-
applicability,
181-
);
179+
let is_in_fn_call_arg =
180+
clippy_utils::get_parent_node(cx.tcx, expr.hir_id).is_some_and(|x| match x {
181+
Node::Expr(expr) => matches!(expr.kind, hir::ExprKind::Call(_, _)),
182+
_ => false,
183+
});
184+
185+
// avoid clippy::double_parens
186+
if !is_in_fn_call_arg {
187+
hint = hint.maybe_par();
188+
};
189+
190+
diag.span_suggestion(full_expr.span, "try doing something like", hint, applicability);
182191
}
183192
},
184193
);

tests/ui/redundant_closure_call_fixable.fixed

+18
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,21 @@ fn issue9956() {
8484
bar()(42, 5);
8585
foo(42, 5);
8686
}
87+
88+
async fn issue11357() {
89+
async {}.await;
90+
}
91+
92+
mod issue11707 {
93+
use core::future::Future;
94+
95+
fn spawn_on(fut: impl Future<Output = ()>) {}
96+
97+
fn demo() {
98+
spawn_on(async move {});
99+
}
100+
}
101+
102+
fn avoid_double_parens() {
103+
std::convert::identity(13_i32 + 36_i32).leading_zeros();
104+
}

tests/ui/redundant_closure_call_fixable.rs

+18
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,21 @@ fn issue9956() {
8484
bar()((|| || 42)()(), 5);
8585
foo((|| || 42)()(), 5);
8686
}
87+
88+
async fn issue11357() {
89+
(|| async {})().await;
90+
}
91+
92+
mod issue11707 {
93+
use core::future::Future;
94+
95+
fn spawn_on(fut: impl Future<Output = ()>) {}
96+
97+
fn demo() {
98+
spawn_on((|| async move {})());
99+
}
100+
}
101+
102+
fn avoid_double_parens() {
103+
std::convert::identity((|| 13_i32 + 36_i32)()).leading_zeros();
104+
}

tests/ui/redundant_closure_call_fixable.stderr

+19-1
Original file line numberDiff line numberDiff line change
@@ -123,5 +123,23 @@ error: try not to call a closure in the expression where it is declared
123123
LL | foo((|| || 42)()(), 5);
124124
| ^^^^^^^^^^^^^^ help: try doing something like: `42`
125125

126-
error: aborting due to 14 previous errors
126+
error: try not to call a closure in the expression where it is declared
127+
--> $DIR/redundant_closure_call_fixable.rs:89:5
128+
|
129+
LL | (|| async {})().await;
130+
| ^^^^^^^^^^^^^^^ help: try doing something like: `async {}`
131+
132+
error: try not to call a closure in the expression where it is declared
133+
--> $DIR/redundant_closure_call_fixable.rs:98:18
134+
|
135+
LL | spawn_on((|| async move {})());
136+
| ^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `async move {}`
137+
138+
error: try not to call a closure in the expression where it is declared
139+
--> $DIR/redundant_closure_call_fixable.rs:103:28
140+
|
141+
LL | std::convert::identity((|| 13_i32 + 36_i32)()).leading_zeros();
142+
| ^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `13_i32 + 36_i32`
143+
144+
error: aborting due to 17 previous errors
127145

0 commit comments

Comments
 (0)