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,
};
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);
}
}
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;
(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))
+// edition:2018
// run-rustfix
#![warn(clippy::implicit_return)]
diverge()
}
+// issue #6940
+async fn foo() -> bool {
+ return true
+}
+
fn main() {}
+// edition:2018
// run-rustfix
#![warn(clippy::implicit_return)]
diverge()
}
+// issue #6940
+async fn foo() -> bool {
+ true
+}
+
fn main() {}
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`
= 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);
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