Code change:
let mut _5: &mut [u8; 1024];         // in scope 0 at $DIR/simple.rs:6:10: 6:18 let mut _6: &mut [u8; 1024];         // in scope 0 at $DIR/simple.rs:6:10: 6:18 scope 1 { <del> -         debug buf => _2;                 // in scope 1 at $DIR/simple.rs:5:9: 5:16 +         debug buf => _0;                 // in scope 1 at $DIR/simple.rs:5:9: 5:16 </del> <ins> debug buf => _2;                 // in scope 1 at $DIR/simple.rs:5:9: 5:16 </ins> } bb0: { <del> -         StorageLive(_2);                 // scope 0 at $DIR/simple.rs:5:9: 5:16 -         _2 = [const 0_u8; 1024];         // scope 0 at $DIR/simple.rs:5:19: 5:28 +         nop;                             // scope 0 at $DIR/simple.rs:5:9: 5:16 +         _0 = [const 0_u8; 1024];         // scope 0 at $DIR/simple.rs:5:19: 5:28 </del> <ins> StorageLive(_2);                 // scope 0 at $DIR/simple.rs:5:9: 5:16 _2 = [const 0_u8; 1024];         // scope 0 at $DIR/simple.rs:5:19: 5:28 </ins> StorageLive(_3);                 // scope 1 at $DIR/simple.rs:6:5: 6:19 StorageLive(_4);                 // scope 1 at $DIR/simple.rs:6:5: 6:9 _4 = _1;                         // scope 1 at $DIR/simple.rs:6:5: 6:9 StorageLive(_5);                 // scope 1 at $DIR/simple.rs:6:10: 6:18 StorageLive(_6);                 // scope 1 at $DIR/simple.rs:6:10: 6:18 <del> -         _6 = &mut _2;                    // scope 1 at $DIR/simple.rs:6:10: 6:18 +         _6 = &mut _0;                    // scope 1 at $DIR/simple.rs:6:10: 6:18 </del> <ins> _6 = &mut _2;                    // scope 1 at $DIR/simple.rs:6:10: 6:18 </ins> _5 = &mut (*_6);                 // scope 1 at $DIR/simple.rs:6:10: 6:18 _3 = move _4(move _5) -> bb1;    // scope 1 at $DIR/simple.rs:6:5: 6:19 }

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