Skip to content

Padding to ensure a value is well-aligned is not used for niche value optimization #79531

Open
@jhpratt

Description

@jhpratt
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>>());
}

(Playground)

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-layoutArea: Memory layout of typesA-mir-optArea: MIR optimizations

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions