From a0b107bbb624ab4bf889f916707d2f025964d3be Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Mon, 20 Jun 2022 12:03:27 +0000 Subject: [PATCH] unused_async: lint async methods --- clippy_lints/src/unused_async.rs | 28 +++++++++--------- tests/ui/methods.rs | 1 + tests/ui/methods.stderr | 4 +-- tests/ui/should_impl_trait/corner_cases.rs | 3 +- tests/ui/unused_async.rs | 34 ++++++++++++++++++++++ tests/ui/unused_async.stderr | 14 +++++++-- 6 files changed, 64 insertions(+), 20 deletions(-) diff --git a/clippy_lints/src/unused_async.rs b/clippy_lints/src/unused_async.rs index c8ec4442ab1a..a832dfcccaf3 100644 --- a/clippy_lints/src/unused_async.rs +++ b/clippy_lints/src/unused_async.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_help; use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, Visitor}; -use rustc_hir::{Body, Expr, ExprKind, FnDecl, FnHeader, HirId, IsAsync, YieldSource}; +use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId, IsAsync, YieldSource}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -68,20 +68,18 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAsync { 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", - ); - } + if !span.from_expansion() && fn_kind.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/methods.rs b/tests/ui/methods.rs index 9805097084d3..1970c2eae531 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -15,6 +15,7 @@ clippy::use_self, clippy::useless_format, clippy::wrong_self_convention, + clippy::unused_async, clippy::unused_self, unused )] diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 6be38b24fbda..b63672dd6fdb 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -1,5 +1,5 @@ error: methods called `new` usually return `Self` - --> $DIR/methods.rs:103:5 + --> $DIR/methods.rs:104:5 | LL | / fn new() -> i32 { LL | | 0 @@ -9,7 +9,7 @@ LL | | } = note: `-D clippy::new-ret-no-self` implied by `-D warnings` error: called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(..)` instead - --> $DIR/methods.rs:124:13 + --> $DIR/methods.rs:125:13 | LL | let _ = v.iter().filter(|&x| { | _____________^ diff --git a/tests/ui/should_impl_trait/corner_cases.rs b/tests/ui/should_impl_trait/corner_cases.rs index 1ccb0a1d167d..50999c6f2198 100644 --- a/tests/ui/should_impl_trait/corner_cases.rs +++ b/tests/ui/should_impl_trait/corner_cases.rs @@ -8,7 +8,8 @@ clippy::missing_safety_doc, clippy::wrong_self_convention, clippy::missing_panics_doc, - clippy::return_self_not_must_use + clippy::return_self_not_must_use, + clippy::unused_async )] use std::ops::Mul; diff --git a/tests/ui/unused_async.rs b/tests/ui/unused_async.rs index 2a3a506a57b1..4ca7f29b34cd 100644 --- a/tests/ui/unused_async.rs +++ b/tests/ui/unused_async.rs @@ -1,5 +1,8 @@ #![warn(clippy::unused_async)] +use std::future::Future; +use std::pin::Pin; + async fn foo() -> i32 { 4 } @@ -8,6 +11,37 @@ async fn bar() -> i32 { foo().await } +struct S; + +impl S { + async fn unused(&self) -> i32 { + 1 + } + + async fn used(&self) -> i32 { + self.unused().await + } +} + +trait AsyncTrait { + fn trait_method() -> Pin>>; +} + +macro_rules! async_trait_impl { + () => { + impl AsyncTrait for S { + fn trait_method() -> Pin>> { + async fn unused() -> i32 { + 5 + } + + Box::pin(unused()) + } + } + }; +} +async_trait_impl!(); + fn main() { foo(); bar(); diff --git a/tests/ui/unused_async.stderr b/tests/ui/unused_async.stderr index cc6096d65d9f..8b8ad065a4ca 100644 --- a/tests/ui/unused_async.stderr +++ b/tests/ui/unused_async.stderr @@ -1,5 +1,5 @@ error: unused `async` for function with no await statements - --> $DIR/unused_async.rs:3:1 + --> $DIR/unused_async.rs:6:1 | LL | / async fn foo() -> i32 { LL | | 4 @@ -9,5 +9,15 @@ LL | | } = note: `-D clippy::unused-async` implied by `-D warnings` = help: consider removing the `async` from this function -error: aborting due to previous error +error: unused `async` for function with no await statements + --> $DIR/unused_async.rs:17:5 + | +LL | / async fn unused(&self) -> i32 { +LL | | 1 +LL | | } + | |_____^ + | + = help: consider removing the `async` from this function + +error: aborting due to 2 previous errors