Skip to content

Commit 747992d

Browse files
committed
Add gen blocks to ast and do some broken ast lowering
1 parent b5aa943 commit 747992d

File tree

21 files changed

+132
-56
lines changed

21 files changed

+132
-56
lines changed

compiler/rustc_ast/src/ast.rs

+26-7
Original file line numberDiff line numberDiff line change
@@ -1232,7 +1232,7 @@ impl Expr {
12321232
ExprKind::Closure(..) => ExprPrecedence::Closure,
12331233
ExprKind::Block(..) => ExprPrecedence::Block,
12341234
ExprKind::TryBlock(..) => ExprPrecedence::TryBlock,
1235-
ExprKind::Async(..) => ExprPrecedence::Async,
1235+
ExprKind::Gen(..) => ExprPrecedence::Gen,
12361236
ExprKind::Await(..) => ExprPrecedence::Await,
12371237
ExprKind::Assign(..) => ExprPrecedence::Assign,
12381238
ExprKind::AssignOp(..) => ExprPrecedence::AssignOp,
@@ -1401,11 +1401,9 @@ pub enum ExprKind {
14011401
Closure(Box<Closure>),
14021402
/// A block (`'label: { ... }`).
14031403
Block(P<Block>, Option<Label>),
1404-
/// An async block (`async move { ... }`).
1405-
///
1406-
/// The async block used to have a `NodeId`, which was removed in favor of
1407-
/// using the parent `NodeId` of the parent `Expr`.
1408-
Async(CaptureBy, P<Block>),
1404+
/// An `async` block (`async move { ... }`),
1405+
/// or a `gen` block (`gen move { ... }`)
1406+
Gen(CaptureBy, P<Block>, GenBlockKind),
14091407
/// An await expression (`my_future.await`). Span is of await keyword.
14101408
Await(P<Expr>, Span),
14111409

@@ -1469,7 +1467,6 @@ pub enum ExprKind {
14691467

14701468
/// A try expression (`expr?`).
14711469
Try(P<Expr>),
1472-
14731470
/// A `yield`, with an optional value to be yielded.
14741471
Yield(Option<P<Expr>>),
14751472

@@ -1495,6 +1492,28 @@ pub enum ExprKind {
14951492
Err,
14961493
}
14971494

1495+
/// Used to differentiate between `async {}` blocks and `gen {}` blocks.
1496+
#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
1497+
pub enum GenBlockKind {
1498+
Async,
1499+
Gen,
1500+
}
1501+
1502+
impl fmt::Display for GenBlockKind {
1503+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1504+
self.modifier().fmt(f)
1505+
}
1506+
}
1507+
1508+
impl GenBlockKind {
1509+
pub fn modifier(&self) -> &'static str {
1510+
match self {
1511+
GenBlockKind::Async => "async",
1512+
GenBlockKind::Gen => "gen",
1513+
}
1514+
}
1515+
}
1516+
14981517
/// The explicit `Self` type in a "qualified path". The actual
14991518
/// path, including the trait and the associated item, is stored
15001519
/// separately. `position` represents the index of the associated

compiler/rustc_ast/src/mut_visit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1418,7 +1418,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
14181418
vis.visit_block(blk);
14191419
visit_opt(label, |label| vis.visit_label(label));
14201420
}
1421-
ExprKind::Async(_capture_by, body) => {
1421+
ExprKind::Gen(_capture_by, body, _) => {
14221422
vis.visit_block(body);
14231423
}
14241424
ExprKind::Await(expr, await_kw_span) => {

compiler/rustc_ast/src/util/classify.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
4646
Closure(closure) => {
4747
expr = &closure.body;
4848
}
49-
Async(..) | Block(..) | ForLoop(..) | If(..) | Loop(..) | Match(..) | Struct(..)
49+
Gen(..) | Block(..) | ForLoop(..) | If(..) | Loop(..) | Match(..) | Struct(..)
5050
| TryBlock(..) | While(..) => break Some(expr),
5151
_ => break None,
5252
}

compiler/rustc_ast/src/util/parser.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ pub enum ExprPrecedence {
285285
Block,
286286
TryBlock,
287287
Struct,
288-
Async,
288+
Gen,
289289
Await,
290290
Err,
291291
}
@@ -351,7 +351,7 @@ impl ExprPrecedence {
351351
| ExprPrecedence::ConstBlock
352352
| ExprPrecedence::Block
353353
| ExprPrecedence::TryBlock
354-
| ExprPrecedence::Async
354+
| ExprPrecedence::Gen
355355
| ExprPrecedence::Struct
356356
| ExprPrecedence::Err => PREC_PAREN,
357357
}

compiler/rustc_ast/src/visit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -872,7 +872,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
872872
walk_list!(visitor, visit_label, opt_label);
873873
visitor.visit_block(block);
874874
}
875-
ExprKind::Async(_, body) => {
875+
ExprKind::Gen(_, body, _) => {
876876
visitor.visit_block(body);
877877
}
878878
ExprKind::Await(expr, _) => visitor.visit_expr(expr),

compiler/rustc_ast_lowering/src/expr.rs

+62-1
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
183183
self.arena.alloc_from_iter(arms.iter().map(|x| self.lower_arm(x))),
184184
hir::MatchSource::Normal,
185185
),
186-
ExprKind::Async(capture_clause, block) => self.make_async_expr(
186+
ExprKind::Gen(capture_clause, block, GenBlockKind::Async) => self.make_async_expr(
187187
*capture_clause,
188188
e.id,
189189
None,
@@ -317,6 +317,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
317317
rest,
318318
)
319319
}
320+
ExprKind::Gen(capture_clause, block, GenBlockKind::Gen) => self.make_gen_expr(
321+
*capture_clause,
322+
e.id,
323+
None,
324+
e.span,
325+
hir::AsyncGeneratorKind::Block,
326+
|this| this.with_new_scopes(|this| this.lower_block_expr(block)),
327+
),
320328
ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()),
321329
ExprKind::Err => hir::ExprKind::Err(
322330
self.tcx.sess.delay_span_bug(e.span, "lowered ExprKind::Err"),
@@ -661,6 +669,59 @@ impl<'hir> LoweringContext<'_, 'hir> {
661669
}))
662670
}
663671

672+
/// Lower a `gen` construct to a generator that implements `Future`.
673+
///
674+
/// This results in:
675+
///
676+
/// ```text
677+
/// static move? |()| -> () {
678+
/// <body>
679+
/// }
680+
/// ```
681+
pub(super) fn make_gen_expr(
682+
&mut self,
683+
capture_clause: CaptureBy,
684+
closure_node_id: NodeId,
685+
_yield_ty: Option<hir::FnRetTy<'hir>>,
686+
span: Span,
687+
// We re-use the async enum, because we have the same cases.
688+
// FIXME(oli-obk): rename the enum.
689+
gen_kind: hir::AsyncGeneratorKind,
690+
body: impl FnOnce(&mut Self) -> hir::Expr<'hir>,
691+
) -> hir::ExprKind<'hir> {
692+
let output = hir::FnRetTy::DefaultReturn(self.lower_span(span));
693+
694+
// The closure/generator `FnDecl` takes a single (resume) argument of type `input_ty`.
695+
let fn_decl = self.arena.alloc(hir::FnDecl {
696+
inputs: &[],
697+
output,
698+
c_variadic: false,
699+
implicit_self: hir::ImplicitSelfKind::None,
700+
lifetime_elision_allowed: false,
701+
});
702+
703+
let body = self.lower_body(move |this| {
704+
this.generator_kind = Some(hir::GeneratorKind::Iter(gen_kind));
705+
706+
let res = body(this);
707+
(&[], res)
708+
});
709+
710+
// `static |()| -> () { body }`:
711+
hir::ExprKind::Closure(self.arena.alloc(hir::Closure {
712+
def_id: self.local_def_id(closure_node_id),
713+
binder: hir::ClosureBinder::Default,
714+
capture_clause,
715+
bound_generic_params: &[],
716+
fn_decl,
717+
body,
718+
fn_decl_span: self.lower_span(span),
719+
fn_arg_span: None,
720+
movability: Some(hir::Movability::Static),
721+
constness: hir::Constness::NotConst,
722+
}))
723+
}
724+
664725
/// Forwards a possible `#[track_caller]` annotation from `outer_hir_id` to
665726
/// `inner_hir_id` in case the `async_fn_track_caller` feature is enabled.
666727
pub(super) fn maybe_forward_track_caller(

compiler/rustc_ast_pretty/src/pprust/state/expr.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -445,8 +445,8 @@ impl<'a> State<'a> {
445445
self.ibox(0);
446446
self.print_block_with_attrs(blk, attrs);
447447
}
448-
ast::ExprKind::Async(capture_clause, blk) => {
449-
self.word_nbsp("async");
448+
ast::ExprKind::Gen(capture_clause, blk, kind) => {
449+
self.word_nbsp(kind.modifier());
450450
self.print_capture_clause(*capture_clause);
451451
// cbox/ibox in analogy to the `ExprKind::Block` arm above
452452
self.cbox(0);

compiler/rustc_builtin_macros/src/assert/context.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
294294
// sync with the `rfc-2011-nicer-assert-messages/all-expr-kinds.rs` test.
295295
ExprKind::Assign(_, _, _)
296296
| ExprKind::AssignOp(_, _, _)
297-
| ExprKind::Async(_, _)
297+
| ExprKind::Gen(_, _, _)
298298
| ExprKind::Await(_, _)
299299
| ExprKind::Block(_, _)
300300
| ExprKind::Break(_, _)

compiler/rustc_parse/src/parser/expr.rs

+14-18
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use super::{
99
use crate::errors;
1010
use crate::maybe_recover_from_interpolated_ty_qpath;
1111
use ast::mut_visit::{noop_visit_expr, MutVisitor};
12-
use ast::{Path, PathSegment};
12+
use ast::{GenBlockKind, Path, PathSegment};
1313
use core::mem;
1414
use rustc_ast::ptr::P;
1515
use rustc_ast::token::{self, Delimiter, Token, TokenKind};
@@ -1422,9 +1422,6 @@ impl<'a> Parser<'a> {
14221422
} else if this.is_try_block() {
14231423
this.expect_keyword(kw::Try)?;
14241424
this.parse_try_block(lo)
1425-
} else if this.is_gen_block() {
1426-
this.expect_keyword(kw::Gen)?;
1427-
this.parse_gen_block(lo)
14281425
} else if this.eat_keyword(kw::Return) {
14291426
this.parse_expr_return()
14301427
} else if this.eat_keyword(kw::Continue) {
@@ -1446,12 +1443,14 @@ impl<'a> Parser<'a> {
14461443
if this.check_keyword(kw::Async) {
14471444
if this.is_async_block() {
14481445
// Check for `async {` and `async move {`.
1449-
this.parse_async_block()
1446+
this.parse_gen_block()
14501447
} else {
14511448
this.parse_expr_closure()
14521449
}
14531450
} else if this.eat_keyword(kw::Await) {
14541451
this.recover_incorrect_await_syntax(lo, this.prev_token.span)
1452+
} else if this.token.uninterpolated_span().at_least_rust_2024() {
1453+
if this.is_gen_block() { this.parse_gen_block() } else { this.parse_expr_lit() }
14551454
} else {
14561455
this.parse_expr_lit()
14571456
}
@@ -3043,14 +3042,6 @@ impl<'a> Parser<'a> {
30433042
}
30443043
}
30453044

3046-
/// Parses a `gen {...}` expression (`gen` token already eaten).
3047-
fn parse_gen_block(&mut self, _span_lo: Span) -> PResult<'a, P<Expr>> {
3048-
let (_attrs, _body) = self.parse_inner_attrs_and_block()?;
3049-
3050-
Err(errors::GenBlock { span: self.prev_token.span }
3051-
.into_diagnostic(&self.sess.span_diagnostic))
3052-
}
3053-
30543045
fn is_do_catch_block(&self) -> bool {
30553046
self.token.is_keyword(kw::Do)
30563047
&& self.is_keyword_ahead(1, &[kw::Catch])
@@ -3077,13 +3068,18 @@ impl<'a> Parser<'a> {
30773068
&& self.token.uninterpolated_span().at_least_rust_2024()
30783069
}
30793070

3080-
/// Parses an `async move? {...}` expression.
3081-
fn parse_async_block(&mut self) -> PResult<'a, P<Expr>> {
3071+
/// Parses an `async move? {...}` or `gen move? {...}` expression.
3072+
fn parse_gen_block(&mut self) -> PResult<'a, P<Expr>> {
30823073
let lo = self.token.span;
3083-
self.expect_keyword(kw::Async)?;
3074+
let kind = if self.eat_keyword(kw::Async) {
3075+
GenBlockKind::Async
3076+
} else {
3077+
assert!(self.eat_keyword(kw::Gen));
3078+
GenBlockKind::Gen
3079+
};
30843080
let capture_clause = self.parse_capture_clause()?;
30853081
let (attrs, body) = self.parse_inner_attrs_and_block()?;
3086-
let kind = ExprKind::Async(capture_clause, body);
3082+
let kind = ExprKind::Gen(capture_clause, body, kind);
30873083
Ok(self.mk_expr_with_attrs(lo.to(self.prev_token.span), kind, attrs))
30883084
}
30893085

@@ -3614,7 +3610,7 @@ impl MutVisitor for CondChecker<'_> {
36143610
| ExprKind::Match(_, _)
36153611
| ExprKind::Closure(_)
36163612
| ExprKind::Block(_, _)
3617-
| ExprKind::Async(_, _)
3613+
| ExprKind::Gen(_, _, _)
36183614
| ExprKind::TryBlock(_)
36193615
| ExprKind::Underscore
36203616
| ExprKind::Path(_, _)

compiler/rustc_passes/src/hir_stats.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -567,10 +567,10 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
567567
(self, e, e.kind, Id::None, ast, Expr, ExprKind),
568568
[
569569
Array, ConstBlock, Call, MethodCall, Tup, Binary, Unary, Lit, Cast, Type, Let,
570-
If, While, ForLoop, Loop, Match, Closure, Block, Async, Await, TryBlock, Assign,
570+
If, While, ForLoop, Loop, Match, Closure, Block, Await, TryBlock, Assign,
571571
AssignOp, Field, Index, Range, Underscore, Path, AddrOf, Break, Continue, Ret,
572572
InlineAsm, FormatArgs, OffsetOf, MacCall, Struct, Repeat, Paren, Try, Yield, Yeet,
573-
Become, IncludedBytes, Err
573+
Become, IncludedBytes, Gen, Err
574574
]
575575
);
576576
ast_visit::walk_expr(self, e)

compiler/rustc_resolve/src/def_collector.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
260260
Async::No => closure_def,
261261
}
262262
}
263-
ExprKind::Async(_, _) => self.create_def(expr.id, DefPathData::ClosureExpr, expr.span),
263+
ExprKind::Gen(_, _, _) => self.create_def(expr.id, DefPathData::ClosureExpr, expr.span),
264264
_ => self.parent_def,
265265
};
266266

compiler/rustc_resolve/src/late.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4321,7 +4321,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
43214321
);
43224322
}
43234323
ExprKind::Closure(..) => visit::walk_expr(self, expr),
4324-
ExprKind::Async(..) => {
4324+
ExprKind::Gen(..) => {
43254325
self.with_label_rib(RibKind::ClosureOrAsync, |this| visit::walk_expr(this, expr));
43264326
}
43274327
ExprKind::Repeat(ref elem, ref ct) => {

src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,7 @@ fn ident_difference_expr_with_base_location(
578578
| (Assign(_, _, _), Assign(_, _, _))
579579
| (TryBlock(_), TryBlock(_))
580580
| (Await(_, _), Await(_, _))
581-
| (Async(_, _), Async(_, _))
581+
| (Gen(_, _, _), Gen(_, _, _))
582582
| (Block(_, _), Block(_, _))
583583
| (Closure(_), Closure(_))
584584
| (Match(_, _), Match(_, _))

src/tools/clippy/clippy_utils/src/ast_utils.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
211211
&& eq_fn_decl(lf, rf)
212212
&& eq_expr(le, re)
213213
},
214-
(Async(lc, lb), Async(rc, rb)) => lc == rc && eq_block(lb, rb),
214+
(Gen(lc, lb, lk), Gen(rc, rb, rk)) => lc == rc && eq_block(lb, rb) && lk == rk,
215215
(Range(lf, lt, ll), Range(rf, rt, rl)) => ll == rl && eq_expr_opt(lf, rf) && eq_expr_opt(lt, rt),
216216
(AddrOf(lbk, lm, le), AddrOf(rbk, rm, re)) => lbk == rbk && lm == rm && eq_expr(le, re),
217217
(Path(lq, lp), Path(rq, rp)) => both(lq, rq, eq_qself) && eq_path(lp, rp),

src/tools/clippy/clippy_utils/src/sugg.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ impl<'a> Sugg<'a> {
190190
(snip, false) => Sugg::MaybeParen(snip),
191191
(snip, true) => Sugg::NonParen(snip),
192192
},
193-
ast::ExprKind::Async(..)
193+
ast::ExprKind::Gen(..)
194194
| ast::ExprKind::Block(..)
195195
| ast::ExprKind::Break(..)
196196
| ast::ExprKind::Call(..)

src/tools/rustfmt/src/closures.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ fn rewrite_closure_expr(
188188
fn allow_multi_line(expr: &ast::Expr) -> bool {
189189
match expr.kind {
190190
ast::ExprKind::Match(..)
191-
| ast::ExprKind::Async(..)
191+
| ast::ExprKind::Gen(..)
192192
| ast::ExprKind::Block(..)
193193
| ast::ExprKind::TryBlock(..)
194194
| ast::ExprKind::Loop(..)

src/tools/rustfmt/src/expr.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -367,15 +367,15 @@ pub(crate) fn format_expr(
367367
))
368368
}
369369
}
370-
ast::ExprKind::Async(capture_by, ref block) => {
370+
ast::ExprKind::Gen(capture_by, ref block, ref kind) => {
371371
let mover = if capture_by == ast::CaptureBy::Value {
372372
"move "
373373
} else {
374374
""
375375
};
376376
if let rw @ Some(_) = rewrite_single_line_block(
377377
context,
378-
format!("async {mover}").as_str(),
378+
format!("{kind} {mover}").as_str(),
379379
block,
380380
Some(&expr.attrs),
381381
None,
@@ -386,7 +386,7 @@ pub(crate) fn format_expr(
386386
// 6 = `async `
387387
let budget = shape.width.saturating_sub(6);
388388
Some(format!(
389-
"async {mover}{}",
389+
"{kind} {mover}{}",
390390
rewrite_block(
391391
block,
392392
Some(&expr.attrs),
@@ -1371,7 +1371,7 @@ pub(crate) fn can_be_overflowed_expr(
13711371
}
13721372

13731373
// Handle always block-like expressions
1374-
ast::ExprKind::Async(..) | ast::ExprKind::Block(..) | ast::ExprKind::Closure(..) => true,
1374+
ast::ExprKind::Gen(..) | ast::ExprKind::Block(..) | ast::ExprKind::Closure(..) => true,
13751375

13761376
// Handle `[]` and `{}`-like expressions
13771377
ast::ExprKind::Array(..) | ast::ExprKind::Struct(..) => {

0 commit comments

Comments
 (0)