Open
Description
use core::mem::size_of;
use core::num::NonZeroU8;
struct Foo(u8, u16);
struct Bar(u8, u16, NonZeroU8);
fn main() {
dbg!(size_of::<Foo>());
dbg!(size_of::<Option<Foo>>());
dbg!(size_of::<Bar>());
dbg!(size_of::<Option<Bar>>());
}
Output:
[src/main.rs:8] size_of::<Foo>() = 4
[src/main.rs:9] size_of::<Option<Foo>>() = 6
[src/main.rs:10] size_of::<Bar>() = 4
[src/main.rs:11] size_of::<Option<Bar>>() = 4
size_of::<Foo>()
returns 4 as expected. size_of::<Option<Foo>>()
returns 6, indicating that the unused padding byte is not being used to store the tag for the Option
. (playground)
However, by adding a field that is NonZero*
, the compiler is able to take advantage of the unused bit. This, of course, only works with one bit, not the potential eight.
In this example, the size of Bar
is the same as Foo
, but the situation that I ran across this with requires an increase in size of the struct to decrease the size of Option<CompoundStruct>
; needless to say this is a tradeoff I don't want to make.
Presumably the compiler could do some magic here to take advantage of the niche values.