about summary refs log tree commit diff
path: root/tests/ui/async-await/in-trait
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ui/async-await/in-trait')
-rw-r--r--tests/ui/async-await/in-trait/async-associated-types.rs24
-rw-r--r--tests/ui/async-await/in-trait/async-associated-types2.rs30
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.rs21
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr17
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared-boxed.rs21
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr11
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared-extra.rs37
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared-in-trait.rs21
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared-manual.rs29
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared-manual.stderr11
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared.rs20
-rw-r--r--tests/ui/async-await/in-trait/async-example.rs32
-rw-r--r--tests/ui/async-await/in-trait/async-generics-and-bounds.rs21
-rw-r--r--tests/ui/async-await/in-trait/async-generics-and-bounds.stderr37
-rw-r--r--tests/ui/async-await/in-trait/async-generics.rs18
-rw-r--r--tests/ui/async-await/in-trait/async-generics.stderr37
-rw-r--r--tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs19
-rw-r--r--tests/ui/async-await/in-trait/async-lifetimes.rs17
-rw-r--r--tests/ui/async-await/in-trait/async-recursive-generic.rs21
-rw-r--r--tests/ui/async-await/in-trait/async-recursive-generic.stderr12
-rw-r--r--tests/ui/async-await/in-trait/async-recursive.rs21
-rw-r--r--tests/ui/async-await/in-trait/async-recursive.stderr12
-rw-r--r--tests/ui/async-await/in-trait/bad-signatures.rs16
-rw-r--r--tests/ui/async-await/in-trait/bad-signatures.stderr26
-rw-r--r--tests/ui/async-await/in-trait/early-bound-1.rs17
-rw-r--r--tests/ui/async-await/in-trait/early-bound-2.rs15
-rw-r--r--tests/ui/async-await/in-trait/fn-not-async-err.rs17
-rw-r--r--tests/ui/async-await/in-trait/fn-not-async-err.stderr11
-rw-r--r--tests/ui/async-await/in-trait/fn-not-async-err2.rs19
-rw-r--r--tests/ui/async-await/in-trait/fn-not-async-err2.stderr12
-rw-r--r--tests/ui/async-await/in-trait/implied-bounds.rs13
-rw-r--r--tests/ui/async-await/in-trait/issue-102138.rs46
-rw-r--r--tests/ui/async-await/in-trait/issue-102219.rs10
-rw-r--r--tests/ui/async-await/in-trait/issue-102310.rs15
-rw-r--r--tests/ui/async-await/in-trait/issue-104678.rs31
-rw-r--r--tests/ui/async-await/in-trait/lifetime-mismatch.rs20
-rw-r--r--tests/ui/async-await/in-trait/lifetime-mismatch.stderr21
-rw-r--r--tests/ui/async-await/in-trait/nested-rpit.rs17
-rw-r--r--tests/ui/async-await/in-trait/object-safety.rs13
-rw-r--r--tests/ui/async-await/in-trait/object-safety.stderr27
-rw-r--r--tests/ui/async-await/in-trait/return-type-suggestion.rs14
-rw-r--r--tests/ui/async-await/in-trait/return-type-suggestion.stderr23
42 files changed, 872 insertions, 0 deletions
diff --git a/tests/ui/async-await/in-trait/async-associated-types.rs b/tests/ui/async-await/in-trait/async-associated-types.rs
new file mode 100644
index 00000000000..974f5aaff83
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-associated-types.rs
@@ -0,0 +1,24 @@
+// check-pass
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![feature(impl_trait_projections)]
+#![allow(incomplete_features)]
+
+use std::fmt::Debug;
+
+trait MyTrait<'a, 'b, T> where Self: 'a, T: Debug + Sized + 'b {
+    type MyAssoc;
+
+    async fn foo(&'a self, key: &'b T) -> Self::MyAssoc;
+}
+
+impl<'a, 'b, T: Debug + Sized + 'b, U: 'a> MyTrait<'a, 'b, T> for U {
+    type MyAssoc = (&'a U, &'b T);
+
+    async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) {
+        (self, key)
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/async-associated-types2.rs b/tests/ui/async-await/in-trait/async-associated-types2.rs
new file mode 100644
index 00000000000..e546a0579c6
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-associated-types2.rs
@@ -0,0 +1,30 @@
+// check-pass
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![feature(type_alias_impl_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+
+trait MyTrait {
+    type Fut<'a>: Future<Output = i32>
+    where
+        Self: 'a;
+
+    fn foo<'a>(&'a self) -> Self::Fut<'a>;
+}
+
+impl MyTrait for i32 {
+    type Fut<'a> = impl Future<Output = i32> + 'a
+    where
+        Self: 'a;
+
+    fn foo<'a>(&'a self) -> Self::Fut<'a> {
+        async {
+            *self
+        }
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.rs b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.rs
new file mode 100644
index 00000000000..38ba297189c
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.rs
@@ -0,0 +1,21 @@
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+use std::pin::Pin;
+
+trait MyTrait {
+    fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>>;
+}
+
+impl MyTrait for i32 {
+    async fn foo(&self) -> i32 {
+        //~^ ERROR method `foo` has an incompatible type for trait
+        *self
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr
new file mode 100644
index 00000000000..13e7222551a
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr
@@ -0,0 +1,17 @@
+error[E0053]: method `foo` has an incompatible type for trait
+  --> $DIR/async-example-desugared-boxed-in-trait.rs:15:28
+   |
+LL |     async fn foo(&self) -> i32 {
+   |                            ^^^ expected struct `Pin`, found opaque type
+   |
+note: type in trait
+  --> $DIR/async-example-desugared-boxed-in-trait.rs:11:22
+   |
+LL |     fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>>;
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: expected signature `fn(&i32) -> Pin<Box<dyn Future<Output = i32>>>`
+              found signature `fn(&i32) -> impl Future<Output = i32>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs b/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs
new file mode 100644
index 00000000000..1b1b3cffd58
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs
@@ -0,0 +1,21 @@
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+use std::pin::Pin;
+
+trait MyTrait {
+    async fn foo(&self) -> i32;
+}
+
+impl MyTrait for i32 {
+    fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>> {
+        //~^ ERROR method `foo` should be async
+        Box::pin(async { *self })
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr b/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr
new file mode 100644
index 00000000000..60fa534a64f
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr
@@ -0,0 +1,11 @@
+error: method `foo` should be async because the method from the trait is async
+  --> $DIR/async-example-desugared-boxed.rs:15:5
+   |
+LL |     async fn foo(&self) -> i32;
+   |     --------------------------- required because the trait method is async
+...
+LL |     fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>> {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/in-trait/async-example-desugared-extra.rs b/tests/ui/async-await/in-trait/async-example-desugared-extra.rs
new file mode 100644
index 00000000000..81e1e59a362
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-example-desugared-extra.rs
@@ -0,0 +1,37 @@
+// check-pass
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+use std::pin::Pin;
+use std::task::Poll;
+
+trait MyTrait {
+    async fn foo(&self) -> i32;
+}
+
+#[derive(Clone)]
+struct MyFuture(i32);
+
+impl Future for MyFuture {
+    type Output = i32;
+    fn poll(
+        self: Pin<&mut Self>,
+        _: &mut std::task::Context<'_>,
+    ) -> Poll<<Self as Future>::Output> {
+        Poll::Ready(self.0)
+    }
+}
+
+impl MyTrait for i32 {
+    // FIXME: this should eventually require `#[refine]` to compile, because it also provides
+    // `Clone`.
+    fn foo(&self) -> impl Future<Output = i32> + Clone {
+        MyFuture(*self)
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/async-example-desugared-in-trait.rs b/tests/ui/async-await/in-trait/async-example-desugared-in-trait.rs
new file mode 100644
index 00000000000..feeda719e03
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-example-desugared-in-trait.rs
@@ -0,0 +1,21 @@
+// check-pass
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+
+trait MyTrait {
+    fn foo(&self) -> impl Future<Output = i32> + '_;
+}
+
+impl MyTrait for i32 {
+    // This will break once a PR that implements #102745 is merged
+    async fn foo(&self) -> i32 {
+        *self
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/async-example-desugared-manual.rs b/tests/ui/async-await/in-trait/async-example-desugared-manual.rs
new file mode 100644
index 00000000000..71473e7455f
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-example-desugared-manual.rs
@@ -0,0 +1,29 @@
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+use std::task::Poll;
+
+trait MyTrait {
+    async fn foo(&self) -> i32;
+}
+
+struct MyFuture;
+impl Future for MyFuture {
+    type Output = i32;
+    fn poll(self: std::pin::Pin<&mut Self>, _: &mut std::task::Context<'_>) -> Poll<Self::Output> {
+        Poll::Ready(0)
+    }
+}
+
+impl MyTrait for u32 {
+    fn foo(&self) -> MyFuture {
+        //~^ ERROR method `foo` should be async
+        MyFuture
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr b/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr
new file mode 100644
index 00000000000..567a36a86d1
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr
@@ -0,0 +1,11 @@
+error: method `foo` should be async because the method from the trait is async
+  --> $DIR/async-example-desugared-manual.rs:23:5
+   |
+LL |     async fn foo(&self) -> i32;
+   |     --------------------------- required because the trait method is async
+...
+LL |     fn foo(&self) -> MyFuture {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/in-trait/async-example-desugared.rs b/tests/ui/async-await/in-trait/async-example-desugared.rs
new file mode 100644
index 00000000000..fb92ec78674
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-example-desugared.rs
@@ -0,0 +1,20 @@
+// check-pass
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+
+trait MyTrait {
+    async fn foo(&self) -> i32;
+}
+
+impl MyTrait for i32 {
+    fn foo(&self) -> impl Future<Output = i32> + '_ {
+        async { *self }
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/async-example.rs b/tests/ui/async-await/in-trait/async-example.rs
new file mode 100644
index 00000000000..abf94ef7450
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-example.rs
@@ -0,0 +1,32 @@
+// check-pass
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+trait MyTrait {
+    async fn foo(&self) -> i32;
+    async fn bar(&self) -> i32;
+}
+
+impl MyTrait for i32 {
+    async fn foo(&self) -> i32 {
+        *self
+    }
+
+    async fn bar(&self) -> i32 {
+        self.foo().await
+    }
+}
+
+fn main() {
+    let x = 5;
+    // Calling from non-async context
+    let _ = x.foo();
+    let _ = x.bar();
+    // Calling from async block in non-async context
+    async {
+        let _: i32 = x.foo().await;
+        let _: i32 = x.bar().await;
+    };
+}
diff --git a/tests/ui/async-await/in-trait/async-generics-and-bounds.rs b/tests/ui/async-await/in-trait/async-generics-and-bounds.rs
new file mode 100644
index 00000000000..a73d55adfec
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-generics-and-bounds.rs
@@ -0,0 +1,21 @@
+// check-fail
+// known-bug: #102682
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+use std::fmt::Debug;
+use std::hash::Hash;
+
+trait MyTrait<T, U> {
+    async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+}
+
+impl<T, U> MyTrait<T, U> for (T, U) {
+    async fn foo(&self) -> &(T, U) {
+        self
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr b/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr
new file mode 100644
index 00000000000..f1f0d7e5907
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr
@@ -0,0 +1,37 @@
+error[E0311]: the parameter type `U` may not live long enough
+  --> $DIR/async-generics-and-bounds.rs:12:28
+   |
+LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+   |                            ^^^^^^^
+   |
+note: the parameter type `U` must be valid for the anonymous lifetime defined here...
+  --> $DIR/async-generics-and-bounds.rs:12:18
+   |
+LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+   |                  ^^^^^
+note: ...so that the reference type `&(T, U)` does not outlive the data it points at
+  --> $DIR/async-generics-and-bounds.rs:12:28
+   |
+LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+   |                            ^^^^^^^
+
+error[E0311]: the parameter type `T` may not live long enough
+  --> $DIR/async-generics-and-bounds.rs:12:28
+   |
+LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+   |                            ^^^^^^^
+   |
+note: the parameter type `T` must be valid for the anonymous lifetime defined here...
+  --> $DIR/async-generics-and-bounds.rs:12:18
+   |
+LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+   |                  ^^^^^
+note: ...so that the reference type `&(T, U)` does not outlive the data it points at
+  --> $DIR/async-generics-and-bounds.rs:12:28
+   |
+LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+   |                            ^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0311`.
diff --git a/tests/ui/async-await/in-trait/async-generics.rs b/tests/ui/async-await/in-trait/async-generics.rs
new file mode 100644
index 00000000000..67000e5770e
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-generics.rs
@@ -0,0 +1,18 @@
+// check-fail
+// known-bug: #102682
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+trait MyTrait<T, U> {
+    async fn foo(&self) -> &(T, U);
+}
+
+impl<T, U> MyTrait<T, U> for (T, U) {
+    async fn foo(&self) -> &(T, U) {
+        self
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/async-generics.stderr b/tests/ui/async-await/in-trait/async-generics.stderr
new file mode 100644
index 00000000000..2f05564564c
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-generics.stderr
@@ -0,0 +1,37 @@
+error[E0311]: the parameter type `U` may not live long enough
+  --> $DIR/async-generics.rs:9:28
+   |
+LL |     async fn foo(&self) -> &(T, U);
+   |                            ^^^^^^^
+   |
+note: the parameter type `U` must be valid for the anonymous lifetime defined here...
+  --> $DIR/async-generics.rs:9:18
+   |
+LL |     async fn foo(&self) -> &(T, U);
+   |                  ^^^^^
+note: ...so that the reference type `&(T, U)` does not outlive the data it points at
+  --> $DIR/async-generics.rs:9:28
+   |
+LL |     async fn foo(&self) -> &(T, U);
+   |                            ^^^^^^^
+
+error[E0311]: the parameter type `T` may not live long enough
+  --> $DIR/async-generics.rs:9:28
+   |
+LL |     async fn foo(&self) -> &(T, U);
+   |                            ^^^^^^^
+   |
+note: the parameter type `T` must be valid for the anonymous lifetime defined here...
+  --> $DIR/async-generics.rs:9:18
+   |
+LL |     async fn foo(&self) -> &(T, U);
+   |                  ^^^^^
+note: ...so that the reference type `&(T, U)` does not outlive the data it points at
+  --> $DIR/async-generics.rs:9:28
+   |
+LL |     async fn foo(&self) -> &(T, U);
+   |                            ^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0311`.
diff --git a/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs b/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs
new file mode 100644
index 00000000000..d5481d277e4
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs
@@ -0,0 +1,19 @@
+// check-pass
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+use std::fmt::Debug;
+
+trait MyTrait<'a, 'b, T> {
+    async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T) where T: Debug + Sized;
+}
+
+impl<'a, 'b, T, U> MyTrait<'a, 'b, T> for U {
+    async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) {
+        (self, key)
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/async-lifetimes.rs b/tests/ui/async-await/in-trait/async-lifetimes.rs
new file mode 100644
index 00000000000..f298e45d239
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-lifetimes.rs
@@ -0,0 +1,17 @@
+// check-pass
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+trait MyTrait<'a, 'b, T> {
+    async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T);
+}
+
+impl<'a, 'b, T, U> MyTrait<'a, 'b, T> for U {
+    async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) {
+        (self, key)
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/async-recursive-generic.rs b/tests/ui/async-await/in-trait/async-recursive-generic.rs
new file mode 100644
index 00000000000..6839abd381c
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-recursive-generic.rs
@@ -0,0 +1,21 @@
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+trait MyTrait<T> {
+    async fn foo_recursive(&self, n: usize) -> T;
+}
+
+impl<T> MyTrait<T> for T where T: Copy {
+    async fn foo_recursive(&self, n: usize) -> T {
+        //~^ ERROR recursion in an `async fn` requires boxing
+        if n > 0 {
+            self.foo_recursive(n - 1).await
+        } else {
+            *self
+        }
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/async-recursive-generic.stderr b/tests/ui/async-await/in-trait/async-recursive-generic.stderr
new file mode 100644
index 00000000000..cab173bdd5b
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-recursive-generic.stderr
@@ -0,0 +1,12 @@
+error[E0733]: recursion in an `async fn` requires boxing
+  --> $DIR/async-recursive-generic.rs:11:48
+   |
+LL |     async fn foo_recursive(&self, n: usize) -> T {
+   |                                                ^ recursive `async fn`
+   |
+   = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
+   = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0733`.
diff --git a/tests/ui/async-await/in-trait/async-recursive.rs b/tests/ui/async-await/in-trait/async-recursive.rs
new file mode 100644
index 00000000000..61119f8095b
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-recursive.rs
@@ -0,0 +1,21 @@
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+trait MyTrait {
+    async fn foo_recursive(&self, n: usize) -> i32;
+}
+
+impl MyTrait for i32 {
+    async fn foo_recursive(&self, n: usize) -> i32 {
+        //~^ ERROR recursion in an `async fn` requires boxing
+        if n > 0 {
+            self.foo_recursive(n - 1).await
+        } else {
+            *self
+        }
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/async-recursive.stderr b/tests/ui/async-await/in-trait/async-recursive.stderr
new file mode 100644
index 00000000000..9feff37b3fe
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-recursive.stderr
@@ -0,0 +1,12 @@
+error[E0733]: recursion in an `async fn` requires boxing
+  --> $DIR/async-recursive.rs:11:48
+   |
+LL |     async fn foo_recursive(&self, n: usize) -> i32 {
+   |                                                ^^^ recursive `async fn`
+   |
+   = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
+   = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0733`.
diff --git a/tests/ui/async-await/in-trait/bad-signatures.rs b/tests/ui/async-await/in-trait/bad-signatures.rs
new file mode 100644
index 00000000000..b86f1d1c135
--- /dev/null
+++ b/tests/ui/async-await/in-trait/bad-signatures.rs
@@ -0,0 +1,16 @@
+// edition:2021
+
+#![feature(async_fn_in_trait)]
+//~^ WARN the feature `async_fn_in_trait` is incomplete
+
+trait MyTrait {
+    async fn bar(&abc self);
+    //~^ ERROR expected identifier, found keyword `self`
+    //~| ERROR expected one of `:`, `@`, or `|`, found keyword `self`
+}
+
+impl MyTrait for () {
+    async fn bar(&self) {}
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/bad-signatures.stderr b/tests/ui/async-await/in-trait/bad-signatures.stderr
new file mode 100644
index 00000000000..e0ba7b53ec4
--- /dev/null
+++ b/tests/ui/async-await/in-trait/bad-signatures.stderr
@@ -0,0 +1,26 @@
+error: expected identifier, found keyword `self`
+  --> $DIR/bad-signatures.rs:7:23
+   |
+LL |     async fn bar(&abc self);
+   |                       ^^^^ expected identifier, found keyword
+
+error: expected one of `:`, `@`, or `|`, found keyword `self`
+  --> $DIR/bad-signatures.rs:7:23
+   |
+LL |     async fn bar(&abc self);
+   |                  -----^^^^
+   |                  |    |
+   |                  |    expected one of `:`, `@`, or `|`
+   |                  help: declare the type after the parameter binding: `<identifier>: <type>`
+
+warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/bad-signatures.rs:3:12
+   |
+LL | #![feature(async_fn_in_trait)]
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
diff --git a/tests/ui/async-await/in-trait/early-bound-1.rs b/tests/ui/async-await/in-trait/early-bound-1.rs
new file mode 100644
index 00000000000..6b3b142014b
--- /dev/null
+++ b/tests/ui/async-await/in-trait/early-bound-1.rs
@@ -0,0 +1,17 @@
+// check-pass
+// edition:2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+pub trait Foo {
+    async fn foo(&mut self);
+}
+
+struct MyFoo<'a>(&'a mut ());
+
+impl<'a> Foo for MyFoo<'a> {
+    async fn foo(&mut self) {}
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/early-bound-2.rs b/tests/ui/async-await/in-trait/early-bound-2.rs
new file mode 100644
index 00000000000..270443229b0
--- /dev/null
+++ b/tests/ui/async-await/in-trait/early-bound-2.rs
@@ -0,0 +1,15 @@
+// check-pass
+// edition:2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+pub trait Foo {
+    async fn foo(&mut self);
+}
+
+impl<T: Foo> Foo for &mut T {
+    async fn foo(&mut self) {}
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/fn-not-async-err.rs b/tests/ui/async-await/in-trait/fn-not-async-err.rs
new file mode 100644
index 00000000000..9598d53bce8
--- /dev/null
+++ b/tests/ui/async-await/in-trait/fn-not-async-err.rs
@@ -0,0 +1,17 @@
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+trait MyTrait {
+    async fn foo(&self) -> i32;
+}
+
+impl MyTrait for i32 {
+    fn foo(&self) -> i32 {
+        //~^ ERROR: method `foo` should be async
+        *self
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/fn-not-async-err.stderr b/tests/ui/async-await/in-trait/fn-not-async-err.stderr
new file mode 100644
index 00000000000..579801d0f39
--- /dev/null
+++ b/tests/ui/async-await/in-trait/fn-not-async-err.stderr
@@ -0,0 +1,11 @@
+error: method `foo` should be async because the method from the trait is async
+  --> $DIR/fn-not-async-err.rs:11:5
+   |
+LL |     async fn foo(&self) -> i32;
+   |     --------------------------- required because the trait method is async
+...
+LL |     fn foo(&self) -> i32 {
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/in-trait/fn-not-async-err2.rs b/tests/ui/async-await/in-trait/fn-not-async-err2.rs
new file mode 100644
index 00000000000..2c4ed553580
--- /dev/null
+++ b/tests/ui/async-await/in-trait/fn-not-async-err2.rs
@@ -0,0 +1,19 @@
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+
+trait MyTrait {
+    async fn foo(&self) -> i32;
+}
+
+impl MyTrait for i32 {
+    fn foo(&self) -> impl Future<Output = i32> {
+        //~^ ERROR `impl Trait` only allowed in function and inherent method return types, not in `impl` method return [E0562]
+        async { *self }
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/fn-not-async-err2.stderr b/tests/ui/async-await/in-trait/fn-not-async-err2.stderr
new file mode 100644
index 00000000000..f591f184772
--- /dev/null
+++ b/tests/ui/async-await/in-trait/fn-not-async-err2.stderr
@@ -0,0 +1,12 @@
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `impl` method return
+  --> $DIR/fn-not-async-err2.rs:13:22
+   |
+LL |     fn foo(&self) -> impl Future<Output = i32> {
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0562`.
diff --git a/tests/ui/async-await/in-trait/implied-bounds.rs b/tests/ui/async-await/in-trait/implied-bounds.rs
new file mode 100644
index 00000000000..52bceb3cc5c
--- /dev/null
+++ b/tests/ui/async-await/in-trait/implied-bounds.rs
@@ -0,0 +1,13 @@
+// check-pass
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+trait TcpStack {
+    type Connection<'a>: Sized where Self: 'a;
+    fn connect<'a>(&'a self) -> Self::Connection<'a>;
+    async fn async_connect<'a>(&'a self) -> Self::Connection<'a>;
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/issue-102138.rs b/tests/ui/async-await/in-trait/issue-102138.rs
new file mode 100644
index 00000000000..f61b34ed99e
--- /dev/null
+++ b/tests/ui/async-await/in-trait/issue-102138.rs
@@ -0,0 +1,46 @@
+// check-pass
+// edition:2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+
+async fn yield_now() {}
+
+trait AsyncIterator {
+    type Item;
+    async fn next(&mut self) -> Option<Self::Item>;
+}
+
+struct YieldingRange {
+    counter: u32,
+    stop: u32,
+}
+
+impl AsyncIterator for YieldingRange {
+    type Item = u32;
+
+    async fn next(&mut self) -> Option<Self::Item> {
+        if self.counter == self.stop {
+            None
+        } else {
+            let c = self.counter;
+            self.counter += 1;
+            yield_now().await;
+            Some(c)
+        }
+    }
+}
+
+async fn async_main() {
+    let mut x = YieldingRange { counter: 0, stop: 10 };
+
+    while let Some(v) = x.next().await {
+        println!("Hi: {v}");
+    }
+}
+
+fn main() {
+    let _ = async_main();
+}
diff --git a/tests/ui/async-await/in-trait/issue-102219.rs b/tests/ui/async-await/in-trait/issue-102219.rs
new file mode 100644
index 00000000000..9a35f6515cb
--- /dev/null
+++ b/tests/ui/async-await/in-trait/issue-102219.rs
@@ -0,0 +1,10 @@
+// compile-flags:--crate-type=lib
+// edition:2021
+// check-pass
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+trait T {
+    async fn foo();
+}
diff --git a/tests/ui/async-await/in-trait/issue-102310.rs b/tests/ui/async-await/in-trait/issue-102310.rs
new file mode 100644
index 00000000000..49c3e9feeb4
--- /dev/null
+++ b/tests/ui/async-await/in-trait/issue-102310.rs
@@ -0,0 +1,15 @@
+// check-pass
+// edition:2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+pub trait SpiDevice {
+    async fn transaction<F, R>(&mut self);
+}
+
+impl SpiDevice for () {
+    async fn transaction<F, R>(&mut self) {}
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/issue-104678.rs b/tests/ui/async-await/in-trait/issue-104678.rs
new file mode 100644
index 00000000000..e396df4e5d1
--- /dev/null
+++ b/tests/ui/async-await/in-trait/issue-104678.rs
@@ -0,0 +1,31 @@
+// edition:2021
+// check-pass
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+pub trait Pool {
+    type Conn;
+
+    async fn async_callback<'a, F: FnOnce(&'a Self::Conn) -> Fut, Fut: Future<Output = ()>>(
+        &'a self,
+        callback: F,
+    ) -> ();
+}
+
+pub struct PoolImpl;
+pub struct ConnImpl;
+
+impl Pool for PoolImpl {
+    type Conn = ConnImpl;
+
+    async fn async_callback<'a, F: FnOnce(&'a Self::Conn) -> Fut, Fut: Future<Output = ()>>(
+        &'a self,
+        _callback: F,
+    ) -> () {
+        todo!()
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/lifetime-mismatch.rs b/tests/ui/async-await/in-trait/lifetime-mismatch.rs
new file mode 100644
index 00000000000..45ede193c0f
--- /dev/null
+++ b/tests/ui/async-await/in-trait/lifetime-mismatch.rs
@@ -0,0 +1,20 @@
+// edition:2021
+
+#![feature(async_fn_in_trait)]
+//~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+
+trait MyTrait {
+    async fn foo<'a>(&self);
+    async fn bar(&self);
+}
+
+impl MyTrait for i32 {
+    async fn foo(&self) {}
+    //~^ ERROR lifetime parameters or bounds on method `foo` do not match the trait declaration
+
+    async fn bar(&self) {
+        self.foo();
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/lifetime-mismatch.stderr b/tests/ui/async-await/in-trait/lifetime-mismatch.stderr
new file mode 100644
index 00000000000..d87adcc78b6
--- /dev/null
+++ b/tests/ui/async-await/in-trait/lifetime-mismatch.stderr
@@ -0,0 +1,21 @@
+warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/lifetime-mismatch.rs:3:12
+   |
+LL | #![feature(async_fn_in_trait)]
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration
+  --> $DIR/lifetime-mismatch.rs:12:17
+   |
+LL |     async fn foo<'a>(&self);
+   |                 ---- lifetimes in impl do not match this method in trait
+...
+LL |     async fn foo(&self) {}
+   |                 ^ lifetimes do not match method in trait
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0195`.
diff --git a/tests/ui/async-await/in-trait/nested-rpit.rs b/tests/ui/async-await/in-trait/nested-rpit.rs
new file mode 100644
index 00000000000..ae8e0aed0cc
--- /dev/null
+++ b/tests/ui/async-await/in-trait/nested-rpit.rs
@@ -0,0 +1,17 @@
+// check-pass
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+use std::marker::PhantomData;
+
+trait Lockable<K, V> {
+    async fn lock_all_entries(&self) -> impl Future<Output = Guard<'_>>;
+}
+
+struct Guard<'a>(PhantomData<&'a ()>);
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/object-safety.rs b/tests/ui/async-await/in-trait/object-safety.rs
new file mode 100644
index 00000000000..a8bc35f7e0c
--- /dev/null
+++ b/tests/ui/async-await/in-trait/object-safety.rs
@@ -0,0 +1,13 @@
+// edition:2021
+
+#![feature(async_fn_in_trait)]
+//~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+
+trait Foo {
+    async fn foo(&self);
+}
+
+fn main() {
+    let x: &dyn Foo = todo!();
+    //~^ ERROR the trait `Foo` cannot be made into an object
+}
diff --git a/tests/ui/async-await/in-trait/object-safety.stderr b/tests/ui/async-await/in-trait/object-safety.stderr
new file mode 100644
index 00000000000..0b318f71f39
--- /dev/null
+++ b/tests/ui/async-await/in-trait/object-safety.stderr
@@ -0,0 +1,27 @@
+warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/object-safety.rs:3:12
+   |
+LL | #![feature(async_fn_in_trait)]
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/object-safety.rs:11:12
+   |
+LL |     let x: &dyn Foo = todo!();
+   |            ^^^^^^^^ `Foo` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/object-safety.rs:7:14
+   |
+LL | trait Foo {
+   |       --- this trait cannot be made into an object...
+LL |     async fn foo(&self);
+   |              ^^^ ...because method `foo` is `async`
+   = help: consider moving `foo` to another trait
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/async-await/in-trait/return-type-suggestion.rs b/tests/ui/async-await/in-trait/return-type-suggestion.rs
new file mode 100644
index 00000000000..3446761d119
--- /dev/null
+++ b/tests/ui/async-await/in-trait/return-type-suggestion.rs
@@ -0,0 +1,14 @@
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+//~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+
+trait A {
+    async fn e() {
+        Ok(())
+        //~^ ERROR mismatched types
+        //~| HELP consider using a semicolon here
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/return-type-suggestion.stderr b/tests/ui/async-await/in-trait/return-type-suggestion.stderr
new file mode 100644
index 00000000000..5a9b15e54a0
--- /dev/null
+++ b/tests/ui/async-await/in-trait/return-type-suggestion.stderr
@@ -0,0 +1,23 @@
+warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/return-type-suggestion.rs:3:12
+   |
+LL | #![feature(async_fn_in_trait)]
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0308]: mismatched types
+  --> $DIR/return-type-suggestion.rs:8:9
+   |
+LL |         Ok(())
+   |         ^^^^^^- help: consider using a semicolon here: `;`
+   |         |
+   |         expected `()`, found enum `Result`
+   |
+   = note: expected unit type `()`
+                   found enum `Result<(), _>`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0308`.