Yes. It's a typed read, and i32's validity invariant requires that it be initialized.
If you want to do an untyped copy, that preserves bits (including uninitialized-ness) exactly, copy it using copy_nonoverlapping in std::ptr - Rust instead.
Thanks for the reply. I always interpreted the spec as the UB must requires some kind of a usage of the value we obtained. Never really thought the obtaining action itself is defined as UB.
The x.double.1 is a read (a copy) of it, which is the use.
There are ways you can mention the place without it being a read, and which are thus not UB. For example, MIRI confirms that this is allowed:
let x = Foo { single: 7 };
unsafe {
// Not a read, because `_` is special.
let _ = x.double.1;
}
let value = unsafe {
x.single
};
println!("{}", value);