diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0a328a20dd4..6b11354e830 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2722,6 +2722,7 @@ Released 2018-09-13
 [`unsound_collection_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#unsound_collection_transmute
 [`unstable_as_mut_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#unstable_as_mut_slice
 [`unstable_as_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#unstable_as_slice
+[`unused_async`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_async
 [`unused_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_collect
 [`unused_io_amount`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_io_amount
 [`unused_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_self
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index f0fae6ee1c7..22d9f6e12a5 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -364,6 +364,7 @@ mod unnecessary_sort_by;
 mod unnecessary_wraps;
 mod unnested_or_patterns;
 mod unsafe_removed_from_name;
+mod unused_async;
 mod unused_io_amount;
 mod unused_self;
 mod unused_unit;
@@ -961,6 +962,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         unnecessary_wraps::UNNECESSARY_WRAPS,
         unnested_or_patterns::UNNESTED_OR_PATTERNS,
         unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME,
+        unused_async::UNUSED_ASYNC,
         unused_io_amount::UNUSED_IO_AMOUNT,
         unused_self::UNUSED_SELF,
         unused_unit::UNUSED_UNIT,
@@ -1273,6 +1275,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| box manual_map::ManualMap);
     store.register_late_pass(move || box if_then_some_else_none::IfThenSomeElseNone::new(msrv));
     store.register_early_pass(|| box bool_assert_comparison::BoolAssertComparison);
+    store.register_late_pass(|| box unused_async::UnusedAsync);
 
     store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
         LintId::of(arithmetic::FLOAT_ARITHMETIC),
@@ -1417,6 +1420,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(unit_types::LET_UNIT_VALUE),
         LintId::of(unnecessary_wraps::UNNECESSARY_WRAPS),
         LintId::of(unnested_or_patterns::UNNESTED_OR_PATTERNS),
+        LintId::of(unused_async::UNUSED_ASYNC),
         LintId::of(unused_self::UNUSED_SELF),
         LintId::of(wildcard_imports::ENUM_GLOB_USE),
         LintId::of(wildcard_imports::WILDCARD_IMPORTS),
diff --git a/clippy_lints/src/unused_async.rs b/clippy_lints/src/unused_async.rs
new file mode 100644
index 00000000000..18ee07d3a95
--- /dev/null
+++ b/clippy_lints/src/unused_async.rs
@@ -0,0 +1,92 @@
+use clippy_utils::diagnostics::span_lint_and_help;
+use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, NestedVisitorMap, Visitor};
+use rustc_hir::{Body, Expr, ExprKind, FnDecl, FnHeader, HirId, IsAsync, Item, ItemKind, YieldSource};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::hir::map::Map;
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::Span;
+
+declare_clippy_lint! {
+    /// **What it does:** Checks for functions that are declared `async` but have no `.await`s inside of them.
+    ///
+    /// **Why is this bad?** Async functions with no async code create overhead, both mentally and computationally.
+    /// Callers of async methods either need to be calling from an async function themselves or run it on an executor, both of which
+    /// causes runtime overhead and hassle for the caller.
+    ///
+    /// **Known problems:** None
+    ///
+    /// **Example:**
+    ///
+    /// ```rust
+    /// // Bad
+    /// async fn get_random_number() -> i64 {
+    ///     4 // Chosen by fair dice roll. Guaranteed to be random.
+    /// }
+    /// let number_future = get_random_number();
+    ///
+    /// // Good
+    /// fn get_random_number_improved() -> i64 {
+    ///     4 // Chosen by fair dice roll. Guaranteed to be random.
+    /// }
+    /// let number_future = async { get_random_number_improved() };
+    /// ```
+    pub UNUSED_ASYNC,
+    pedantic,
+    "finds async functions with no await statements"
+}
+
+declare_lint_pass!(UnusedAsync => [UNUSED_ASYNC]);
+
+struct AsyncFnVisitor<'a, 'tcx> {
+    cx: &'a LateContext<'tcx>,
+    found_await: bool,
+}
+
+impl<'a, 'tcx> Visitor<'tcx> for AsyncFnVisitor<'a, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
+        if let ExprKind::Yield(_, YieldSource::Await { .. }) = ex.kind {
+            self.found_await = true;
+        }
+        walk_expr(self, ex);
+    }
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::OnlyBodies(self.cx.tcx.hir())
+    }
+}
+
+impl<'tcx> LateLintPass<'tcx> for UnusedAsync {
+    fn check_item(&mut self, _: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
+        if let ItemKind::Trait(..) = item.kind {
+            return;
+        }
+    }
+    fn check_fn(
+        &mut self,
+        cx: &LateContext<'tcx>,
+        fn_kind: FnKind<'tcx>,
+        fn_decl: &'tcx FnDecl<'tcx>,
+        body: &Body<'tcx>,
+        span: Span,
+        hir_id: HirId,
+    ) {
+        if let FnKind::ItemFn(_, _, FnHeader { asyncness, .. }, _) = &fn_kind {
+            if matches!(asyncness, IsAsync::Async) {
+                let mut visitor = AsyncFnVisitor { cx, found_await: false };
+                walk_fn(&mut visitor, fn_kind, fn_decl, body.id(), span, hir_id);
+                if !visitor.found_await {
+                    span_lint_and_help(
+                        cx,
+                        UNUSED_ASYNC,
+                        span,
+                        "unused `async` for function with no await statements",
+                        None,
+                        "consider removing the `async` from this function",
+                    );
+                }
+            }
+        }
+    }
+}
diff --git a/tests/ui/unused_async.rs b/tests/ui/unused_async.rs
new file mode 100644
index 00000000000..4f4203f5fdb
--- /dev/null
+++ b/tests/ui/unused_async.rs
@@ -0,0 +1,15 @@
+// edition:2018
+#![warn(clippy::unused_async)]
+
+async fn foo() -> i32 {
+    4
+}
+
+async fn bar() -> i32 {
+    foo().await
+}
+
+fn main() {
+    foo();
+    bar();
+}
diff --git a/tests/ui/unused_async.stderr b/tests/ui/unused_async.stderr
new file mode 100644
index 00000000000..8b834d205b1
--- /dev/null
+++ b/tests/ui/unused_async.stderr
@@ -0,0 +1,13 @@
+error: unused `async` for function with no await statements
+  --> $DIR/unused_async.rs:4:1
+   |
+LL | / async fn foo() -> i32 {
+LL | |     4
+LL | | }
+   | |_^
+   |
+   = note: `-D clippy::unused-async` implied by `-D warnings`
+   = help: consider removing the `async` from this function
+
+error: aborting due to previous error
+