about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2022-12-15 12:46:00 +0100
committerGitHub <noreply@github.com>2022-12-15 12:46:00 +0100
commitc00eac355845637b604d3b0225e5416430776e21 (patch)
tree19a257317926672f232115b8d35e2e78ac824694 /src
parentd67000e44e1b9908c81fc4d5de875608f1b80ae9 (diff)
parentda98ef9a5d0b8a4fb90e1d845506880fae9e7352 (diff)
downloadrust-c00eac355845637b604d3b0225e5416430776e21.tar.gz
rust-c00eac355845637b604d3b0225e5416430776e21.zip
Rollup merge of #104592 - ComputerDruid:async_check, r=compiler-errors
Ensure async trait impls are async (or otherwise return an opaque type)

As a workaround for the full `#[refine]` semantics not being implemented
yet, forbit returning a concrete future type like `Box<dyn Future>` or a
manually implemented Future.

`-> impl Future` is still permitted; while that can also cause
accidental refinement, that's behind a different feature gate
(`return_position_impl_trait_in_trait`) and that problem exists
regardless of whether the trait method is async, so will have to be
solved more generally.

Fixes https://github.com/rust-lang/rust/issues/102745
Diffstat (limited to 'src')
-rw-r--r--src/test/ui/async-await/in-trait/async-example-desugared-boxed.rs7
-rw-r--r--src/test/ui/async-await/in-trait/async-example-desugared-boxed.stderr11
-rw-r--r--src/test/ui/async-await/in-trait/async-example-desugared-extra.rs37
-rw-r--r--src/test/ui/async-await/in-trait/async-example-desugared-manual.rs29
-rw-r--r--src/test/ui/async-await/in-trait/async-example-desugared-manual.stderr11
-rw-r--r--src/test/ui/async-await/in-trait/async-example-desugared.rs5
-rw-r--r--src/test/ui/async-await/in-trait/fn-not-async-err.rs2
-rw-r--r--src/test/ui/async-await/in-trait/fn-not-async-err.stderr18
-rw-r--r--src/test/ui/async-await/in-trait/fn-not-async-err2.rs4
9 files changed, 99 insertions, 25 deletions
diff --git a/src/test/ui/async-await/in-trait/async-example-desugared-boxed.rs b/src/test/ui/async-await/in-trait/async-example-desugared-boxed.rs
index 61d7e2520ea..1b1b3cffd58 100644
--- a/src/test/ui/async-await/in-trait/async-example-desugared-boxed.rs
+++ b/src/test/ui/async-await/in-trait/async-example-desugared-boxed.rs
@@ -1,4 +1,3 @@
-// check-pass
 // edition: 2021
 
 #![feature(async_fn_in_trait)]
@@ -13,11 +12,9 @@ trait MyTrait {
 }
 
 impl MyTrait for i32 {
-    // This will break once a PR that implements #102745 is merged
     fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>> {
-        Box::pin(async {
-            *self
-        })
+        //~^ ERROR method `foo` should be async
+        Box::pin(async { *self })
     }
 }
 
diff --git a/src/test/ui/async-await/in-trait/async-example-desugared-boxed.stderr b/src/test/ui/async-await/in-trait/async-example-desugared-boxed.stderr
new file mode 100644
index 00000000000..60fa534a64f
--- /dev/null
+++ b/src/test/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/src/test/ui/async-await/in-trait/async-example-desugared-extra.rs b/src/test/ui/async-await/in-trait/async-example-desugared-extra.rs
new file mode 100644
index 00000000000..81e1e59a362
--- /dev/null
+++ b/src/test/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/src/test/ui/async-await/in-trait/async-example-desugared-manual.rs b/src/test/ui/async-await/in-trait/async-example-desugared-manual.rs
new file mode 100644
index 00000000000..71473e7455f
--- /dev/null
+++ b/src/test/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/src/test/ui/async-await/in-trait/async-example-desugared-manual.stderr b/src/test/ui/async-await/in-trait/async-example-desugared-manual.stderr
new file mode 100644
index 00000000000..567a36a86d1
--- /dev/null
+++ b/src/test/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/src/test/ui/async-await/in-trait/async-example-desugared.rs b/src/test/ui/async-await/in-trait/async-example-desugared.rs
index 1313c9edd86..fb92ec78674 100644
--- a/src/test/ui/async-await/in-trait/async-example-desugared.rs
+++ b/src/test/ui/async-await/in-trait/async-example-desugared.rs
@@ -12,11 +12,8 @@ trait MyTrait {
 }
 
 impl MyTrait for i32 {
-    // This will break once a PR that implements #102745 is merged
     fn foo(&self) -> impl Future<Output = i32> + '_ {
-        async {
-            *self
-        }
+        async { *self }
     }
 }
 
diff --git a/src/test/ui/async-await/in-trait/fn-not-async-err.rs b/src/test/ui/async-await/in-trait/fn-not-async-err.rs
index f94d32145a2..9598d53bce8 100644
--- a/src/test/ui/async-await/in-trait/fn-not-async-err.rs
+++ b/src/test/ui/async-await/in-trait/fn-not-async-err.rs
@@ -9,7 +9,7 @@ trait MyTrait {
 
 impl MyTrait for i32 {
     fn foo(&self) -> i32 {
-        //~^ ERROR: `i32` is not a future [E0277]
+        //~^ ERROR: method `foo` should be async
         *self
     }
 }
diff --git a/src/test/ui/async-await/in-trait/fn-not-async-err.stderr b/src/test/ui/async-await/in-trait/fn-not-async-err.stderr
index 03321dc5b5a..579801d0f39 100644
--- a/src/test/ui/async-await/in-trait/fn-not-async-err.stderr
+++ b/src/test/ui/async-await/in-trait/fn-not-async-err.stderr
@@ -1,17 +1,11 @@
-error[E0277]: `i32` is not a future
-  --> $DIR/fn-not-async-err.rs:11:22
-   |
-LL |     fn foo(&self) -> i32 {
-   |                      ^^^ `i32` is not a future
-   |
-   = help: the trait `Future` is not implemented for `i32`
-   = note: i32 must be a future or must implement `IntoFuture` to be awaited
-note: required by a bound in `MyTrait::foo::{opaque#0}`
-  --> $DIR/fn-not-async-err.rs:7:28
+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 by this bound in `MyTrait::foo::{opaque#0}`
+   |     --------------------------- required because the trait method is async
+...
+LL |     fn foo(&self) -> i32 {
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/async-await/in-trait/fn-not-async-err2.rs b/src/test/ui/async-await/in-trait/fn-not-async-err2.rs
index 594baa91ad8..2c4ed553580 100644
--- a/src/test/ui/async-await/in-trait/fn-not-async-err2.rs
+++ b/src/test/ui/async-await/in-trait/fn-not-async-err2.rs
@@ -12,9 +12,7 @@ trait MyTrait {
 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
-        }
+        async { *self }
     }
 }