You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Rollup merge of rust-lang#56100 - RalfJung:visiting-generators, r=oli-obk
generator fields are not necessarily initialized
Looking at the MIR we generate for generators, I think we deliberately leave fields of the generator uninitialized in ways that would be illegal if this was a normal struct (or rather, one would have to use `MaybeUninit`). Consider [this example](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=417b4a2950421b726dd7b307e9ee3bec):
```rust
#![feature(generators, generator_trait)]
fn main() {
let generator = || {
let mut x = Box::new(5);
{
let y = &mut *x;
*y = 5;
yield *y;
*y = 10;
}
*x
};
let _gen = generator;
}
```
It generates the MIR
```
fn main() -> (){
let mut _0: (); // return place
scope 1 {
scope 3 {
}
scope 4 {
let _2: [generator@src/main.rs:4:21: 13:6 for<'r> {std::boxed::Box<i32>, i32, &'r mut i32, ()}]; // "_gen" in scope 4 at src/main.rs:14:9: 14:13
}
}
scope 2 {
let _1: [generator@src/main.rs:4:21: 13:6 for<'r> {std::boxed::Box<i32>, i32, &'r mut i32, ()}]; // "generator" in scope 2 at src/main.rs:4:9: 4:18
}
bb0: {
StorageLive(_1); // bb0[0]: scope 0 at src/main.rs:4:9: 4:18
(_1.0: u32) = const 0u32; // bb0[1]: scope 0 at src/main.rs:4:21: 13:6
// ty::Const
// + ty: u32
// + val: Scalar(Bits { size: 4, bits: 0 })
// mir::Constant
// + span: src/main.rs:4:21: 13:6
// + ty: u32
// + literal: Const { ty: u32, val: Scalar(Bits { size: 4, bits: 0 }) }
StorageLive(_2); // bb0[2]: scope 1 at src/main.rs:14:9: 14:13
_2 = move _1; // bb0[3]: scope 1 at src/main.rs:14:16: 14:25
drop(_2) -> bb1; // bb0[4]: scope 1 at src/main.rs:15:1: 15:2
}
bb1: {
StorageDead(_2); // bb1[0]: scope 1 at src/main.rs:15:1: 15:2
StorageDead(_1); // bb1[1]: scope 0 at src/main.rs:15:1: 15:2
return; // bb1[2]: scope 0 at src/main.rs:15:2: 15:2
}
}
```
Notice how we only initialize the first field of `_1` (even though it contains a `Box`!), and then assign it to `_2`. This violates the rule "on assignment, all data must satisfy the validity invariant", and hence miri complains about this code.
What this PR effectively does is to change the validity invariant for generators such that it says nothing about the fields of the generator. We behave as if every field of the generator was wrapped in a `MaybeUninit`.
r? @oli-obk
Cc @nikomatsakis@eddyb@cramertj@withoutboats@Zoxc
0 commit comments