From 2169c1630ca9262a1b01a5ea2fdc8468f39ec841 Mon Sep 17 00:00:00 2001 From: durationextender Date: Fri, 5 Jun 2026 17:46:50 +0200 Subject: [PATCH] fixes issue 17162 false positive for never type impls --- clippy_lints/src/unused_async.rs | 20 ++++++++++++++------ tests/ui/unused_async_trait_impl.fixed | 12 ++++++++++++ tests/ui/unused_async_trait_impl.rs | 11 +++++++++++ tests/ui/unused_async_trait_impl.stderr | 10 +++++----- 4 files changed, 42 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/unused_async.rs b/clippy_lints/src/unused_async.rs index 456b98e6459d..b351fa084aa8 100644 --- a/clippy_lints/src/unused_async.rs +++ b/clippy_lints/src/unused_async.rs @@ -257,13 +257,21 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAsync { visitor.visit_nested_body(body_id); if !visitor.found_await - && let Some(builtin_crate) = clippy_utils::std_or_core(cx) - && let Some(inner) = unpack_async_fn_body(cx, body) - // Find the tail expression contained in the async fn (if any), - // which will be wrapped in std::future::ready. - && let ExprKind::Block(block, _) = inner.kind - && let Some(tail_expr) = block.expr + && let Some(builtin_crate) = clippy_utils::std_or_core(cx) + && let Some(inner) = unpack_async_fn_body(cx, body) + // Find the tail expression contained in the async fn (if any), + // which will be wrapped in std::future::ready. + && let ExprKind::Block(block, _) = inner.kind + && let Some(tail_expr) = block.expr { + let parent = cx.tcx.hir_get_parent_item(impl_item.hir_id()).def_id; + let item = cx.tcx.hir_expect_item(parent); + let self_ty = cx.tcx.type_of(item.owner_id).instantiate_identity().skip_norm_wip(); + //check if self.ty is never type ! if it is, then we don't want to lint because the function can + // never be called and thus doesn't need to be async + if self_ty.is_never() { + return; + } span_lint_and_then( cx, UNUSED_ASYNC_TRAIT_IMPL, diff --git a/tests/ui/unused_async_trait_impl.fixed b/tests/ui/unused_async_trait_impl.fixed index 384bb3449f90..1986105e2d76 100644 --- a/tests/ui/unused_async_trait_impl.fixed +++ b/tests/ui/unused_async_trait_impl.fixed @@ -1,4 +1,5 @@ #![warn(clippy::unused_async_trait_impl)] +#![feature(never_type)] trait HasAsyncMethod { async fn do_something() -> u32; @@ -107,3 +108,14 @@ mod macros { } } } + + +mod issue17162 { + // Should not lint when async trait impl is for `!` (never type) + + impl crate::HasAsyncMethod for ! { + async fn do_something() -> u32 { + unreachable!() + } + } +} \ No newline at end of file diff --git a/tests/ui/unused_async_trait_impl.rs b/tests/ui/unused_async_trait_impl.rs index 0a93635c264f..1a07dc9109df 100644 --- a/tests/ui/unused_async_trait_impl.rs +++ b/tests/ui/unused_async_trait_impl.rs @@ -1,4 +1,5 @@ #![warn(clippy::unused_async_trait_impl)] +#![feature(never_type)] trait HasAsyncMethod { async fn do_something() -> u32; @@ -107,3 +108,13 @@ mod macros { } } } + +mod issue17162 { + // Should not lint when async trait impl is for `!` (never type) + + impl crate::HasAsyncMethod for ! { + async fn do_something() -> u32 { + unreachable!() + } + } +} diff --git a/tests/ui/unused_async_trait_impl.stderr b/tests/ui/unused_async_trait_impl.stderr index 7265dc2dd059..1d4b54a4be61 100644 --- a/tests/ui/unused_async_trait_impl.stderr +++ b/tests/ui/unused_async_trait_impl.stderr @@ -1,5 +1,5 @@ error: unused `async` for async trait impl function with no `.await` statements - --> tests/ui/unused_async_trait_impl.rs:16:9 + --> tests/ui/unused_async_trait_impl.rs:17:9 | LL | / async fn do_something() -> u32 { LL | | @@ -18,7 +18,7 @@ LL ~ std::future::ready(1) | error: unused `async` for async trait impl function with no `.await` statements - --> tests/ui/unused_async_trait_impl.rs:40:9 + --> tests/ui/unused_async_trait_impl.rs:41:9 | LL | / async fn do_something() -> u32 { LL | | @@ -40,7 +40,7 @@ LL ~ std::future::ready(x) | error: unused `async` for async trait impl function with no `.await` statements - --> tests/ui/unused_async_trait_impl.rs:63:9 + --> tests/ui/unused_async_trait_impl.rs:64:9 | LL | / async fn do_something() -> u32 { LL | | @@ -57,7 +57,7 @@ LL ~ std::future::ready(5) | error: unused `async` for async trait impl function with no `.await` statements - --> tests/ui/unused_async_trait_impl.rs:97:9 + --> tests/ui/unused_async_trait_impl.rs:98:9 | LL | / async fn do_something() -> vec_ty!(u32) { LL | | @@ -74,7 +74,7 @@ LL ~ std::future::ready(Vec::new()) | error: unused `async` for async trait impl function with no `.await` statements - --> tests/ui/unused_async_trait_impl.rs:104:9 + --> tests/ui/unused_async_trait_impl.rs:105:9 | LL | / async fn do_something() -> Vec { LL | |