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
This commit is contained in:
bors 2023-03-18 15:19:27 +00:00
commit e64c5961dc
4 changed files with 75 additions and 4 deletions

View File

@ -6,7 +6,7 @@ use rustc_errors::Applicability;
use rustc_hir::intravisit::FnKind; use rustc_hir::intravisit::FnKind;
use rustc_hir::{ use rustc_hir::{
AsyncGeneratorKind, Block, Body, Closure, Expr, ExprKind, FnDecl, FnRetTy, GeneratorKind, GenericArg, GenericBound, 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_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
@ -46,7 +46,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
decl: &'tcx FnDecl<'_>, decl: &'tcx FnDecl<'_>,
body: &'tcx Body<'_>, body: &'tcx Body<'_>,
span: Span, span: Span,
_: LocalDefId, def_id: LocalDefId,
) { ) {
if_chain! { if_chain! {
if let Some(header) = kind.header(); 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 let ExprKind::Block(block, _) = body.value.kind;
if block.stmts.is_empty(); if block.stmts.is_empty();
if let Some(closure_body) = desugared_async_block(cx, block); 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 { then {
let header_span = span.with_hi(ret_ty.span.hi()); 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", "this function can be simplified using the `async fn` syntax",
|diag| { |diag| {
if_chain! { 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(header_snip) = snippet_opt(cx, header_span);
if let Some(ret_pos) = position_before_rarrow(&header_snip); if let Some(ret_pos) = position_before_rarrow(&header_snip);
if let Some((ret_sugg, ret_snip)) = suggested_ret(cx, output); if let Some((ret_sugg, ret_snip)) = suggested_ret(cx, output);
then { 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}"); let help = format!("make the function `async` and {ret_sugg}");
diag.span_suggestion( diag.span_suggestion(
header_span, header_span,
help, help,
format!("async {}{ret_snip}", &header_snip[..ret_pos]), format!("{header_snip}{ret_snip}"),
Applicability::MachineApplicable Applicability::MachineApplicable
); );

View File

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

View File

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

View File

@ -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 } 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