Skip to content

Commit c4aeb32

Browse files
authored
chore: use multipart_suggestions for manual_async_fn (#13788)
This addresses #13099 for the manual_async_fn test. changelog: [manual_async_fn]: Updated manual_async_fn to use multipart_suggestions where appropriate
2 parents ec37eb6 + c963e22 commit c4aeb32

File tree

4 files changed

+166
-108
lines changed

4 files changed

+166
-108
lines changed

clippy_lints/src/manual_async_fn.rs

+8-13
Original file line numberDiff line numberDiff line change
@@ -74,27 +74,22 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
7474
if let Some(vis_snip) = vis_span.get_source_text(cx)
7575
&& let Some(header_snip) = header_span.get_source_text(cx)
7676
&& let Some(ret_pos) = position_before_rarrow(&header_snip)
77-
&& let Some((ret_sugg, ret_snip)) = suggested_ret(cx, output)
77+
&& let Some((_, ret_snip)) = suggested_ret(cx, output)
7878
{
7979
let header_snip = if vis_snip.is_empty() {
8080
format!("async {}", &header_snip[..ret_pos])
8181
} else {
8282
format!("{} async {}", vis_snip, &header_snip[vis_snip.len() + 1..ret_pos])
8383
};
8484

85-
let help = format!("make the function `async` and {ret_sugg}");
86-
diag.span_suggestion(
87-
header_span,
88-
help,
89-
format!("{header_snip}{ret_snip}"),
90-
Applicability::MachineApplicable,
91-
);
85+
let body_snip = snippet_block(cx, closure_body.value.span, "..", Some(block.span)).to_string();
9286

93-
let body_snip = snippet_block(cx, closure_body.value.span, "..", Some(block.span));
94-
diag.span_suggestion(
95-
block.span,
96-
"move the body of the async block to the enclosing function",
97-
body_snip,
87+
diag.multipart_suggestion(
88+
"make the function `async` and return the output of the future directly",
89+
vec![
90+
(header_span, format!("{header_snip}{ret_snip}")),
91+
(block.span, body_snip),
92+
],
9893
Applicability::MachineApplicable,
9994
);
10095
}

tests/ui/manual_async_fn.fixed

+116
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
#![warn(clippy::manual_async_fn)]
2+
#![allow(clippy::needless_pub_self, unused)]
3+
4+
use std::future::Future;
5+
6+
async fn fut() -> i32 { 42 }
7+
8+
#[rustfmt::skip]
9+
async fn fut2() -> i32 { 42 }
10+
11+
#[rustfmt::skip]
12+
async fn fut3() -> i32 { 42 }
13+
14+
async fn empty_fut() {}
15+
16+
#[rustfmt::skip]
17+
async fn empty_fut2() {}
18+
19+
#[rustfmt::skip]
20+
async fn empty_fut3() {}
21+
22+
async fn core_fut() -> i32 { 42 }
23+
24+
// should be ignored
25+
fn has_other_stmts() -> impl core::future::Future<Output = i32> {
26+
let _ = 42;
27+
async move { 42 }
28+
}
29+
30+
// should be ignored
31+
fn not_fut() -> i32 {
32+
42
33+
}
34+
35+
// should be ignored
36+
async fn already_async() -> impl Future<Output = i32> {
37+
async { 42 }
38+
}
39+
40+
struct S;
41+
impl S {
42+
async fn inh_fut() -> i32 {
43+
// NOTE: this code is here just to check that the indentation is correct in the suggested fix
44+
let a = 42;
45+
let b = 21;
46+
if a < b {
47+
let c = 21;
48+
let d = 42;
49+
if c < d {
50+
let _ = 42;
51+
}
52+
}
53+
42
54+
}
55+
56+
// should be ignored
57+
fn not_fut(&self) -> i32 {
58+
42
59+
}
60+
61+
// should be ignored
62+
fn has_other_stmts() -> impl core::future::Future<Output = i32> {
63+
let _ = 42;
64+
async move { 42 }
65+
}
66+
67+
// should be ignored
68+
async fn already_async(&self) -> impl Future<Output = i32> {
69+
async { 42 }
70+
}
71+
}
72+
73+
// Tests related to lifetime capture
74+
75+
async fn elided(_: &i32) -> i32 { 42 }
76+
77+
// should be ignored
78+
fn elided_not_bound(_: &i32) -> impl Future<Output = i32> {
79+
async { 42 }
80+
}
81+
82+
#[allow(clippy::needless_lifetimes)]
83+
async fn explicit<'a, 'b>(_: &'a i32, _: &'b i32) -> i32 { 42 }
84+
85+
// should be ignored
86+
#[allow(clippy::needless_lifetimes)]
87+
fn explicit_not_bound<'a, 'b>(_: &'a i32, _: &'b i32) -> impl Future<Output = i32> {
88+
async { 42 }
89+
}
90+
91+
// should be ignored
92+
mod issue_5765 {
93+
use std::future::Future;
94+
95+
struct A;
96+
impl A {
97+
fn f(&self) -> impl Future<Output = ()> {
98+
async {}
99+
}
100+
}
101+
102+
fn test() {
103+
let _future = {
104+
let a = A;
105+
a.f()
106+
};
107+
}
108+
}
109+
110+
pub async fn issue_10450() -> i32 { 42 }
111+
112+
pub(crate) async fn issue_10450_2() -> i32 { 42 }
113+
114+
pub(self) async fn issue_10450_3() -> i32 { 42 }
115+
116+
fn main() {}

tests/ui/manual_async_fn.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
#![warn(clippy::manual_async_fn)]
22
#![allow(clippy::needless_pub_self, unused)]
33

4-
//@no-rustfix: need to change the suggestion to a multipart suggestion
5-
64
use std::future::Future;
75

86
fn fut() -> impl Future<Output = i32> {
@@ -99,6 +97,7 @@ fn elided_not_bound(_: &i32) -> impl Future<Output = i32> {
9997
async { 42 }
10098
}
10199

100+
#[allow(clippy::needless_lifetimes)]
102101
fn explicit<'a, 'b>(_: &'a i32, _: &'b i32) -> impl Future<Output = i32> + 'a + 'b {
103102
async { 42 }
104103
}

0 commit comments

Comments
 (0)