Closed
Description
Miri's CI started failing recently, with an error similar to:
error: Undefined Behavior: StorageLive on a local that was already live
--> foo.rs:9:52
|
9 | Foo::Variant1(x) | Foo::Variant2(x) if x => {}
| ^ StorageLive on a local that was already live
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
It seems likely that this is a regression from #88572. cc @matthewjasper
Thanks to @hyd-dev for doing the original minimization.
MCVE
enum Foo {
Variant1(bool),
Variant2(bool),
}
fn main() {
loop {
match Foo::Variant1(true) {
Foo::Variant1(x) | Foo::Variant2(x) if x => {}
_ => {}
}
}
}
Generated MIR (from right after building)
// MIR for `main` 0 mir_map
fn main() -> () {
let mut _0: (); // return place in scope 0 at foo.rs:6:11: 6:11
let mut _1: !; // in scope 0 at foo.rs:7:5: 12:6
let mut _2: (); // in scope 0 at foo.rs:6:1: 13:2
let mut _3: Foo; // in scope 0 at foo.rs:8:15: 8:34
let mut _4: isize; // in scope 0 at foo.rs:9:13: 9:29
let mut _5: &Foo; // in scope 0 at foo.rs:8:15: 8:34
let _6: bool; // in scope 0 at foo.rs:9:27: 9:28
let _7: &bool; // in scope 0 at foo.rs:9:27: 9:28
let mut _8: bool; // in scope 0 at foo.rs:9:52: 9:53
let mut _9: bool; // in scope 0 at foo.rs:9:52: 9:53
scope 1 {
debug x => _6; // in scope 1 at foo.rs:9:27: 9:28
debug x => _7; // in scope 1 at foo.rs:9:27: 9:28
}
bb0: {
StorageLive(_1); // scope 0 at foo.rs:7:5: 12:6
goto -> bb1; // scope 0 at foo.rs:7:5: 12:6
}
bb1: {
falseUnwind -> [real: bb2, cleanup: bb19]; // scope 0 at foo.rs:7:5: 12:6
}
bb2: {
StorageLive(_3); // scope 0 at foo.rs:8:15: 8:34
_3 = Foo::Variant1(const true); // scope 0 at foo.rs:8:15: 8:34
FakeRead(ForMatchedPlace(None), _3); // scope 0 at foo.rs:8:15: 8:34
_4 = discriminant(_3); // scope 0 at foo.rs:8:15: 8:34
switchInt(move _4) -> [0_isize: bb3, 1_isize: bb5, otherwise: bb4]; // scope 0 at foo.rs:8:9: 8:34
}
bb3: {
falseEdge -> [real: bb8, imaginary: bb5]; // scope 0 at foo.rs:9:13: 9:29
}
bb4: {
_2 = const (); // scope 0 at foo.rs:10:18: 10:20
goto -> bb16; // scope 0 at foo.rs:10:18: 10:20
}
bb5: {
falseEdge -> [real: bb12, imaginary: bb4]; // scope 0 at foo.rs:9:32: 9:48
}
bb6: {
goto -> bb4; // scope 0 at foo.rs:8:9: 8:34
}
bb7: {
_2 = const (); // scope 1 at foo.rs:9:57: 9:59
StorageDead(_6); // scope 0 at foo.rs:9:58: 9:59
StorageDead(_9); // scope 0 at foo.rs:9:58: 9:59
StorageDead(_7); // scope 0 at foo.rs:9:58: 9:59
goto -> bb16; // scope 0 at foo.rs:9:58: 9:59
}
bb8: {
StorageLive(_7); // scope 0 at foo.rs:9:27: 9:28
_7 = &((_3 as Variant1).0: bool); // scope 0 at foo.rs:9:27: 9:28
_5 = &shallow _3; // scope 0 at foo.rs:8:15: 8:34
StorageLive(_8); // scope 0 at foo.rs:9:52: 9:53
_8 = (*_7); // scope 0 at foo.rs:9:52: 9:53
switchInt(move _8) -> [false: bb10, otherwise: bb9]; // scope 0 at foo.rs:9:52: 9:53
}
bb9: {
FakeRead(ForMatchGuard, _5); // scope 0 at foo.rs:9:52: 9:53
FakeRead(ForGuardBinding, _7); // scope 0 at foo.rs:9:52: 9:53
StorageLive(_6); // scope 0 at foo.rs:9:27: 9:28
_6 = ((_3 as Variant1).0: bool); // scope 0 at foo.rs:9:27: 9:28
goto -> bb7; // scope 0 at foo.rs:8:9: 11:10
}
bb10: {
goto -> bb11; // scope 0 at foo.rs:9:52: 9:53
}
bb11: {
StorageDead(_8); // scope 0 at foo.rs:9:58: 9:59
StorageDead(_7); // scope 0 at foo.rs:9:58: 9:59
falseEdge -> [real: bb4, imaginary: bb5]; // scope 0 at foo.rs:9:52: 9:53
}
bb12: {
StorageLive(_7); // scope 0 at foo.rs:9:46: 9:47
_7 = &((_3 as Variant2).0: bool); // scope 0 at foo.rs:9:46: 9:47
_5 = &shallow _3; // scope 0 at foo.rs:8:15: 8:34
StorageLive(_9); // scope 0 at foo.rs:9:52: 9:53
_9 = (*_7); // scope 0 at foo.rs:9:52: 9:53
switchInt(move _9) -> [false: bb14, otherwise: bb13]; // scope 0 at foo.rs:9:52: 9:53
}
bb13: {
FakeRead(ForMatchGuard, _5); // scope 0 at foo.rs:9:52: 9:53
FakeRead(ForGuardBinding, _7); // scope 0 at foo.rs:9:52: 9:53
StorageLive(_6); // scope 0 at foo.rs:9:46: 9:47
_6 = ((_3 as Variant2).0: bool); // scope 0 at foo.rs:9:46: 9:47
goto -> bb7; // scope 0 at foo.rs:8:9: 11:10
}
bb14: {
goto -> bb15; // scope 0 at foo.rs:9:52: 9:53
}
bb15: {
StorageDead(_9); // scope 0 at foo.rs:9:58: 9:59
StorageDead(_7); // scope 0 at foo.rs:9:58: 9:59
falseEdge -> [real: bb6, imaginary: bb4]; // scope 0 at foo.rs:9:52: 9:53
}
bb16: {
StorageDead(_3); // scope 0 at foo.rs:12:5: 12:6
goto -> bb1; // scope 0 at foo.rs:7:5: 12:6
}
bb17: {
unreachable; // scope 0 at foo.rs:7:5: 12:6
}
bb18: {
StorageDead(_1); // scope 0 at foo.rs:12:5: 12:6
return; // scope 0 at foo.rs:13:2: 13:2
}
bb19 (cleanup): {
resume; // scope 0 at foo.rs:6:1: 13:2
}
}
EDIT: updated the MIR output so it's from the latest nightly