diff --git a/clippy_lints/src/redundant_async_block.rs b/clippy_lints/src/redundant_async_block.rs index 19d9d64b31e..11007450a16 100644 --- a/clippy_lints/src/redundant_async_block.rs +++ b/clippy_lints/src/redundant_async_block.rs @@ -3,6 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::peel_blocks; use clippy_utils::source::{snippet, walk_span_to_context}; +use clippy_utils::ty::implements_trait; use clippy_utils::visitors::for_each_expr; use rustc_errors::Applicability; use rustc_hir::{Closure, CoroutineKind, CoroutineSource, Expr, ExprKind, MatchSource}; @@ -49,6 +50,9 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { let Some(expr) = desugar_await(peel_blocks(body_expr)) && // The await prefix must not come from a macro as its content could change in the future. expr.span.eq_ctxt(body_expr.span) && + // The await prefix must implement Future, as implementing IntoFuture is not enough. + let Some(future_trait) = cx.tcx.lang_items().future_trait() && + implements_trait(cx, cx.typeck_results().expr_ty(expr), future_trait, &[]) && // An async block does not have immediate side-effects from a `.await` point-of-view. (!expr.can_have_side_effects() || desugar_async_block(cx, expr).is_some()) && let Some(shortened_span) = walk_span_to_context(expr.span, span.ctxt()) diff --git a/tests/ui/redundant_async_block.fixed b/tests/ui/redundant_async_block.fixed index d492ea1be75..a1875c1c06e 100644 --- a/tests/ui/redundant_async_block.fixed +++ b/tests/ui/redundant_async_block.fixed @@ -1,7 +1,7 @@ #![allow(unused, clippy::manual_async_fn)] #![warn(clippy::redundant_async_block)] -use std::future::Future; +use std::future::{Future, IntoFuture}; async fn func1(n: usize) -> usize { n + 1 @@ -189,3 +189,9 @@ fn await_from_macro_deep() -> impl Future { // or return different things depending on its argument async { mac!(async { 42 }) } } + +// Issue 11959 +fn from_into_future(a: impl IntoFuture) -> impl Future { + // Do not lint: `a` is not equivalent to this expression + async { a.await } +} diff --git a/tests/ui/redundant_async_block.rs b/tests/ui/redundant_async_block.rs index dd96e141006..bb43403a043 100644 --- a/tests/ui/redundant_async_block.rs +++ b/tests/ui/redundant_async_block.rs @@ -1,7 +1,7 @@ #![allow(unused, clippy::manual_async_fn)] #![warn(clippy::redundant_async_block)] -use std::future::Future; +use std::future::{Future, IntoFuture}; async fn func1(n: usize) -> usize { n + 1 @@ -189,3 +189,9 @@ macro_rules! mac { // or return different things depending on its argument async { mac!(async { 42 }) } } + +// Issue 11959 +fn from_into_future(a: impl IntoFuture) -> impl Future { + // Do not lint: `a` is not equivalent to this expression + async { a.await } +}