diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2022-12-15 12:46:00 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-12-15 12:46:00 +0100 |
| commit | c00eac355845637b604d3b0225e5416430776e21 (patch) | |
| tree | 19a257317926672f232115b8d35e2e78ac824694 /src | |
| parent | d67000e44e1b9908c81fc4d5de875608f1b80ae9 (diff) | |
| parent | da98ef9a5d0b8a4fb90e1d845506880fae9e7352 (diff) | |
| download | rust-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')
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 } } } |
