Auto merge of #116447 - oli-obk:gen_fn, r=compiler-errors
Implement `gen` blocks in the 2024 edition Coroutines tracking issue https://github.com/rust-lang/rust/issues/43122 `gen` block tracking issue https://github.com/rust-lang/rust/issues/117078 This PR implements `gen` blocks that implement `Iterator`. Most of the logic with `async` blocks is shared, and thus I renamed various types that were referring to `async` specifically. An example usage of `gen` blocks is ```rust fn foo() -> impl Iterator<Item = i32> { gen { yield 42; for i in 5..18 { if i.is_even() { continue } yield i * 2; } } } ``` The limitations (to be resolved) of the implementation are listed in the tracking issue
This commit is contained in:
commit
2cad938a81
75 changed files with 1096 additions and 148 deletions
|
@ -1235,7 +1235,7 @@ impl Expr {
|
|||
ExprKind::Closure(..) => ExprPrecedence::Closure,
|
||||
ExprKind::Block(..) => ExprPrecedence::Block,
|
||||
ExprKind::TryBlock(..) => ExprPrecedence::TryBlock,
|
||||
ExprKind::Async(..) => ExprPrecedence::Async,
|
||||
ExprKind::Gen(..) => ExprPrecedence::Gen,
|
||||
ExprKind::Await(..) => ExprPrecedence::Await,
|
||||
ExprKind::Assign(..) => ExprPrecedence::Assign,
|
||||
ExprKind::AssignOp(..) => ExprPrecedence::AssignOp,
|
||||
|
@ -1405,11 +1405,9 @@ pub enum ExprKind {
|
|||
Closure(Box<Closure>),
|
||||
/// A block (`'label: { ... }`).
|
||||
Block(P<Block>, Option<Label>),
|
||||
/// An async block (`async move { ... }`).
|
||||
///
|
||||
/// The async block used to have a `NodeId`, which was removed in favor of
|
||||
/// using the parent `NodeId` of the parent `Expr`.
|
||||
Async(CaptureBy, P<Block>),
|
||||
/// An `async` block (`async move { ... }`),
|
||||
/// or a `gen` block (`gen move { ... }`)
|
||||
Gen(CaptureBy, P<Block>, GenBlockKind),
|
||||
/// An await expression (`my_future.await`). Span is of await keyword.
|
||||
Await(P<Expr>, Span),
|
||||
|
||||
|
@ -1499,6 +1497,28 @@ pub enum ExprKind {
|
|||
Err,
|
||||
}
|
||||
|
||||
/// Used to differentiate between `async {}` blocks and `gen {}` blocks.
|
||||
#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
|
||||
pub enum GenBlockKind {
|
||||
Async,
|
||||
Gen,
|
||||
}
|
||||
|
||||
impl fmt::Display for GenBlockKind {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.modifier().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl GenBlockKind {
|
||||
pub fn modifier(&self) -> &'static str {
|
||||
match self {
|
||||
GenBlockKind::Async => "async",
|
||||
GenBlockKind::Gen => "gen",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The explicit `Self` type in a "qualified path". The actual
|
||||
/// path, including the trait and the associated item, is stored
|
||||
/// separately. `position` represents the index of the associated
|
||||
|
@ -2363,6 +2383,12 @@ pub enum Async {
|
|||
No,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Encodable, Decodable, Debug)]
|
||||
pub enum Gen {
|
||||
Yes { span: Span, closure_id: NodeId, return_impl_trait_id: NodeId },
|
||||
No,
|
||||
}
|
||||
|
||||
impl Async {
|
||||
pub fn is_async(self) -> bool {
|
||||
matches!(self, Async::Yes { .. })
|
||||
|
|
|
@ -1418,7 +1418,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
|
|||
vis.visit_block(blk);
|
||||
visit_opt(label, |label| vis.visit_label(label));
|
||||
}
|
||||
ExprKind::Async(_capture_by, body) => {
|
||||
ExprKind::Gen(_capture_by, body, _) => {
|
||||
vis.visit_block(body);
|
||||
}
|
||||
ExprKind::Await(expr, await_kw_span) => {
|
||||
|
|
|
@ -197,6 +197,7 @@ pub fn ident_can_begin_expr(name: Symbol, span: Span, is_raw: bool) -> bool {
|
|||
kw::Continue,
|
||||
kw::False,
|
||||
kw::For,
|
||||
kw::Gen,
|
||||
kw::If,
|
||||
kw::Let,
|
||||
kw::Loop,
|
||||
|
|
|
@ -46,7 +46,7 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
|
|||
Closure(closure) => {
|
||||
expr = &closure.body;
|
||||
}
|
||||
Async(..) | Block(..) | ForLoop(..) | If(..) | Loop(..) | Match(..) | Struct(..)
|
||||
Gen(..) | Block(..) | ForLoop(..) | If(..) | Loop(..) | Match(..) | Struct(..)
|
||||
| TryBlock(..) | While(..) => break Some(expr),
|
||||
_ => break None,
|
||||
}
|
||||
|
|
|
@ -285,7 +285,7 @@ pub enum ExprPrecedence {
|
|||
Block,
|
||||
TryBlock,
|
||||
Struct,
|
||||
Async,
|
||||
Gen,
|
||||
Await,
|
||||
Err,
|
||||
}
|
||||
|
@ -351,7 +351,7 @@ impl ExprPrecedence {
|
|||
| ExprPrecedence::ConstBlock
|
||||
| ExprPrecedence::Block
|
||||
| ExprPrecedence::TryBlock
|
||||
| ExprPrecedence::Async
|
||||
| ExprPrecedence::Gen
|
||||
| ExprPrecedence::Struct
|
||||
| ExprPrecedence::Err => PREC_PAREN,
|
||||
}
|
||||
|
|
|
@ -872,7 +872,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
|
|||
walk_list!(visitor, visit_label, opt_label);
|
||||
visitor.visit_block(block);
|
||||
}
|
||||
ExprKind::Async(_, body) => {
|
||||
ExprKind::Gen(_, body, _) => {
|
||||
visitor.visit_block(body);
|
||||
}
|
||||
ExprKind::Await(expr, _) => visitor.visit_expr(expr),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue