]> git.lizzy.rs Git - rust.git/commitdiff
Fix `implicit_return` suggestion for async functions
authorJason Newcomb <jsnewcomb@pm.me>
Fri, 2 Apr 2021 21:53:14 +0000 (17:53 -0400)
committerJason Newcomb <jsnewcomb@pm.me>
Thu, 22 Apr 2021 13:36:32 +0000 (09:36 -0400)
clippy_lints/src/implicit_return.rs
clippy_utils/src/lib.rs
tests/ui/implicit_return.fixed
tests/ui/implicit_return.rs
tests/ui/implicit_return.stderr

index 251a73618716fc304fddbce060277ecf828d0975..39612dbf05004d5f9c7414ca986352a188b213d4 100644 (file)
@@ -1,5 +1,6 @@
 use clippy_utils::{
     diagnostics::span_lint_and_sugg,
 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,
 };
     source::{snippet_with_applicability, snippet_with_context, walk_span_to_context},
     visitors::visit_break_exprs,
 };
@@ -219,6 +220,14 @@ fn check_fn(
             return;
         }
 
             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);
     }
 }
     }
 }
index b7017411927daa5cf81f257296769f979f9e4fcc..6dc96e51a6b1ec65f326f30f901953ea9dc5fb16 100644 (file)
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 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,
 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;
 };
 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)
 }
 
     (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))
 // 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))
index c0fc4b926a04b4d6931bc5e4ad903c7543f67280..7698b88a88c8aa80a143ac27ab11e145a880ef51 100644 (file)
@@ -1,3 +1,4 @@
+// edition:2018
 // run-rustfix
 
 #![warn(clippy::implicit_return)]
 // run-rustfix
 
 #![warn(clippy::implicit_return)]
@@ -122,4 +123,9 @@ fn divergent_test() -> bool {
     diverge()
 }
 
     diverge()
 }
 
+// issue #6940
+async fn foo() -> bool {
+    return true
+}
+
 fn main() {}
 fn main() {}
index 737ffd5ddce1484e71a74963f4de050d18139659..45bbc2ec670e05463d1a0f8d6f8d5fc557561cfe 100644 (file)
@@ -1,3 +1,4 @@
+// edition:2018
 // run-rustfix
 
 #![warn(clippy::implicit_return)]
 // run-rustfix
 
 #![warn(clippy::implicit_return)]
@@ -122,4 +123,9 @@ fn diverge() -> ! {
     diverge()
 }
 
     diverge()
 }
 
+// issue #6940
+async fn foo() -> bool {
+    true
+}
+
 fn main() {}
 fn main() {}
index 632e30cbdc6e075c9b350a56762034d8e1871ad3..16fe9ed444ff696d20c0c3411cb56913a631a6d2 100644 (file)
@@ -1,5 +1,5 @@
 error: missing `return` statement
 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`
    |
 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
    = 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
    |
 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
    |
 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
    |
 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
    |
 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
    |
 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
    |
 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
    |
 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
    |
 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
    |
 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
    |
 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
    |
 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
    |
 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
    |
 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 | /     loop {
 LL | |         m!(true);
@@ -99,5 +99,11 @@ LL |         m!(true);
 LL |     }
    |
 
 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