Make sure async constructs do not impl Generator
Async lowering turns async functions and blocks into generators internally. Though these special kinds of generators should not `impl Generator` themselves. The other way around, normal generators should not `impl Future`.
This commit is contained in:
parent
8de4b13845
commit
b5ae4c9629
@ -203,7 +203,9 @@ fn assemble_generator_candidates(
|
||||
// type/region parameters.
|
||||
let self_ty = obligation.self_ty().skip_binder();
|
||||
match self_ty.kind() {
|
||||
ty::Generator(..) => {
|
||||
// async constructs get lowered to a special kind of generator that
|
||||
// should *not* `impl Generator`.
|
||||
ty::Generator(did, ..) if !self.tcx().generator_is_async(*did) => {
|
||||
debug!(?self_ty, ?obligation, "assemble_generator_candidates",);
|
||||
|
||||
candidates.vec.push(GeneratorCandidate);
|
||||
@ -223,6 +225,8 @@ fn assemble_future_candidates(
|
||||
) {
|
||||
let self_ty = obligation.self_ty().skip_binder();
|
||||
if let ty::Generator(did, ..) = self_ty.kind() {
|
||||
// async constructs get lowered to a special kind of generator that
|
||||
// should directly `impl Future`.
|
||||
if self.tcx().generator_is_async(*did) {
|
||||
debug!(?self_ty, ?obligation, "assemble_future_candidates",);
|
||||
|
||||
|
45
src/test/ui/async-await/generator-not-future.rs
Normal file
45
src/test/ui/async-await/generator-not-future.rs
Normal file
@ -0,0 +1,45 @@
|
||||
// edition:2018
|
||||
#![feature(generators, generator_trait)]
|
||||
|
||||
use std::future::Future;
|
||||
use std::ops::Generator;
|
||||
|
||||
async fn async_fn() {}
|
||||
fn returns_async_block() -> impl Future<Output = ()> {
|
||||
async {}
|
||||
}
|
||||
fn returns_generator() -> impl Generator<(), Yield = (), Return = ()> {
|
||||
|| {
|
||||
let _: () = yield ();
|
||||
}
|
||||
}
|
||||
|
||||
fn takes_future(_f: impl Future<Output = ()>) {}
|
||||
fn takes_generator<ResumeTy>(_g: impl Generator<ResumeTy, Yield = (), Return = ()>) {}
|
||||
|
||||
fn main() {
|
||||
// okay:
|
||||
takes_future(async_fn());
|
||||
takes_future(returns_async_block());
|
||||
takes_future(async {});
|
||||
takes_generator(returns_generator());
|
||||
takes_generator(|| {
|
||||
let _: () = yield ();
|
||||
});
|
||||
|
||||
// async futures are not generators:
|
||||
takes_generator(async_fn());
|
||||
//~^ ERROR the trait bound
|
||||
takes_generator(returns_async_block());
|
||||
//~^ ERROR the trait bound
|
||||
takes_generator(async {});
|
||||
//~^ ERROR the trait bound
|
||||
|
||||
// generators are not futures:
|
||||
takes_future(returns_generator());
|
||||
//~^ ERROR is not a future
|
||||
takes_future(|ctx| {
|
||||
//~^ ERROR is not a future
|
||||
ctx = yield ();
|
||||
});
|
||||
}
|
81
src/test/ui/async-await/generator-not-future.stderr
Normal file
81
src/test/ui/async-await/generator-not-future.stderr
Normal file
@ -0,0 +1,81 @@
|
||||
error[E0277]: the trait bound `impl Future<Output = ()>: Generator<_>` is not satisfied
|
||||
--> $DIR/generator-not-future.rs:31:21
|
||||
|
|
||||
LL | takes_generator(async_fn());
|
||||
| --------------- ^^^^^^^^^^ the trait `Generator<_>` is not implemented for `impl Future<Output = ()>`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `takes_generator`
|
||||
--> $DIR/generator-not-future.rs:18:39
|
||||
|
|
||||
LL | fn takes_generator<ResumeTy>(_g: impl Generator<ResumeTy, Yield = (), Return = ()>) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_generator`
|
||||
|
||||
error[E0277]: the trait bound `impl Future<Output = ()>: Generator<_>` is not satisfied
|
||||
--> $DIR/generator-not-future.rs:33:21
|
||||
|
|
||||
LL | takes_generator(returns_async_block());
|
||||
| --------------- ^^^^^^^^^^^^^^^^^^^^^ the trait `Generator<_>` is not implemented for `impl Future<Output = ()>`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `takes_generator`
|
||||
--> $DIR/generator-not-future.rs:18:39
|
||||
|
|
||||
LL | fn takes_generator<ResumeTy>(_g: impl Generator<ResumeTy, Yield = (), Return = ()>) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_generator`
|
||||
|
||||
error[E0277]: the trait bound `[async block@$DIR/generator-not-future.rs:35:21: 35:29]: Generator<_>` is not satisfied
|
||||
--> $DIR/generator-not-future.rs:35:21
|
||||
|
|
||||
LL | takes_generator(async {});
|
||||
| --------------- ^^^^^^^^ the trait `Generator<_>` is not implemented for `[async block@$DIR/generator-not-future.rs:35:21: 35:29]`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `takes_generator`
|
||||
--> $DIR/generator-not-future.rs:18:39
|
||||
|
|
||||
LL | fn takes_generator<ResumeTy>(_g: impl Generator<ResumeTy, Yield = (), Return = ()>) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_generator`
|
||||
|
||||
error[E0277]: `impl Generator<Yield = (), Return = ()>` is not a future
|
||||
--> $DIR/generator-not-future.rs:39:18
|
||||
|
|
||||
LL | takes_future(returns_generator());
|
||||
| ------------ ^^^^^^^^^^^^^^^^^^^ `impl Generator<Yield = (), Return = ()>` is not a future
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the trait `Future` is not implemented for `impl Generator<Yield = (), Return = ()>`
|
||||
= note: impl Generator<Yield = (), Return = ()> must be a future or must implement `IntoFuture` to be awaited
|
||||
note: required by a bound in `takes_future`
|
||||
--> $DIR/generator-not-future.rs:17:26
|
||||
|
|
||||
LL | fn takes_future(_f: impl Future<Output = ()>) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_future`
|
||||
|
||||
error[E0277]: `[generator@$DIR/generator-not-future.rs:41:18: 41:23]` is not a future
|
||||
--> $DIR/generator-not-future.rs:41:18
|
||||
|
|
||||
LL | takes_future(|ctx| {
|
||||
| _____------------_^
|
||||
| | |
|
||||
| | required by a bound introduced by this call
|
||||
LL | |
|
||||
LL | | ctx = yield ();
|
||||
LL | | });
|
||||
| |_____^ `[generator@$DIR/generator-not-future.rs:41:18: 41:23]` is not a future
|
||||
|
|
||||
= help: the trait `Future` is not implemented for `[generator@$DIR/generator-not-future.rs:41:18: 41:23]`
|
||||
= note: [generator@$DIR/generator-not-future.rs:41:18: 41:23] must be a future or must implement `IntoFuture` to be awaited
|
||||
note: required by a bound in `takes_future`
|
||||
--> $DIR/generator-not-future.rs:17:26
|
||||
|
|
||||
LL | fn takes_future(_f: impl Future<Output = ()>) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_future`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
Loading…
Reference in New Issue
Block a user