Skip to content

Commit e64c596

Browse files
committed
Auto merge of #10456 - samueltardieu:issue-10450, r=Manishearth
Issue function modifiers in the right order in manual_async_fn lint Fixes #10450 changelog: [`manual_async_fn`] output function modifiers in correct order
2 parents d3c8442 + afe27ba commit e64c596

File tree

4 files changed

+75
-4
lines changed

4 files changed

+75
-4
lines changed

clippy_lints/src/manual_async_fn.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use rustc_errors::Applicability;
66
use rustc_hir::intravisit::FnKind;
77
use rustc_hir::{
88
AsyncGeneratorKind, Block, Body, Closure, Expr, ExprKind, FnDecl, FnRetTy, GeneratorKind, GenericArg, GenericBound,
9-
ItemKind, LifetimeName, Term, TraitRef, Ty, TyKind, TypeBindingKind,
9+
ImplItem, Item, ItemKind, LifetimeName, Node, Term, TraitRef, Ty, TyKind, TypeBindingKind,
1010
};
1111
use rustc_lint::{LateContext, LateLintPass};
1212
use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -46,7 +46,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
4646
decl: &'tcx FnDecl<'_>,
4747
body: &'tcx Body<'_>,
4848
span: Span,
49-
_: LocalDefId,
49+
def_id: LocalDefId,
5050
) {
5151
if_chain! {
5252
if let Some(header) = kind.header();
@@ -60,6 +60,8 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
6060
if let ExprKind::Block(block, _) = body.value.kind;
6161
if block.stmts.is_empty();
6262
if let Some(closure_body) = desugared_async_block(cx, block);
63+
if let Node::Item(Item {vis_span, ..}) | Node::ImplItem(ImplItem {vis_span, ..}) =
64+
cx.tcx.hir().get_by_def_id(def_id);
6365
then {
6466
let header_span = span.with_hi(ret_ty.span.hi());
6567

@@ -70,15 +72,21 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
7072
"this function can be simplified using the `async fn` syntax",
7173
|diag| {
7274
if_chain! {
75+
if let Some(vis_snip) = snippet_opt(cx, *vis_span);
7376
if let Some(header_snip) = snippet_opt(cx, header_span);
7477
if let Some(ret_pos) = position_before_rarrow(&header_snip);
7578
if let Some((ret_sugg, ret_snip)) = suggested_ret(cx, output);
7679
then {
80+
let header_snip = if !vis_snip.is_empty() {
81+
format!("{} async {}", vis_snip, &header_snip[vis_snip.len() + 1..ret_pos])
82+
} else {
83+
format!("async {}", &header_snip[..ret_pos])
84+
};
7785
let help = format!("make the function `async` and {ret_sugg}");
7886
diag.span_suggestion(
7987
header_span,
8088
help,
81-
format!("async {}{ret_snip}", &header_snip[..ret_pos]),
89+
format!("{header_snip}{ret_snip}"),
8290
Applicability::MachineApplicable
8391
);
8492

tests/ui/manual_async_fn.fixed

+6
Original file line numberDiff line numberDiff line change
@@ -107,4 +107,10 @@ mod issue_5765 {
107107
}
108108
}
109109

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+
110116
fn main() {}

tests/ui/manual_async_fn.rs

+12
Original file line numberDiff line numberDiff line change
@@ -127,4 +127,16 @@ mod issue_5765 {
127127
}
128128
}
129129

130+
pub fn issue_10450() -> impl Future<Output = i32> {
131+
async { 42 }
132+
}
133+
134+
pub(crate) fn issue_10450_2() -> impl Future<Output = i32> {
135+
async { 42 }
136+
}
137+
138+
pub(self) fn issue_10450_3() -> impl Future<Output = i32> {
139+
async { 42 }
140+
}
141+
130142
fn main() {}

tests/ui/manual_async_fn.stderr

+46-1
Original file line numberDiff line numberDiff line change
@@ -161,5 +161,50 @@ help: move the body of the async block to the enclosing function
161161
LL | fn explicit<'a, 'b>(_: &'a i32, _: &'b i32) -> impl Future<Output = i32> + 'a + 'b { 42 }
162162
| ~~~~~~
163163

164-
error: aborting due to 10 previous errors
164+
error: this function can be simplified using the `async fn` syntax
165+
--> $DIR/manual_async_fn.rs:130:1
166+
|
167+
LL | pub fn issue_10450() -> impl Future<Output = i32> {
168+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
169+
|
170+
help: make the function `async` and return the output of the future directly
171+
|
172+
LL | pub async fn issue_10450() -> i32 {
173+
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
174+
help: move the body of the async block to the enclosing function
175+
|
176+
LL | pub fn issue_10450() -> impl Future<Output = i32> { 42 }
177+
| ~~~~~~
178+
179+
error: this function can be simplified using the `async fn` syntax
180+
--> $DIR/manual_async_fn.rs:134:1
181+
|
182+
LL | pub(crate) fn issue_10450_2() -> impl Future<Output = i32> {
183+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
184+
|
185+
help: make the function `async` and return the output of the future directly
186+
|
187+
LL | pub(crate) async fn issue_10450_2() -> i32 {
188+
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
189+
help: move the body of the async block to the enclosing function
190+
|
191+
LL | pub(crate) fn issue_10450_2() -> impl Future<Output = i32> { 42 }
192+
| ~~~~~~
193+
194+
error: this function can be simplified using the `async fn` syntax
195+
--> $DIR/manual_async_fn.rs:138:1
196+
|
197+
LL | pub(self) fn issue_10450_3() -> impl Future<Output = i32> {
198+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
199+
|
200+
help: make the function `async` and return the output of the future directly
201+
|
202+
LL | pub(self) async fn issue_10450_3() -> i32 {
203+
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
204+
help: move the body of the async block to the enclosing function
205+
|
206+
LL | pub(self) fn issue_10450_3() -> impl Future<Output = i32> { 42 }
207+
| ~~~~~~
208+
209+
error: aborting due to 13 previous errors
165210

0 commit comments

Comments
 (0)