// 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);
) {
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",);
--- /dev/null
+// 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 ();
+ });
+}
--- /dev/null
+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`.