diff options
Diffstat (limited to 'src/tools/clippy/tests/ui/redundant_async_block.rs')
-rw-r--r-- | src/tools/clippy/tests/ui/redundant_async_block.rs | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/src/tools/clippy/tests/ui/redundant_async_block.rs b/src/tools/clippy/tests/ui/redundant_async_block.rs new file mode 100644 index 000000000..7ae235583 --- /dev/null +++ b/src/tools/clippy/tests/ui/redundant_async_block.rs @@ -0,0 +1,193 @@ +// 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<Output = i32> { + let fut = async { 17 }; + // Lint + async move { fut.await } +} + +fn capture_local_closure(s: &str) -> impl Future<Output = &str> { + 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<Output = &str> { + let fut = async move { s }; + // Lint + async move { fut.await } +} + +fn capture_future_arg<T>(f: impl Future<Output = T>) -> impl Future<Output = T> { + // Lint + async { f.await } +} + +fn capture_func_result<FN, F, T>(f: FN) -> impl Future<Output = T> +where + F: Future<Output = T>, + FN: FnOnce() -> F, +{ + // Do not lint, as f() would be evaluated prematurely + async { f().await } +} + +fn double_future(f: impl Future<Output = impl Future<Output = u32>>) -> impl Future<Output = u32> { + // Do not lint, we will get a `.await` outside a `.async` + async { f.await.await } +} + +fn await_in_async<F, R>(f: F) -> impl Future<Output = u32> +where + F: FnOnce() -> R, + R: Future<Output = u32>, +{ + // 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: Future + 'static>(_: 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<Output = u32> { + 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<Output = u32> { + 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<Output = u32> { + macro_rules! mac { + () => { + async { 42 } + }; + } + // Do not lint: the macro may change in the future + async { ({ mac!() }).await } +} + +fn all_from_macro() -> impl Future<Output = u32> { + macro_rules! mac { + () => { + // Lint + async { async { 42 }.await } + }; + } + mac!() +} + +fn parts_from_macro() -> impl Future<Output = u32> { + 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<Output = u32> { + macro_rules! mac { + ($e: expr) => { + // Lint + async { async { $e }.await } + }; + } + mac!(42) +} + +fn parts_from_macro_deep() -> impl Future<Output = u32> { + 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<Output = u32> { + 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 }) } +} |