Code change:
fn main() -> () { let mut _0: ();                      // return place in scope 0 at $DIR/issue-73223.rs:1:11: 1:11 <del> let _1: i32;                         // in scope 0 at $DIR/issue-73223.rs:2:9: 2:14 let mut _2: std::option::Option<i32>; // in scope 0 at $DIR/issue-73223.rs:2:23: 2:30 </del> <ins> let mut _1: std::option::Option<i32>; // in scope 0 at $DIR/issue-73223.rs:2:23: 2:30 let _2: i32;                         // in scope 0 at $DIR/issue-73223.rs:3:14: 3:15 </ins> let mut _4: (&i32, &i32);            // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL <del> let mut _5: bool;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _6: bool;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _7: i32;                     // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _8: &std::fmt::Arguments;    // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL let _9: std::fmt::Arguments;         // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _10: &[std::fmt::ArgumentV1; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL let _11: [std::fmt::ArgumentV1; 2];  // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _12: (&&i32, &&i32);         // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL let _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 </del> <ins> let mut _7: bool;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _8: bool;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _9: i32;                     // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _10: &std::fmt::Arguments;   // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL let _11: std::fmt::Arguments;        // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _12: &[std::fmt::ArgumentV1; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL let _13: [std::fmt::ArgumentV1; 2];  // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _14: (&&i32, &&i32);         // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL </ins> let _15: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL <del> let mut _16: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL </del> <ins> let mut _16: &&i32;                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL </ins> let mut _17: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL <ins> let mut _18: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL </ins> scope 1 { <del> debug split => _1;               // in scope 1 at $DIR/issue-73223.rs:2:9: 2:14 </del> <ins> debug split => _2;               // in scope 1 at $DIR/issue-73223.rs:2:9: 2:14 </ins> let _3: std::option::Option<i32>; // in scope 1 at $DIR/issue-73223.rs:7:9: 7:14 scope 3 { debug _prev => _3;           // in scope 3 at $DIR/issue-73223.rs:7:9: 7:14 <ins> let _5: &i32;                // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let _6: &i32;                // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL </ins> scope 4 { <del> debug left_val => _13;   // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL debug right_val => _15;  // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL </del> <ins> debug left_val => _5;    // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL debug right_val => _6;   // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL </ins> scope 5 { <del> debug arg0 => _20;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL debug arg1 => _23;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL </del> <ins> debug arg0 => _21;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL debug arg1 => _24;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL </ins> scope 6 { <del> debug x => _20;  // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL debug f => _19;  // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL let mut _18: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _19: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _20: &&i32; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL </del> <ins> debug x => _21;  // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL debug f => _20;  // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL let mut _19: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _20: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _21: &&i32; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL </ins> } scope 8 { <del> debug x => _23;  // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL debug f => _22;  // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL let mut _21: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _22: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _23: &&i32; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL </del> <ins> debug x => _24;  // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL debug f => _23;  // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL let mut _22: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _23: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _24: &&i32; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL </ins> } } scope 10 { <del> debug pieces => (_9.0: &[&str]); // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL debug args => _25;   // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL let mut _24: std::option::Option<&[std::fmt::rt::v1::Argument]>; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _25: &[std::fmt::ArgumentV1]; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL </del> <ins> debug pieces => _25; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL debug args => _27;   // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL let mut _25: &[&str]; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _26: std::option::Option<&[std::fmt::rt::v1::Argument]>; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _27: &[std::fmt::ArgumentV1]; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL </ins> } } } } scope 2 { <del> debug v => _1;                   // in scope 2 at $DIR/issue-73223.rs:3:14: 3:15 </del> <ins> debug v => _2;                   // in scope 2 at $DIR/issue-73223.rs:3:14: 3:15 </ins> } scope 7 { }

Related discussion:
text: This little matrix processing code shows miscompilation if compiled with: But it compiles correctly with: With:
Hmm, on first glance the replacement it performs looks correct: It replaces local () with the return place . Previously the return place was only used in the block by a copy statement, so this transformation should be correct. Maybe this part of the diff causes a problem? We're using our return place as the return destination for the inner call. It's possible that there's an undocumented (and maybe unintended) assumption that the return place is not reused like this, either in other MIR optimizations or in codegen. Haven't looked too deeply yet though.
Ah, there's this bad call in LLVM IR: It passes a reference to as both the return pointer, and the second (immutable) argument.
we have this corresponding MIR, where we already incorrectly pass a reference to as an argument, while also assigning the call result to it: The destination propagation pass already has code that prevents merging a call destination with one of the arguments, but here we pass a reference instead. Curiously, the was produced by merging with , which is not really something the pass should be doing since a reference is taken to , and we avoid touching any local that has its address taken.
The propagation is disabled only if both locals have their address taken. Changing that to be more conservative does fix this issue. Minimized:
Oof, this should have been an , not an
Thanks
Opened with a fix