Coroutine desugaring creates mutable reference to uninitialized fields
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.2k
- PR merge metrics
- PR metrics pending
Description
This code triggers a UB error in Miri with -Zmiri-recursive-validation:
fn uninit_fields() {
// Test that uninhabited saved local doesn't make the entire variant uninhabited.
// (https://github.com/rust-lang/rust/issues/115145, https://github.com/rust-lang/rust/pull/118871)
fn conjure<T>() -> T {
loop {}
}
fn run<T>(x: bool, y: bool) {
let mut c = #[coroutine]
|| {
if x {
let _a: T;
if y {
_a = conjure::<T>();
}
yield ();
} else {
let _a: T;
if y {
_a = conjure::<T>();
}
yield ();
}
};
assert!(matches!(Pin::new(&mut c).resume(()), CoroutineState::Yielded(())));
assert!(matches!(Pin::new(&mut c).resume(()), CoroutineState::Complete(())));
}
run::<!>(false, false);
}
error: Undefined Behavior: constructing invalid value of type &mut {coroutine@src/tools/miri/tests/pass/coroutine.rs:296:9: 296:11}: at .<deref>.<coroutine-state(4)>.<captured-var(x)>, encountered a value of the never type `!`
--> src/tools/miri/tests/pass/coroutine.rs:312:35
|
312 | assert!(matches!(Pin::new(&mut c).resume(()), CoroutineState::Complete(())));
| ^^^^^^ Undefined Behavior occurred here
|
This is in the grey area between sound and unsound since we have not yet decided whether the data behind a reference has to be valid or not.
I am not fully sure what happens here. I thought coroutines wrap their fields in MaybeUninit exactly to avoid this. Also it is very strange that apparently the problem is with the field x, which should be a bool...
Is there some way to dump a bit more information about the generated coroutine to better understand what is going on?
Tracking issue: https://github.com/rust-lang/rust/issues/43122
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the reproducer in src/tools/miri/tests/pass/coroutine.rs and run it under Miri with -Zmiri-recursive-validation. Inspect the generated coroutine and desugaring to determine why the captured x field is treated as containing an uninitialized never value; done means explaining the validity issue and adding or updating a regression test if a compiler fix is identified.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100