Actually parse async gen blocks correctly

This commit is contained in:
Michael Goulet 2023-12-12 20:08:34 +00:00
parent 27d8a57713
commit 1d78ce681e
5 changed files with 87 additions and 15 deletions

View File

@ -1440,21 +1440,23 @@ fn parse_expr_bottom(&mut self) -> PResult<'a, P<Expr>> {
} 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 @@ fn parse_gen_block(&mut self) -> PResult<'a, P<Expr>> {
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);

View File

@ -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<Item = ()> {
async gen {
yield Default::default();
}
}
fn main() {}

View File

@ -2,16 +2,34 @@ error[E0658]: gen blocks are experimental
--> $DIR/feature-gate-gen_blocks.rs:5:5
|
LL | gen {};
| ^^^^^
| ^^^
|
= note: see issue #117078 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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`.

View File

@ -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`.

View File

@ -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`
}