From afe27ba1a2fbf902ecb5bd02590871be5f46f34d Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 5 Mar 2023 12:38:23 +0100 Subject: [PATCH] Issue function modifiers in the right order in manual_async_fn lint --- clippy_lints/src/manual_async_fn.rs | 14 +++++++-- tests/ui/manual_async_fn.fixed | 6 ++++ tests/ui/manual_async_fn.rs | 12 ++++++++ tests/ui/manual_async_fn.stderr | 47 ++++++++++++++++++++++++++++- 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 3778eb4c732d7..af52090d8a476 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 b7e46a4a8ccc2..5cc4a43af7e36 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 b05429da66225..ba504b8a8231f 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 { + async { 42 } +} + +pub(crate) fn issue_10450_2() -> impl Future { + async { 42 } +} + +pub(self) fn issue_10450_3() -> impl Future { + async { 42 } +} + fn main() {} diff --git a/tests/ui/manual_async_fn.stderr b/tests/ui/manual_async_fn.stderr index 0a903ed6fd436..f5ee3eb7cccba 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 + '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 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +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 { 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 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +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 { 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 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +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 { 42 } + | ~~~~~~ + +error: aborting due to 13 previous errors