//@run-rustfix #![allow(unused, clippy::manual_async_fn)] #![warn(clippy::redundant_async_block)] use std::future::Future; async fn func1(n: usize) -> usize { n + 1 } async fn func2() -> String { let s = String::from("some string"); let f = async { (*s).to_owned() }; let x = async { f.await }; x.await } fn main() { let fut1 = async { 17 }; // Lint let fut2 = async { fut1.await }; let fut1 = async { 25 }; // Lint let fut2 = async move { fut1.await }; // Lint let fut = async { async { 42 }.await }; // Do not lint: not a single expression let fut = async { func1(10).await; func2().await }; // Do not lint: expression contains `.await` let fut = async { func1(func2().await.len()).await }; } #[allow(clippy::let_and_return)] fn capture_local() -> impl Future { let fut = async { 17 }; // Lint async move { fut.await } } fn capture_local_closure(s: &str) -> impl Future { let f = move || std::future::ready(s); // Do not lint: `f` would not live long enough async move { f().await } } #[allow(clippy::let_and_return)] fn capture_arg(s: &str) -> impl Future { let fut = async move { s }; // Lint async move { fut.await } } fn capture_future_arg(f: impl Future) -> impl Future { // Lint async { f.await } } fn capture_func_result(f: FN) -> impl Future where F: Future, FN: FnOnce() -> F, { // Do not lint, as f() would be evaluated prematurely async { f().await } } fn double_future(f: impl Future>) -> impl Future { // Do not lint, we will get a `.await` outside a `.async` async { f.await.await } } fn await_in_async(f: F) -> impl Future where F: FnOnce() -> R, R: Future, { // Lint async { async { f().await + 1 }.await } } #[derive(Debug, Clone)] struct F {} impl F { async fn run(&self) {} } pub async fn run() { let f = F {}; let c = f.clone(); // Do not lint: `c` would not live long enough spawn(async move { c.run().await }); let _f = f; } fn spawn(_: F) {} async fn work(_: &str) {} fn capture() { let val = "Hello World".to_owned(); // Do not lint: `val` would not live long enough spawn(async { work(&{ val }).await }); } fn await_from_macro() -> impl Future { macro_rules! mac { ($e:expr) => { $e.await }; } // Do not lint: the macro may change in the future // or return different things depending on its argument async { mac!(async { 42 }) } } fn async_expr_from_macro() -> impl Future { macro_rules! mac { () => { async { 42 } }; } // Do not lint: the macro may change in the future async { mac!().await } } fn async_expr_from_macro_deep() -> impl Future { macro_rules! mac { () => { async { 42 } }; } // Do not lint: the macro may change in the future async { ({ mac!() }).await } } fn all_from_macro() -> impl Future { macro_rules! mac { () => { // Lint async { async { 42 }.await } }; } mac!() } fn parts_from_macro() -> impl Future { macro_rules! mac { ($e: expr) => { // Do not lint: `$e` might not always be side-effect free async { $e.await } }; } mac!(async { 42 }) } fn safe_parts_from_macro() -> impl Future { macro_rules! mac { ($e: expr) => { // Lint async { async { $e }.await } }; } mac!(42) } fn parts_from_macro_deep() -> impl Future { macro_rules! mac { ($e: expr) => { // Do not lint: `$e` might not always be side-effect free async { ($e,).0.await } }; } let f = std::future::ready(42); mac!(f) } fn await_from_macro_deep() -> impl Future { macro_rules! mac { ($e:expr) => {{ $e }.await}; } // Do not lint: the macro may change in the future // or return different things depending on its argument async { mac!(async { 42 }) } }