Change:
Since few Rustc nightly versions I see a miscompilation problem with the code below. I am using: If I compile with: The code:
NB: this is because it needs an unstable CLI flag to reproduce.
cc since this might have something to do with recent const-eval work (apologies if I left anyone out)
I've managed to minify it to
Bisected it to , most probably the same issue as

Discussion:
impl<'tcx> MirPass<'tcx> for SimplifyArmIdentity { fn run_pass(&self, _: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { <del> for bb in body.basic_blocks_mut() { </del> <ins> let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut(); for bb in basic_blocks { </ins> // Need 3 statements: let (s0, s1, s2) = match &mut *bb.statements { [s0, s1, s2] => (s0, s1, s2),

Some(x) => x, }; if local_tmp_s0 != local_tmp_s1 <ins> // The field-and-variant information match up. </ins> || vf_s0 != vf_s1 <ins> // Source and target locals have the same type. // FIXME(Centril | oli-obk): possibly relax to same layout? || local_decls[local_0].ty != local_decls[local_1].ty // We're setting the discriminant of `local_0` to this variant. </ins> || Some((local_0, vf_s0.var_idx)) != match_set_discr(s2) { continue;

<ins> // Checks that `SimplifyArmIdentity` is not applied if enums have incompatible layouts. // Regression test for issue #66856. // // compile-flags: -Zmir-opt-level=2 enum Src { Foo(u8), Bar, } enum Dst { Foo(u8), } fn main() { let e: Src = Src::Foo(0); let _: Dst = match e { Src::Foo(x) => Dst::Foo(x), Src::Bar => Dst::Foo(0), }; } // END RUST SOURCE // START rustc.main.SimplifyArmIdentity.before.mir // fn main() -> () { //     ... //     bb0: { //         StorageLive(_1); //         ((_1 as Foo).0: u8) = const 0u8; //         discriminant(_1) = 0; //         StorageLive(_2); //         _3 = discriminant(_1); //         switchInt(move _3) -> [0isize: bb3, 1isize: bb1, otherwise: bb2]; //     } //     bb1: { //         ((_2 as Foo).0: u8) = const 0u8; //         discriminant(_2) = 0; //         goto -> bb4; //     } //     ... //     bb3: { //         _4 = ((_1 as Foo).0: u8); //         ((_2 as Foo).0: u8) = move _4; //         discriminant(_2) = 0; //         goto -> bb4; //     } //     ... // } // END rustc.main.SimplifyArmIdentity.before.mir // START rustc.main.SimplifyArmIdentity.after.mir // fn main() -> () { //     ... //     bb0: { //         StorageLive(_1); //         ((_1 as Foo).0: u8) = const 0u8; //         discriminant(_1) = 0; //         StorageLive(_2); //         _3 = discriminant(_1); //         switchInt(move _3) -> [0isize: bb3, 1isize: bb1, otherwise: bb2]; //     } //     bb1: { //         ((_2 as Foo).0: u8) = const 0u8; //         discriminant(_2) = 0; //         goto -> bb4; //     } //     ... //     bb3: { //         _4 = ((_1 as Foo).0: u8); //         ((_2 as Foo).0: u8) = move _4; //         discriminant(_2) = 0; //         goto -> bb4; //     } //     ... // } // END rustc.main.SimplifyArmIdentity.after.mir </ins>

<ins> // This used to mis-compile because the mir-opt `SimplifyArmIdentity` // did not check that the types matched up in the `Ok(r)` branch. // // run-pass // compile-flags: -Zmir-opt-level=2 #[derive(Debug, PartialEq, Eq)] enum SpecialsRes { Res(u64) } fn e103() -> SpecialsRes { if let Ok(r) = "1".parse() { SpecialsRes::Res(r) } else { SpecialsRes::Res(42) } } fn main() { assert_eq!(e103(), SpecialsRes::Res(1)); } </ins>