about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/manual_async_fn.rs14
-rw-r--r--tests/ui/manual_async_fn.fixed6
-rw-r--r--tests/ui/manual_async_fn.rs12
-rw-r--r--tests/ui/manual_async_fn.stderr47
4 files changed, 75 insertions, 4 deletions
diff --git a/clippy_lints/src/manual_async_fn.rs b/clippy_lints/src/manual_async_fn.rs
index 3778eb4c732..af52090d8a4 100644
--- a/clippy_lints/src/manual_async_fn.rs
+++ b/clippy_lints/src/manual_async_fn.rs
@@ -6,7 +6,7 @@ use rustc_errors::Applicability;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{
     AsyncGeneratorKind, Block, Body, Closure, Expr, ExprKind, FnDecl, FnRetTy, GeneratorKind, GenericArg, GenericBound,
-    ItemKind, LifetimeName, Term, TraitRef, Ty, TyKind, TypeBindingKind,
+    ImplItem, Item, ItemKind, LifetimeName, Node, Term, TraitRef, Ty, TyKind, TypeBindingKind,
 };
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -46,7 +46,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
         decl: &'tcx FnDecl<'_>,
         body: &'tcx Body<'_>,
         span: Span,
-        _: LocalDefId,
+        def_id: LocalDefId,
     ) {
         if_chain! {
             if let Some(header) = kind.header();
@@ -60,6 +60,8 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
             if let ExprKind::Block(block, _) = body.value.kind;
             if block.stmts.is_empty();
             if let Some(closure_body) = desugared_async_block(cx, block);
+            if let Node::Item(Item {vis_span, ..}) | Node::ImplItem(ImplItem {vis_span, ..}) =
+                cx.tcx.hir().get_by_def_id(def_id);
             then {
                 let header_span = span.with_hi(ret_ty.span.hi());
 
@@ -70,15 +72,21 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
                     "this function can be simplified using the `async fn` syntax",
                     |diag| {
                         if_chain! {
+                            if let Some(vis_snip) = snippet_opt(cx, *vis_span);
                             if let Some(header_snip) = snippet_opt(cx, header_span);
                             if let Some(ret_pos) = position_before_rarrow(&header_snip);
                             if let Some((ret_sugg, ret_snip)) = suggested_ret(cx, output);
                             then {
+                                let header_snip = if !vis_snip.is_empty() {
+                                    format!("{} async {}", vis_snip, &header_snip[vis_snip.len() + 1..ret_pos])
+                                } else {
+                                    format!("async {}", &header_snip[..ret_pos])
+                                };
                                 let help = format!("make the function `async` and {ret_sugg}");
                                 diag.span_suggestion(
                                     header_span,
                                     help,
-                                    format!("async {}{ret_snip}", &header_snip[..ret_pos]),
+                                    format!("{header_snip}{ret_snip}"),
                                     Applicability::MachineApplicable
                                 );
 
diff --git a/tests/ui/manual_async_fn.fixed b/tests/ui/manual_async_fn.fixed
index b7e46a4a8cc..5cc4a43af7e 100644
--- a/tests/ui/manual_async_fn.fixed
+++ b/tests/ui/manual_async_fn.fixed
@@ -107,4 +107,10 @@ mod issue_5765 {
     }
 }
 
+pub async fn issue_10450() -> i32 { 42 }
+
+pub(crate) async fn issue_10450_2() -> i32 { 42 }
+
+pub(self) async fn issue_10450_3() -> i32 { 42 }
+
 fn main() {}
diff --git a/tests/ui/manual_async_fn.rs b/tests/ui/manual_async_fn.rs
index b05429da662..ba504b8a823 100644
--- a/tests/ui/manual_async_fn.rs
+++ b/tests/ui/manual_async_fn.rs
@@ -127,4 +127,16 @@ mod issue_5765 {
     }
 }
 
+pub fn issue_10450() -> impl Future<Output = i32> {
+    async { 42 }
+}
+
+pub(crate) fn issue_10450_2() -> impl Future<Output = i32> {
+    async { 42 }
+}
+
+pub(self) fn issue_10450_3() -> impl Future<Output = i32> {
+    async { 42 }
+}
+
 fn main() {}
diff --git a/tests/ui/manual_async_fn.stderr b/tests/ui/manual_async_fn.stderr
index 0a903ed6fd4..f5ee3eb7ccc 100644
--- a/tests/ui/manual_async_fn.stderr
+++ b/tests/ui/manual_async_fn.stderr
@@ -161,5 +161,50 @@ help: move the body of the async block to the enclosing function
 LL | fn explicit<'a, 'b>(_: &'a i32, _: &'b i32) -> impl Future<Output = i32> + 'a + 'b { 42 }
    |                                                                                    ~~~~~~
 
-error: aborting due to 10 previous errors
+error: this function can be simplified using the `async fn` syntax
+  --> $DIR/manual_async_fn.rs:130:1
+   |
+LL | pub fn issue_10450() -> impl Future<Output = i32> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: make the function `async` and return the output of the future directly
+   |
+LL | pub async fn issue_10450() -> i32 {
+   | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+help: move the body of the async block to the enclosing function
+   |
+LL | pub fn issue_10450() -> impl Future<Output = i32> { 42 }
+   |                                                   ~~~~~~
+
+error: this function can be simplified using the `async fn` syntax
+  --> $DIR/manual_async_fn.rs:134:1
+   |
+LL | pub(crate) fn issue_10450_2() -> impl Future<Output = i32> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: make the function `async` and return the output of the future directly
+   |
+LL | pub(crate) async fn issue_10450_2() -> i32 {
+   | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+help: move the body of the async block to the enclosing function
+   |
+LL | pub(crate) fn issue_10450_2() -> impl Future<Output = i32> { 42 }
+   |                                                            ~~~~~~
+
+error: this function can be simplified using the `async fn` syntax
+  --> $DIR/manual_async_fn.rs:138:1
+   |
+LL | pub(self) fn issue_10450_3() -> impl Future<Output = i32> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: make the function `async` and return the output of the future directly
+   |
+LL | pub(self) async fn issue_10450_3() -> i32 {
+   | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+help: move the body of the async block to the enclosing function
+   |
+LL | pub(self) fn issue_10450_3() -> impl Future<Output = i32> { 42 }
+   |                                                           ~~~~~~
+
+error: aborting due to 13 previous errors