From: Jason Newcomb Date: Fri, 2 Apr 2021 21:53:14 +0000 (-0400) Subject: Fix `implicit_return` suggestion for async functions X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;ds=sidebyside;h=74cf5f2fc6c121ae0eaaa709c9a303cd82fe9b30;p=rust.git Fix `implicit_return` suggestion for async functions --- diff --git a/clippy_lints/src/implicit_return.rs b/clippy_lints/src/implicit_return.rs index 251a7361871..39612dbf050 100644 --- a/clippy_lints/src/implicit_return.rs +++ b/clippy_lints/src/implicit_return.rs @@ -1,5 +1,6 @@ use clippy_utils::{ diagnostics::span_lint_and_sugg, + get_async_fn_body, is_async_fn, source::{snippet_with_applicability, snippet_with_context, walk_span_to_context}, visitors::visit_break_exprs, }; @@ -219,6 +220,14 @@ fn check_fn( return; } - lint_implicit_returns(cx, &body.value, body.value.span.ctxt(), None); + let expr = if is_async_fn(kind) { + match get_async_fn_body(cx.tcx, body) { + Some(e) => e, + None => return, + } + } else { + &body.value + }; + lint_implicit_returns(cx, expr, expr.span.ctxt(), None); } } diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index b7017411927..6dc96e51a6b 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -60,12 +60,12 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; -use rustc_hir::intravisit::{self, walk_expr, ErasedMap, NestedVisitorMap, Visitor}; +use rustc_hir::intravisit::{self, walk_expr, ErasedMap, FnKind, NestedVisitorMap, Visitor}; use rustc_hir::LangItem::{ResultErr, ResultOk}; use rustc_hir::{ def, Arm, BindingAnnotation, Block, Body, Constness, Destination, Expr, ExprKind, FnDecl, GenericArgs, HirId, Impl, - ImplItem, ImplItemKind, Item, ItemKind, LangItem, Local, MatchSource, Node, Param, Pat, PatKind, Path, PathSegment, - QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitRef, TyKind, + ImplItem, ImplItemKind, IsAsync, Item, ItemKind, LangItem, Local, MatchSource, Node, Param, Pat, PatKind, Path, + PathSegment, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitRef, TyKind, }; use rustc_lint::{LateContext, Level, Lint, LintContext}; use rustc_middle::hir::exports::Export; @@ -1300,6 +1300,40 @@ pub fn if_sequence<'tcx>(mut expr: &'tcx Expr<'tcx>) -> (Vec<&'tcx Expr<'tcx>>, (conds, blocks) } +/// Checks if the given function kind is an async function. +pub fn is_async_fn(kind: FnKind) -> bool { + matches!(kind, FnKind::ItemFn(_, _, header, _) if header.asyncness == IsAsync::Async) +} + +/// Peels away all the compiler generated code surrounding the body of an async function, +pub fn get_async_fn_body(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Option<&'tcx Expr<'tcx>> { + if let ExprKind::Call( + _, + &[Expr { + kind: ExprKind::Closure(_, _, body, _, _), + .. + }], + ) = body.value.kind + { + if let ExprKind::Block( + Block { + stmts: [], + expr: + Some(Expr { + kind: ExprKind::DropTemps(expr), + .. + }), + .. + }, + _, + ) = tcx.hir().body(body).value.kind + { + return Some(expr); + } + }; + None +} + // Finds the `#[must_use]` attribute, if any pub fn must_use_attr(attrs: &[Attribute]) -> Option<&Attribute> { attrs.iter().find(|a| a.has_name(sym::must_use)) diff --git a/tests/ui/implicit_return.fixed b/tests/ui/implicit_return.fixed index c0fc4b926a0..7698b88a88c 100644 --- a/tests/ui/implicit_return.fixed +++ b/tests/ui/implicit_return.fixed @@ -1,3 +1,4 @@ +// edition:2018 // run-rustfix #![warn(clippy::implicit_return)] @@ -122,4 +123,9 @@ fn divergent_test() -> bool { diverge() } +// issue #6940 +async fn foo() -> bool { + return true +} + fn main() {} diff --git a/tests/ui/implicit_return.rs b/tests/ui/implicit_return.rs index 737ffd5ddce..45bbc2ec670 100644 --- a/tests/ui/implicit_return.rs +++ b/tests/ui/implicit_return.rs @@ -1,3 +1,4 @@ +// edition:2018 // run-rustfix #![warn(clippy::implicit_return)] @@ -122,4 +123,9 @@ fn diverge() -> ! { diverge() } +// issue #6940 +async fn foo() -> bool { + true +} + fn main() {} diff --git a/tests/ui/implicit_return.stderr b/tests/ui/implicit_return.stderr index 632e30cbdc6..16fe9ed444f 100644 --- a/tests/ui/implicit_return.stderr +++ b/tests/ui/implicit_return.stderr @@ -1,5 +1,5 @@ error: missing `return` statement - --> $DIR/implicit_return.rs:12:5 + --> $DIR/implicit_return.rs:13:5 | LL | true | ^^^^ help: add `return` as shown: `return true` @@ -7,85 +7,85 @@ LL | true = note: `-D clippy::implicit-return` implied by `-D warnings` error: missing `return` statement - --> $DIR/implicit_return.rs:16:15 + --> $DIR/implicit_return.rs:17:15 | LL | if true { true } else { false } | ^^^^ help: add `return` as shown: `return true` error: missing `return` statement - --> $DIR/implicit_return.rs:16:29 + --> $DIR/implicit_return.rs:17:29 | LL | if true { true } else { false } | ^^^^^ help: add `return` as shown: `return false` error: missing `return` statement - --> $DIR/implicit_return.rs:22:17 + --> $DIR/implicit_return.rs:23:17 | LL | true => false, | ^^^^^ help: add `return` as shown: `return false` error: missing `return` statement - --> $DIR/implicit_return.rs:23:20 + --> $DIR/implicit_return.rs:24:20 | LL | false => { true }, | ^^^^ help: add `return` as shown: `return true` error: missing `return` statement - --> $DIR/implicit_return.rs:36:9 + --> $DIR/implicit_return.rs:37:9 | LL | break true; | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` error: missing `return` statement - --> $DIR/implicit_return.rs:43:13 + --> $DIR/implicit_return.rs:44:13 | LL | break true; | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` error: missing `return` statement - --> $DIR/implicit_return.rs:51:13 + --> $DIR/implicit_return.rs:52:13 | LL | break true; | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` error: missing `return` statement - --> $DIR/implicit_return.rs:69:18 + --> $DIR/implicit_return.rs:70:18 | LL | let _ = || { true }; | ^^^^ help: add `return` as shown: `return true` error: missing `return` statement - --> $DIR/implicit_return.rs:70:16 + --> $DIR/implicit_return.rs:71:16 | LL | let _ = || true; | ^^^^ help: add `return` as shown: `return true` error: missing `return` statement - --> $DIR/implicit_return.rs:78:5 + --> $DIR/implicit_return.rs:79:5 | LL | format!("test {}", "test") | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `return` as shown: `return format!("test {}", "test")` error: missing `return` statement - --> $DIR/implicit_return.rs:87:5 + --> $DIR/implicit_return.rs:88:5 | LL | m!(true, false) | ^^^^^^^^^^^^^^^ help: add `return` as shown: `return m!(true, false)` error: missing `return` statement - --> $DIR/implicit_return.rs:93:13 + --> $DIR/implicit_return.rs:94:13 | LL | break true; | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` error: missing `return` statement - --> $DIR/implicit_return.rs:98:17 + --> $DIR/implicit_return.rs:99:17 | LL | break 'outer false; | ^^^^^^^^^^^^^^^^^^ help: change `break` to `return` as shown: `return false` error: missing `return` statement - --> $DIR/implicit_return.rs:113:5 + --> $DIR/implicit_return.rs:114:5 | LL | / loop { LL | | m!(true); @@ -99,5 +99,11 @@ LL | m!(true); LL | } | -error: aborting due to 15 previous errors +error: missing `return` statement + --> $DIR/implicit_return.rs:128:5 + | +LL | true + | ^^^^ help: add `return` as shown: `return true` + +error: aborting due to 16 previous errors