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:
bors 2023-10-29 00:03:52 +00:00
commit 2cad938a81
75 changed files with 1096 additions and 148 deletions

View file

@ -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 { .. })