In Other reprs - The Rustonomicon it says about #[repr(packed)]
:
repr(packed)
forces Rust to strip any padding, and only align the type to a byte
and about #[repr(align(n))]
:
repr(align(n))
(wheren
is a power of two) forces the type to have an alignment of at least n. [...] This is a modifier onrepr(C)
andrepr(rust)
. It is incompatible withrepr(packed)
.
However this:
It is incompatible with
repr(packed)
.
doesn't align with my intuitive understanding about what these mean.
My understanding is that #[repr(packed)]
eliminates the internal padding in a structure, so given:
#[repr(packed)]
struct Foo {
a: Box<()>,
b: u8,
c: Box<()>,
d: u8,
e: Box<()>,
f: u8,
g: Box<()>,
h: u8
}
the size is 36 rather than 40 (on a 64-bit machine, assuming rustc reorders the fields).
Whereas #[repr(align(n))]
defines the external alignment constraint of the structure - that is, the overall structure has to have a particular alignment, rather than the alignment of its most constrained element.
There's no conflict here; a struct declared:
#[repr(packed, align(64))]
struct Foo { ... }
simply means there's no internal padding, but in memory the overall structure must be 64-byte aligned (either in a Box
/Arc
, on the stack, or as an element of an array or other structure). Or to put it another way, it dictates the padding around it that must be applied by a container in order to retain the alignment constraint for the element.
(There is an inherent conflict here:
#[repr(align(128)]
struct Foo { ... }
#[repr(packed)]
struct Bar {
foo1: Foo,
foo2: Foo,
}
but this is just another instance of the general problem that repr(packed)
allows unaligned references to escape which could cause traps or UB.)
I feel like this is something that would have been discussed before. Pointers? What am I missing?
Thanks.