Skip to content

Miscompile in DestinationPropagation? #146383

@saethlin

Description

@saethlin

Reduced example from rustlantis, which is accepted by Miri using Tree Borrows without optimizations enabled:

#![feature(custom_mir, core_intrinsics)]
#![allow(internal_features)]

use std::intrinsics::mir::*;

fn dump_var<T>(_: T) {}

#[custom_mir(dialect = "runtime")]
fn main() {
    mir!{
        let _1: (u8,);
        let _2: (u8,);
        let _3: (u8,);
        let _4: (u8,);
        let _5: ();
        {
            _3.0 = 0;
            _1 = _3;
            _4 = (_1.0, );
            _1 = _4;
            Call(_5 = dump_var(_1), ReturnTo(bb1), UnwindUnreachable())
        }
        bb1 = {
            Return()
        }
    }
}

I'm sure this is caused by DestinationPropagation, because

cargo +nightly miri run

accepts this code, but

MIRIFLAGS=-Zmir-enable-passes=+DestinationPropagation cargo +nightly miri run

reports UB (ignore the span, it's confusing because the source code that's displayed is the pre-optimization MIR):

error: Undefined Behavior: reading memory at alloc125[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory
  --> src/main.rs:19:13
   |
19 |             _4 = (_1.0, );
   |             ^^^^^^^^^^^^^ Undefined Behavior occurred here
   |
   = 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
   = note: BACKTRACE:
   = note: inside `main` at src/main.rs:19:13: 19:26

The errant transformation rewrite the entire body:

-// MIR for `main` before DestinationPropagation
+// MIR for `main` after DestinationPropagation
 
 fn main() -> () {
     let mut _0: ();
     let mut _1: (u8,);
     let mut _2: (u8,);
     let mut _3: (u8,);
     let mut _4: (u8,);
     let mut _5: ();
 
     bb0: {
-        (_3.0: u8) = const 0_u8;
-        _1 = copy _3;
-        _4 = (copy (_1.0: u8),);
-        _1 = copy _4;
-        _5 = dump_var::<(u8,)>(copy _1) -> [return: bb1, unwind unreachable];
+        (_4.0: u8) = const 0_u8;
+        nop;
+        _4 = (copy (_4.0: u8),);
+        nop;
+        _5 = dump_var::<(u8,)>(copy _4) -> [return: bb1, unwind unreachable];
     }
 
     bb1: {
         return;
     }
 }

This is probably #145541 cc @cjgillot @Amanieu

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-mir-optArea: MIR optimizationsA-rustlantisA miscompilation found by RustlantisC-bugCategory: This is a bug.I-miscompileIssue: Correct Rust code lowers to incorrect machine codeS-has-mcveStatus: A Minimal Complete and Verifiable Example has been found for this issueT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions