about summary refs log tree commit diff
path: root/clippy_utils/src
diff options
context:
space:
mode:
authorJason Newcomb <jsnewcomb@pm.me>2021-04-02 17:53:14 -0400
committerJason Newcomb <jsnewcomb@pm.me>2021-04-22 09:36:32 -0400
commit74cf5f2fc6c121ae0eaaa709c9a303cd82fe9b30 (patch)
tree5403c9c05fb5f9ef0fb91197b73bd41b3e53faf2 /clippy_utils/src
parent22f8c13cf5650d6c9d6ee7b4f0e88bffba9076ca (diff)
downloadrust-74cf5f2fc6c121ae0eaaa709c9a303cd82fe9b30.tar.gz
rust-74cf5f2fc6c121ae0eaaa709c9a303cd82fe9b30.zip
Fix `implicit_return` suggestion for async functions
Diffstat (limited to 'clippy_utils/src')
-rw-r--r--clippy_utils/src/lib.rs40
1 files changed, 37 insertions, 3 deletions
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_data_structures::fx::FxHashMap;
 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))