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
Create a new ConstantKind variant (ZeroSized) for StableMIR
ZeroSized constants can be represented as `mir::Const::Val` even if their layout is not yet known. In those cases, CrateItem::body() was crashing when trying to convert a `ConstValue::ZeroSized` into its stable counterpart `ConstantKind::Allocated`.
Instead, we now map `ConstValue::ZeroSized` into a new variant: `ConstantKind::ZeroSized`.
**Note:** I didn't add any new test here since we already have covering tests in our project repository which I manually confirmed that will fix the issue.
ZeroSized constants can be represented as `mir::Const::Val` even if
their layout is not yet known. In those cases, CrateItem::body() was
crashing when trying to convert a `ConstValue::ZeroSized` into its
stable counterpart `ConstantKind::Allocated`.
Instead, we now map `ConstValue::ZeroSized` into a new variant:
`ConstantKind::ZeroSized`.
Add way to differentiate argument locals from other locals in Stable MIR
This PR resolvesrust-lang/project-stable-mir#47 which request a way to differentiate argument locals in a SMIR `Body` from other locals.
Specifically, this PR exposes the `arg_count` field from the MIR `Body`. However, I'm opening this as a draft PR because I think there are a few outstanding questions on how this information should be exposed and described. Namely:
- Is exposing `arg_count` the best way to surface this information to SMIR users? Would it be better to leave `arg_count` as a private field and add public methods (e.g. `fn arguments(&self) -> Iter<'_, LocalDecls>`) that may use the underlying `arg_count` info from the MIR body, but expose this information to users in a more convenient form? Or is it best to stick close to the current MIR convention?
- If the answer to the above point is to stick with the current MIR convention (`arg_count`), is it reasonable to also commit to sticking to the current MIR convention that the first local is always the return local, while the next `arg_count` locals are always the (in-order) argument locals?
- Should `Body` in SMIR only represent function bodies (as implied by the comment I added)? That seems to be the current case in MIR, but should this restriction always be the case for SMIR?
r? `@celinval`
r? `@oli-obk`
The latest locals() method in stable MIR returns slices instead of vecs.
This commit also includes fixes to the existing tests that previously
referenced the private locals field.
The word internal has connotations about information that's not exposed.
It's more accurate to say that the remaining locals apply only to the
inner part of the function, so I'm renaming them to inner locals.
Rename AsyncCoroutineKind to CoroutineSource
pulled out of https://github.com/rust-lang/rust/pull/116447
Also refactors the printing infra of `CoroutineSource` to be ready for easily extending it with a `Gen` variant for `gen` blocks
This is particularly helpful for the ui tests, but also could be helpful
for Stable MIR users who just want all the locals without needing to
concatenate responses
This commit hides the arg_count field in Body and instead exposes more
stable and user-friendly methods to get the return and argument locals.
As a result, Body instances must now be constructed using the `new`
function.
This field allows SMIR consumers to identify which locals correspond to
argument locals. It simply exposes the arg_count field from the MIR
representation.
We are not planning to support user generated constant in the
foreseeable future, so we are removing the Fold logic for now in
favor of the Instance::resolve logic.
The Instance::resolve was however incomplete, since we weren't handling
internalizing constants yet. Thus, I added that.
I decided to keep the Const fields private in case we decide to
translate them lazily.
Add stable Instance::body() and RustcInternal trait
The `Instance::body()` returns a monomorphized body.
For that, we had to implement visitor that monomorphize types and constants. We are also introducing the RustcInternal trait that will allow us to convert back from Stable to Internal.
Note that this trait is not yet visible for our users as it depends on Tables. We should probably add a new trait that can be exposed.
The tests here are very simple, and I'm planning on creating more exhaustive tests in the project-mir repo. But I was hoping to get some feedback here first.
r? ```@oli-obk```
The `Instance::body()` returns a monomorphized body.
For that, we had to implement visitor that monomorphize types and
constants. We are also introducing the RustcInternal trait that will
allow us to convert back from Stable to Internal.
Note that this trait is not yet visible for our users as it depends on
Tables. We should probably add a new trait that can be exposed.
Also add a few methods to instantiate instances and get an instance
definition.
We're still missing support to actually monomorphize the instance body.
In smir use `FxIndexMap` to store indexed ids
Previously we used `vec` for storing indexed types, which is fine for small cases but will lead to huge performance issues when we use `smir` for real world cases.
Addresses https://github.com/rust-lang/project-stable-mir/issues/35
r? ``@oli-obk``