mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-21 11:23:03 +00:00
Auto merge of #105094 - Swatinem:generator-not-future, r=compiler-errors
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 was discovered in https://github.com/rust-lang/rust/pull/105082#issuecomment-1332210907 and is a regression from https://github.com/rust-lang/rust/pull/104321. r? `@compiler-errors`
This commit is contained in:
commit
d1449560e3
@ -203,7 +203,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
// type/region parameters.
|
// type/region parameters.
|
||||||
let self_ty = obligation.self_ty().skip_binder();
|
let self_ty = obligation.self_ty().skip_binder();
|
||||||
match self_ty.kind() {
|
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",);
|
debug!(?self_ty, ?obligation, "assemble_generator_candidates",);
|
||||||
|
|
||||||
candidates.vec.push(GeneratorCandidate);
|
candidates.vec.push(GeneratorCandidate);
|
||||||
@ -223,6 +225,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
) {
|
) {
|
||||||
let self_ty = obligation.self_ty().skip_binder();
|
let self_ty = obligation.self_ty().skip_binder();
|
||||||
if let ty::Generator(did, ..) = self_ty.kind() {
|
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) {
|
if self.tcx().generator_is_async(*did) {
|
||||||
debug!(?self_ty, ?obligation, "assemble_future_candidates",);
|
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