Change:
<del> - // MIR for `main` before SimplifyArmIdentity + // MIR for `main` after SimplifyArmIdentity fn main() -> () { let mut _0: ();                      // return place in scope 0 at $DIR/issue_73223.rs:+0:11: +0:11 let _1: i32;                         // in scope 0 at $DIR/issue_73223.rs:+1:9: +1:14 let mut _2: std::option::Option<i32>; // in scope 0 at $DIR/issue_73223.rs:+1:23: +1:30 let mut _3: isize;                   // in scope 0 at $DIR/issue_73223.rs:+2:9: +2:16 let _4: i32;                         // in scope 0 at $DIR/issue_73223.rs:+2:14: +2:15 let mut _6: i32;                     // in scope 0 at $DIR/issue_73223.rs:+6:22: +6:27 let mut _7: &i32;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _8: &i32;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _11: bool;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _12: bool;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _13: i32;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _14: i32;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let _16: !;                          // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _17: core::panicking::AssertKind; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _18: &i32;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let _19: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _20: &i32;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let _21: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _22: std::option::Option<std::fmt::Arguments<'_>>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _24: &i32;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _25: &i32;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL scope 1 { debug split => _1;               // in scope 1 at $DIR/issue_73223.rs:+1:9: +1:14 let _5: std::option::Option<i32>; // in scope 1 at $DIR/issue_73223.rs:+6:9: +6:14 scope 3 { debug _prev => _5;           // in scope 3 at $DIR/issue_73223.rs:+6:9: +6:14 let _9: &i32;                // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let _10: &i32;               // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _23: &i32;           // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL scope 4 { debug left_val => _9;    // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL debug right_val => _10;  // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let _15: core::panicking::AssertKind; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL scope 5 { debug kind => _15;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL } } } } scope 2 { debug v => _4;                   // in scope 2 at $DIR/issue_73223.rs:+2:14: +2:15 } bb0: { StorageLive(_1);                 // scope 0 at $DIR/issue_73223.rs:+1:9: +1:14 StorageLive(_2);                 // scope 0 at $DIR/issue_73223.rs:+1:23: +1:30 Deinit(_2);                      // scope 0 at $DIR/issue_73223.rs:+1:23: +1:30 ((_2 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue_73223.rs:+1:23: +1:30 discriminant(_2) = 1;            // scope 0 at $DIR/issue_73223.rs:+1:23: +1:30 _3 = const 1_isize;              // scope 0 at $DIR/issue_73223.rs:+1:23: +1:30 goto -> bb3;                     // scope 0 at $DIR/issue_73223.rs:+1:17: +1:30 } bb1: { StorageDead(_2);                 // scope 0 at $DIR/issue_73223.rs:+4:6: +4:7 StorageDead(_1);                 // scope 0 at $DIR/issue_73223.rs:+8:1: +8:2 return;                          // scope 0 at $DIR/issue_73223.rs:+8:2: +8:2 } bb2: { unreachable;                     // scope 0 at $DIR/issue_73223.rs:+1:23: +1:30 } bb3: { StorageLive(_4);                 // scope 0 at $DIR/issue_73223.rs:+2:14: +2:15 _4 = ((_2 as Some).0: i32);      // scope 0 at $DIR/issue_73223.rs:+2:14: +2:15 _1 = _4;                         // scope 2 at $DIR/issue_73223.rs:+2:20: +2:21 StorageDead(_4);                 // scope 0 at $DIR/issue_73223.rs:+2:20: +2:21 StorageDead(_2);                 // scope 0 at $DIR/issue_73223.rs:+4:6: +4:7 StorageLive(_5);                 // scope 1 at $DIR/issue_73223.rs:+6:9: +6:14 StorageLive(_6);                 // scope 1 at $DIR/issue_73223.rs:+6:22: +6:27 _6 = _1;                         // scope 1 at $DIR/issue_73223.rs:+6:22: +6:27 Deinit(_5);                      // scope 1 at $DIR/issue_73223.rs:+6:17: +6:28 ((_5 as Some).0: i32) = move _6; // scope 1 at $DIR/issue_73223.rs:+6:17: +6:28 discriminant(_5) = 1;            // scope 1 at $DIR/issue_73223.rs:+6:17: +6:28 StorageDead(_6);                 // scope 1 at $DIR/issue_73223.rs:+6:27: +6:28 StorageLive(_24);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_25);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_7);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _7 = &_1;                        // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_8);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _23 = const _;                   // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } _8 = _23;                        // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL Deinit(_24);                     // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL Deinit(_25);                     // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _24 = move _7;                   // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _25 = move _8;                   // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_8);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_7);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_9);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _9 = _24;                        // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_10);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _10 = _25;                       // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_11);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_12);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_13);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _13 = (*_9);                     // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_14);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _14 = const 1_i32;               // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _12 = Eq(move _13, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_14);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_13);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _11 = Not(move _12);             // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_12);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL switchInt(move _11) -> [0: bb5, otherwise: bb4]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL } bb4: { StorageLive(_15);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL Deinit(_15);                     // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL discriminant(_15) = 0;           // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_16);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_17);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _17 = const core::panicking::AssertKind::Eq; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) } StorageLive(_18);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_19);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _19 = _9;                        // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _18 = _19;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_20);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_21);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _21 = _10;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _20 = _21;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_22);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL Deinit(_22);                     // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL discriminant(_22) = 0;           // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _16 = core::panicking::assert_failed::<i32, i32>(const core::panicking::AssertKind::Eq, move _18, move _20, move _22); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL // + literal: Const { ty: for<'a, 'b, 'c> fn(core::panicking::AssertKind, &'a i32, &'b i32, Option<Arguments<'c>>) -> ! {core::panicking::assert_failed::<i32, i32>}, val: Value(<ZST>) } // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) } } bb5: { StorageDead(_11);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_10);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_9);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_24);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_25);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_5);                 // scope 1 at $DIR/issue_73223.rs:+8:1: +8:2 StorageDead(_1);                 // scope 0 at $DIR/issue_73223.rs:+8:1: +8:2 return;                          // scope 0 at $DIR/issue_73223.rs:+8:2: +8:2 } } </del>

Discussion:
<!-- Thank you for finding an Internal Compiler Error! If possible, try to provide a minimal verifiable example. You can read "Rust Bug Minimization Patterns" for how to create smaller examples. --from <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --: <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summary<strongBacktrace</strong</summary<p</p</details
This is probably
Hm, the issue is already a couple of weeks old while I was not able to reproduce this one a few days ago.
This happens since :thinking:
modify labels: +requires-nightly
Yes, this is a duplicate of . The changes from fixed the validator, so the bug is now correctly identified when incorrect transform is enabled with .
Does it still ICE if you enable optimizations?
It does, looks like it's still an ICE
This (and ) no longer ICE since , seems to be the case for any opt level cc is that intentional or is still pending?
This is only the case because the changes to MIR make that opt completely broken and just never fire under any circumstances. needs to be revised because of that change, but the plan is still for it to fix these bugs for real

Reproduction here: There's more info in the readme on that repo. Essentially, I have some code that segfaults while debug-printing an enum. The enum has one variant, followed by 11 empty variants. The repro only creates one of the empty ones, but it appears the debug routine attempts to read the string variant. It occurs in the context of some mutually recursive functions building a fairly simple datastructure by walking another. I have tried hard to minimise the repro but it could be better, but it's a bit fragile so I don't know what else I can remove. With a quick glance at the commit that bisect-rustc found, it looks like it could be related to optimising match arms, so that could be a start. Edit: for some linkage, the commit below merges , which 're-enables SimplifyArmIdentity'. searched nightlies: from nightly-2020-05-08 to nightly-2020-09-23 regressed nightly: nightly-2020-09-09 searched commits: from to regressed commit: <details<summarybisected with <a href=''cargo-bisect-rustc</av0.5.2</summaryHost triple: x8664-apple-darwin Reproduce with: </detailsNote that the function is the one in which the debug segfaults, and it is debugging a larger structure. I have also seen it segfault when cloning just the enum, which is the String+11x one mentioned above. <details<summaryBacktrace from rust-lldb</summary<p</p</details
Can't reproduce with .
I don’t have MacOS, so I can’t test this myself easily. Here’s some tags though: modify labels: O-macos, T-compiler, E-needs-mcve. And someone might wanna add I-unsound. Edit: To clarify, I’m not seeing any segfault on Windows or Linux (both 2020-09-27). Oddly enough, I’m getting on Windows, and on Linux. And I get without on both (also with on or or in , for that matter). Is this program supposed to be deterministic?

Perhaps you could test your less minimized version on Linux or Windows if you have access to those (since you said “the segfault started to change a bit”, so maybe the original version also segfaults on e.g. Linux).
Yes, the program is deterministic. I have seen similar wrong variants as well in the original code on macOS, so I'll go out in a limb and say that's the same bug on Linux. I can run a docker image if you like but I think you've already found it. The fragility I was referring to was in terms of "add a debug statement or delete some line, the issue goes away or pops up on a different input instead". But once you have it it produces the same segfault again and again. Given the complexity of the repro I'm not surprised that platform differences including calling conventions etc would affect reproducibility. I did run in Miri and it didn't find anything amiss, and produced correct output, ie the full .
Yeah I should have made it more obvious about macOS. I can still reproduce with:
Okay, I guess if it is supposed to be deterministic, this means I can then confirm the problem for linux and windows. I’m currently trying to reduce the example further, keeping the different behavior between and debug on linux. modify labels: -O-macos
Just got a segfault on Linux with a reduced example.
SimplifyArmIdentity moves an assignment to a local before StorageLive: cc
The label might also be appropriate.
A slight modification to repro and it will segfault in release mode: I can open a PR disabling this optimization so this doesn't hit beta next week.
Marking this as P-critical based on the
We can probably turn bugs like this into ICEs by extending the MIR validator (unless another optimization interferes before this hits codegen)
Because I didn’t feel like aborting my own minimization attempt, here’s the (heavily) reduced version of OPs example that I got: Causing a segfault on linux with nightly.
Your modified example does not consistently segfault. It only does so for nightlies newer than or so. The difference between and being printed does however start from the same commit that OPs bisection identified. (Actually it does not “segfault” at all but gives me an “invalid pointer” error.)

That sounds about right to me since should have been in nightly 2020-09-26. Prior to that PR, the mis-optimization was disabled in which should have been in nightly-2020-09-19 or so. Between ~2020-09-19 and ~2020-09-26 the issue should not appear. Does your repro work on the playground? When I try it with the nightly available, it works correctly.
Opened with an implementation of this. It does indeed catch this miscompilation.
It doesn’t seem to work in the playground. Even the (mostly) untouched original code that OP provided . (I.e. it correctly displays .) To demonstrate some online reproduction: (exit code 139).
I can reproduce with based on one of the MCVEs: stderr stdout
Perhaps change the title of the issue to "... in release mode"?
Is this still open so that the underlying issue is fixed? (The PR to temporarily disable the optimization was merged.)
We should leave this issue open to track fixing the optimization but we can remove some of the tags. Once a nightly goes out with the fix, we should also confirm it's no longer repros on the nightly channel. (I was going to wait for that confirmation before changing any labels)
Both repros work correctly on the latest nightly (2020-10-02), so I'm adjusting the tags accordingly. Thanks for reporting this issue!
Did you mean to remove ?
Yeah