The addr_of!
docs imply that it can handle unaligned pointers so long as a reference is never materialized from that pointer (which would be insta-UB). However, running the following program under Miri fails:
fn main() {
#[repr(C, packed)]
struct Unalign<T>(T);
#[repr(C)]
struct Foo {
a: u8,
b: u16,
}
// Has alignment `align_of::<T>()`, and the `Unalign<T>`
// is at byte offset 1; so long as `align_of::<T>() > 1`,
// the contained `T` is misaligned.
#[repr(C)]
struct Misalign<T>(u8, Unalign<T>, [T; 0]);
let u = Misalign(0, Unalign(Foo{ a: 1, b: 2 }), []);
let u_ptr: *const Unalign<Foo> = &u.1;
// Sound because `Unalign` contains a `T` and nothing else.
let f_ptr: *const Foo = u_ptr.cast();
// Should be sound because we never construct a reference.
let addr_of_b: *const u16 = unsafe { core::ptr::addr_of!((*f_ptr).b) };
println!("{:?}", addr_of_b);
}
Here's the failure:
error: Undefined Behavior: accessing memory with alignment 1, but alignment 2 is required
--> src/main.rs:22:42
|
22 | let addr_of_b: *const u16 = unsafe { core::ptr::addr_of!((*f_ptr).b) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ accessing memory with alignment 1, but alignment 2 is required
|
= 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 /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:1980:5: 1980:22
= note: this error originates in the macro `core::ptr::addr_of` (in Nightly builds, run with -Z macro-backtrace for more info)
Am I misunderstanding addr_of!
's requirements? Is there any way to get this to be sound?