Skip to content

Commit

Permalink
Actually parse async gen blocks correctly
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Dec 12, 2023
1 parent 27d8a57 commit 1d78ce6
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 15 deletions.
27 changes: 18 additions & 9 deletions compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
Expand Down
14 changes: 14 additions & 0 deletions tests/ui/coroutine/async-gen-deduce-yield.rs
Original file line number Diff line number Diff line change
@@ -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() {}
32 changes: 28 additions & 4 deletions tests/ui/feature-gates/feature-gate-gen_blocks.e2024.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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`.
14 changes: 13 additions & 1 deletion tests/ui/feature-gates/feature-gate-gen_blocks.none.stderr
Original file line number Diff line number Diff line change
@@ -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`.
15 changes: 14 additions & 1 deletion tests/ui/feature-gates/feature-gate-gen_blocks.rs
Original file line number Diff line number Diff line change
@@ -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`
}

0 comments on commit 1d78ce6

Please sign in to comment.