From 1d78ce681e4bf0c0259fc97e422298d68635dc4f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 12 Dec 2023 20:08:34 +0000 Subject: [PATCH] Actually parse async gen blocks correctly --- compiler/rustc_parse/src/parser/expr.rs | 27 ++++++++++------ tests/ui/coroutine/async-gen-deduce-yield.rs | 14 ++++++++ .../feature-gate-gen_blocks.e2024.stderr | 32 ++++++++++++++++--- .../feature-gate-gen_blocks.none.stderr | 14 +++++++- .../feature-gates/feature-gate-gen_blocks.rs | 15 ++++++++- 5 files changed, 87 insertions(+), 15 deletions(-) create mode 100644 tests/ui/coroutine/async-gen-deduce-yield.rs diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 3c0627526bed5..3606c0fa09871 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1440,21 +1440,23 @@ impl<'a> Parser<'a> { } else if this.eat_keyword(kw::Underscore) { Ok(this.mk_expr(this.prev_token.span, ExprKind::Underscore)) } else if this.token.uninterpolated_span().at_least_rust_2018() { - // `Span:.at_least_rust_2018()` is somewhat expensive; don't get it repeatedly. - if this.check_keyword(kw::Async) { + // `Span::at_least_rust_2018()` is somewhat expensive; don't get it repeatedly. + if this.token.uninterpolated_span().at_least_rust_2024() + // check for `gen {}` and `gen move {}` + // or `async gen {}` and `async gen move {}` + && (this.is_gen_block(kw::Gen, 0) + || (this.check_keyword(kw::Async) && this.is_gen_block(kw::Gen, 1))) + { + // FIXME: (async) gen closures aren't yet parsed. + this.parse_gen_block() + } else if this.check_keyword(kw::Async) { // FIXME(gen_blocks): Parse `gen async` and suggest swap if this.is_gen_block(kw::Async, 0) { // Check for `async {` and `async move {`, - // or `async gen {` and `async gen move {`. this.parse_gen_block() } else { this.parse_expr_closure() } - } else if this.token.uninterpolated_span().at_least_rust_2024() - && (this.is_gen_block(kw::Gen, 0) - || (this.check_keyword(kw::Async) && this.is_gen_block(kw::Gen, 1))) - { - this.parse_gen_block() } else if this.eat_keyword_noexpect(kw::Await) { this.recover_incorrect_await_syntax(lo, this.prev_token.span) } else { @@ -3219,9 +3221,16 @@ impl<'a> Parser<'a> { if self.eat_keyword(kw::Gen) { GenBlockKind::AsyncGen } else { GenBlockKind::Async } } else { assert!(self.eat_keyword(kw::Gen)); - self.sess.gated_spans.gate(sym::gen_blocks, lo.to(self.token.span)); GenBlockKind::Gen }; + match kind { + GenBlockKind::Async => { + // `async` blocks are stable + } + GenBlockKind::Gen | GenBlockKind::AsyncGen => { + self.sess.gated_spans.gate(sym::gen_blocks, lo.to(self.prev_token.span)); + } + } let capture_clause = self.parse_capture_clause()?; let (attrs, body) = self.parse_inner_attrs_and_block()?; let kind = ExprKind::Gen(capture_clause, body, kind); diff --git a/tests/ui/coroutine/async-gen-deduce-yield.rs b/tests/ui/coroutine/async-gen-deduce-yield.rs new file mode 100644 index 0000000000000..9ccc8ee41f667 --- /dev/null +++ b/tests/ui/coroutine/async-gen-deduce-yield.rs @@ -0,0 +1,14 @@ +// compile-flags: --edition 2024 -Zunstable-options +// check-pass + +#![feature(async_iterator, gen_blocks)] + +use std::async_iter::AsyncIterator; + +fn deduce() -> impl AsyncIterator { + async gen { + yield Default::default(); + } +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-gen_blocks.e2024.stderr b/tests/ui/feature-gates/feature-gate-gen_blocks.e2024.stderr index 1462c41e957b2..c582ca7ba3d58 100644 --- a/tests/ui/feature-gates/feature-gate-gen_blocks.e2024.stderr +++ b/tests/ui/feature-gates/feature-gate-gen_blocks.e2024.stderr @@ -2,16 +2,34 @@ error[E0658]: gen blocks are experimental --> $DIR/feature-gate-gen_blocks.rs:5:5 | LL | gen {}; - | ^^^^^ + | ^^^ | = note: see issue #117078 for more information = help: add `#![feature(gen_blocks)]` to the crate attributes to enable error[E0658]: gen blocks are experimental - --> $DIR/feature-gate-gen_blocks.rs:13:5 + --> $DIR/feature-gate-gen_blocks.rs:12:5 + | +LL | async gen {}; + | ^^^^^^^^^ + | + = note: see issue #117078 for more information + = help: add `#![feature(gen_blocks)]` to the crate attributes to enable + +error[E0658]: gen blocks are experimental + --> $DIR/feature-gate-gen_blocks.rs:22:5 | LL | gen {}; - | ^^^^^ + | ^^^ + | + = note: see issue #117078 for more information + = help: add `#![feature(gen_blocks)]` to the crate attributes to enable + +error[E0658]: gen blocks are experimental + --> $DIR/feature-gate-gen_blocks.rs:25:5 + | +LL | async gen {}; + | ^^^^^^^^^ | = note: see issue #117078 for more information = help: add `#![feature(gen_blocks)]` to the crate attributes to enable @@ -22,7 +40,13 @@ error[E0282]: type annotations needed LL | gen {}; | ^^ cannot infer type -error: aborting due to 3 previous errors +error[E0282]: type annotations needed + --> $DIR/feature-gate-gen_blocks.rs:12:15 + | +LL | async gen {}; + | ^^ cannot infer type + +error: aborting due to 6 previous errors Some errors have detailed explanations: E0282, E0658. For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/feature-gates/feature-gate-gen_blocks.none.stderr b/tests/ui/feature-gates/feature-gate-gen_blocks.none.stderr index 56f8309a69f9b..b4b37f0e63847 100644 --- a/tests/ui/feature-gates/feature-gate-gen_blocks.none.stderr +++ b/tests/ui/feature-gates/feature-gate-gen_blocks.none.stderr @@ -1,9 +1,21 @@ +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `gen` + --> $DIR/feature-gate-gen_blocks.rs:12:11 + | +LL | async gen {}; + | ^^^ expected one of 8 possible tokens + +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `gen` + --> $DIR/feature-gate-gen_blocks.rs:25:11 + | +LL | async gen {}; + | ^^^ expected one of 8 possible tokens + error[E0422]: cannot find struct, variant or union type `gen` in this scope --> $DIR/feature-gate-gen_blocks.rs:5:5 | LL | gen {}; | ^^^ not found in this scope -error: aborting due to 1 previous error +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0422`. diff --git a/tests/ui/feature-gates/feature-gate-gen_blocks.rs b/tests/ui/feature-gates/feature-gate-gen_blocks.rs index e2e1574a36a0f..ff9a0b139c057 100644 --- a/tests/ui/feature-gates/feature-gate-gen_blocks.rs +++ b/tests/ui/feature-gates/feature-gate-gen_blocks.rs @@ -1,15 +1,28 @@ // revisions: e2024 none //[e2024] compile-flags: --edition 2024 -Zunstable-options -fn main() { +fn test_gen() { gen {}; //[none]~^ ERROR: cannot find struct, variant or union type `gen` //[e2024]~^^ ERROR: gen blocks are experimental //[e2024]~| ERROR: type annotations needed } +fn test_async_gen() { + async gen {}; + //[none]~^ ERROR expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `gen` + //[e2024]~^^ ERROR: gen blocks are experimental + //[e2024]~| ERROR: type annotations needed +} + +fn main() {} + #[cfg(FALSE)] fn foo() { gen {}; //[e2024]~^ ERROR: gen blocks are experimental + + async gen {}; + //[e2024]~^ ERROR: gen blocks are experimental + //[none]~^^ ERROR expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `gen` }