diff --git a/clippy_lints/src/unused_async.rs b/clippy_lints/src/unused_async.rs index a1f08cf6623b..0ed64fd1f8ef 100644 --- a/clippy_lints/src/unused_async.rs +++ b/clippy_lints/src/unused_async.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::is_def_id_trait_method; use rustc_hir::def::DefKind; use rustc_hir::intravisit::{FnKind, Visitor, walk_expr, walk_fn}; -use rustc_hir::{Body, Expr, ExprKind, FnDecl, Node, YieldSource}; +use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId, Node, YieldSource}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_session::impl_lint_pass; @@ -137,17 +137,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAsync { } } - fn check_path(&mut self, cx: &LateContext<'tcx>, path: &rustc_hir::Path<'tcx>, hir_id: rustc_hir::HirId) { - fn is_node_func_call(node: Node<'_>, expected_receiver: Span) -> bool { - matches!( - node, - Node::Expr(Expr { - kind: ExprKind::Call(Expr { span, .. }, _) | ExprKind::MethodCall(_, Expr { span, .. }, ..), - .. - }) if *span == expected_receiver - ) - } - + fn check_path(&mut self, cx: &LateContext<'tcx>, path: &rustc_hir::Path<'tcx>, hir_id: HirId) { // Find paths to local async functions that aren't immediately called. // E.g. `async fn f() {}; let x = f;` // Depending on how `x` is used, f's asyncness might be required despite not having any `await` @@ -156,7 +146,14 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAsync { && let Some(local_def_id) = def_id.as_local() && cx.tcx.def_kind(def_id) == DefKind::Fn && cx.tcx.asyncness(def_id).is_async() - && !is_node_func_call(cx.tcx.parent_hir_node(hir_id), path.span) + && let parent = cx.tcx.parent_hir_node(hir_id) + && !matches!( + parent, + Node::Expr(Expr { + kind: ExprKind::Call(Expr { span, .. }, _), + .. + }) if *span == path.span + ) { self.async_fns_as_value.insert(local_def_id); } diff --git a/tests/ui/unused_async.rs b/tests/ui/unused_async.rs index 7ec8a3adb4cd..838d6f0aa971 100644 --- a/tests/ui/unused_async.rs +++ b/tests/ui/unused_async.rs @@ -55,6 +55,22 @@ mod issue9695 { } } +mod issue13466 { + use std::future::Future; + + struct Wrap(F); + impl From for Wrap { + fn from(f: F) -> Self { + Self(f) + } + } + fn takes_fut Fut, Fut: Future>(_: Wrap) {} + async fn unused_async() {} + fn fp() { + takes_fut(unused_async.into()); + } +} + async fn foo() -> i32 { //~^ ERROR: unused `async` for function with no await statements 4 diff --git a/tests/ui/unused_async.stderr b/tests/ui/unused_async.stderr index 337c650e029f..4811df63658a 100644 --- a/tests/ui/unused_async.stderr +++ b/tests/ui/unused_async.stderr @@ -27,7 +27,7 @@ LL | async fn f3() {} = help: consider removing the `async` from this function error: unused `async` for function with no await statements - --> tests/ui/unused_async.rs:58:1 + --> tests/ui/unused_async.rs:74:1 | LL | / async fn foo() -> i32 { LL | | @@ -38,7 +38,7 @@ LL | | } = help: consider removing the `async` from this function error: unused `async` for function with no await statements - --> tests/ui/unused_async.rs:70:5 + --> tests/ui/unused_async.rs:86:5 | LL | / async fn unused(&self) -> i32 { LL | |