summaryrefslogtreecommitdiffstats
path: root/src/tools/clippy/tests/ui/redundant_async_block.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/clippy/tests/ui/redundant_async_block.rs')
-rw-r--r--src/tools/clippy/tests/ui/redundant_async_block.rs193
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 }) }
+}