repr(Rust)
unions (including MaybeUninit
) do not preserve padding bytes · Issue #99604 · rust-lang/rust (original) (raw)
The following program isn't detected to have any UB in miri, and doesn't hit the panic, but does panic when ran (with or without optimizations) normally (using LLVM)
use std::mem::MaybeUninit;
unsafe fn print(x: MaybeUninit::<(u16, u8)>) { let value: u32 = std::mem::transmute(x); if value != 0xaabbccdd { panic!("got {value:x}"); } }
fn main() { let mut x = MaybeUninit::<(u16, u8)>::uninit(); unsafe { x.as_mut_ptr().cast::().write_unaligned(0xaabbccdd); print(x); } }
Panics with "got bbccdd
", so the padding byte, presumably at aa
, got zeroed.
The LLVM IR for print
says it passes it as 2 arguments, so it makes sense that the padding is getting zeroed.
define void @_ZN10playground5print17hfd0afe434a63e3b7E(i16 %x.0, i8 %x.1) unnamed_addr #0 [...]
We (might?) already promise that MaybeUninit is just a bag of bytes that doesn't zero any padding, but we also promise that it has the ABI of T, and those two seem to be in conflict.