Skip to content

Commit e8a6ccc

Browse files
committed
Add explicit syntax for coroutines instead of relying on closures having yield expressions
1 parent 05ccc49 commit e8a6ccc

File tree

5 files changed

+42
-24
lines changed

5 files changed

+42
-24
lines changed

compiler/rustc_ast_lowering/src/expr.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -201,18 +201,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
201201
fn_decl_span,
202202
fn_arg_span,
203203
}) => match coroutine_kind {
204-
Some(coroutine_kind) => self.lower_expr_coroutine_closure(
204+
Some(kind @ CoroutineKind::Async { .. }) => self.lower_expr_coroutine_closure(
205205
binder,
206206
*capture_clause,
207207
e.id,
208208
hir_id,
209-
*coroutine_kind,
209+
*kind,
210210
fn_decl,
211211
body,
212212
*fn_decl_span,
213213
*fn_arg_span,
214214
),
215-
None => self.lower_expr_closure(
215+
_ => self.lower_expr_closure(
216216
binder,
217217
*capture_clause,
218218
e.id,
@@ -222,6 +222,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
222222
body,
223223
*fn_decl_span,
224224
*fn_arg_span,
225+
*coroutine_kind,
225226
),
226227
},
227228
ExprKind::Gen(capture_clause, block, genblock_kind) => {
@@ -963,12 +964,22 @@ impl<'hir> LoweringContext<'_, 'hir> {
963964
body: &Expr,
964965
fn_decl_span: Span,
965966
fn_arg_span: Span,
967+
coroutine_kind: Option<CoroutineKind>,
966968
) -> hir::ExprKind<'hir> {
967969
let (binder_clause, generic_params) = self.lower_closure_binder(binder);
968970

969971
let (body_id, closure_kind) = self.with_new_scopes(fn_decl_span, move |this| {
970-
let mut coroutine_kind = None;
972+
let mut coroutine_kind = coroutine_kind.map(|k| match k {
973+
CoroutineKind::Async { span, .. } => {
974+
span_bug!(span, "should have used lower_expr_coroutine_closure")
975+
}
976+
CoroutineKind::Gen { .. } => hir::CoroutineKind::Coroutine(Movability::Movable),
977+
CoroutineKind::AsyncGen { span, .. } => {
978+
span_bug!(span, "async gen closures are not supported yet")
979+
}
980+
});
971981
let body_id = this.lower_fn_body(decl, |this| {
982+
this.coroutine_kind = coroutine_kind;
972983
let e = this.lower_expr_mut(body);
973984
coroutine_kind = this.coroutine_kind;
974985
e

compiler/rustc_parse/src/parser/expr.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1522,17 +1522,18 @@ impl<'a> Parser<'a> {
15221522
Ok(this.mk_expr(this.prev_token.span, ExprKind::Underscore))
15231523
} else if this.token.uninterpolated_span().at_least_rust_2018() {
15241524
// `Span::at_least_rust_2018()` is somewhat expensive; don't get it repeatedly.
1525-
if this.token.uninterpolated_span().at_least_rust_2024()
1526-
// check for `gen {}` and `gen move {}`
1527-
// or `async gen {}` and `async gen move {}`
1528-
&& (this.is_gen_block(kw::Gen, 0)
1529-
|| (this.check_keyword(kw::Async) && this.is_gen_block(kw::Gen, 1)))
1530-
{
1531-
// FIXME: (async) gen closures aren't yet parsed.
1532-
this.parse_gen_block()
1533-
} else if this.check_keyword(kw::Async) {
1525+
if this.check_keyword(kw::Async) {
15341526
// FIXME(gen_blocks): Parse `gen async` and suggest swap
1535-
if this.is_gen_block(kw::Async, 0) {
1527+
if this.is_gen_block(kw::Async, 0) || this.is_gen_block(kw::Gen, 1) {
1528+
// Check for `async {` and `async move {`,
1529+
this.parse_gen_block()
1530+
} else {
1531+
this.parse_expr_closure()
1532+
}
1533+
} else if this.check_keyword(kw::Gen)
1534+
&& this.token.uninterpolated_span().at_least_rust_2024()
1535+
{
1536+
if this.is_gen_block(kw::Gen, 0) {
15361537
// Check for `async {` and `async move {`,
15371538
this.parse_gen_block()
15381539
} else {

tests/ui/coroutine/addassign-yield.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,27 @@
11
//@ run-pass
2+
//@ edition: 2024
3+
//@ compile-flags: -Zunstable-options
24
// Regression test for broken MIR error (#61442)
35
// Due to the two possible evaluation orders for
46
// a '+=' expression (depending on whether or not the 'AddAssign' trait
57
// is being used), we were failing to account for all types that might
68
// possibly be live across a yield point.
79

8-
#![feature(coroutines)]
10+
#![feature(coroutines, gen_blocks)]
911

1012
fn foo() {
11-
let _x = static || {
13+
let _x = static gen || {
1214
let mut s = String::new();
1315
s += { yield; "" };
1416
};
1517

16-
let _y = static || {
18+
let _y = static gen || {
1719
let x = &mut 0;
1820
*{ yield; x } += match String::new() { _ => 0 };
1921
};
2022

2123
// Please don't ever actually write something like this
22-
let _z = static || {
24+
let _z = static gen || {
2325
let x = &mut 0;
2426
*{
2527
let inner = &mut 1;

tests/ui/coroutine/borrow-in-tail-expr.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
//@ run-pass
2+
//@ edition: 2024
3+
//@ compile-flags: -Zunstable-options
24

3-
#![feature(coroutines)]
5+
#![feature(coroutines, gen_blocks)]
46

57
fn main() {
6-
let _a = || {
8+
let _a = gen || {
79
yield;
810
let a = String::new();
911
a.len()
Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
//@ build-pass
2+
//@ edition: 2024
3+
//@ compile-flags: -Zunstable-options
24

35
//! Like drop-tracking-parent-expression, but also tests that this doesn't ICE when building MIR
4-
#![feature(coroutines)]
6+
#![feature(coroutines, gen_blocks)]
57

68
fn assert_send<T: Send>(_thing: T) {}
79

810
#[derive(Default)]
911
pub struct Client { pub nickname: String }
1012

1113
fn main() {
12-
let g = move || match drop(Client { ..Client::default() }) {
13-
_status => yield,
14-
};
14+
let g = gen || match drop(Client { ..Client::default() }) {
15+
_status => yield,
16+
};
1517
assert_send(g);
1618
}

0 commit comments

Comments
 (0)