-
Notifications
You must be signed in to change notification settings - Fork 413
Description
Consider this example:
#![feature(core_intrinsics)]
#![feature(custom_mir)]
use std::intrinsics::mir::*;
#[custom_mir(dialect = "runtime", phase = "optimized")]
fn test(x: (i32, i32)) -> (i32, i32) {
mir! {
{
x = (x.1, x.0);
RET = x;
Return()
}
}
}
fn main() {
dbg!(test((0, 1)));
}Miri and codegen currently produce the rather nonsensical output (1, 1). Arguably this code should either be UB, or produce (1, 0).
A strict reading of the MIR docs would allow the code as written but disallow a variant with a triple instead of a tuple, based on this part of the Statement docs:
Specifically, overlap is permitted only for assignments of a type with BackendRepr::Scalar | BackendRepr::ScalarPair where all the scalar fields are Scalar::Initialized
However, that part is explicitly marked as WIP -- I doubt anyone intended to allow overlapping LHS and RHS for aggregate assignment, and if they are allowed, then the output (1, 1) is definitely not in accordance with any interpretation of MIR semantics.
So I think, at least for now, this should be considered UB. That means codegen doesn't need changing, but Miri does. This is somewhat non-trivial to detect since we (have to) do the assignment field-by-field so how would we even realize that we're reading from the same memory we are writing to?