Skip to content

Niche-filling layouts are picked over tagged ones even when detrimental. #63866

Closed
@eddyb

Description

@eddyb

This prints the values in comments:

use std::num::NonZeroU8;

pub enum Foo { A(NonZeroU8, u32), B }
pub enum Bar { A(u8, u32), B }

fn main() {
    use std::mem::size_of;
    
    dbg!(size_of::<Foo>()); // = 8
    dbg!(size_of::<Option<Foo>>()); // = 12
    dbg!(size_of::<Option<Option<Foo>>>()); // = 12
    
    dbg!(size_of::<Bar>()); // = 8
    dbg!(size_of::<Option<Bar>>()); // = 8
    dbg!(size_of::<Option<Option<Bar>>>()); // = 8
}

Note that Foo contains strictly more opportunities for optimization, but it's optimized worse.

That's because it uses a "niche-filling" layout (using 0 in the NonZeroU8 field of A for B), but the "tag" layout wouldn't be any larger, because it has enough space in 8 bytes to fit the (byte-sized) tag, NonZeroU8 and u32.

Bar uses the tagged layout since it has no other choice, and ends up with 254 free values in the byte-sized tag, but Foo "jumps the gun" on using a pre-existing niche.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-layoutArea: Memory layout of typesC-enhancementCategory: An issue proposing an enhancement or a PR with one.I-slowIssue: Problems and improvements with respect to performance of generated code.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions