Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Actually parse async gen blocks correctly #118891

Merged
merged 1 commit into from
Dec 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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.
eholk marked this conversation as resolved.
Show resolved Hide resolved
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`
}