Skip to content

Missed niche optimization (Box<impl Sized> & Box<impl Unsized>) #66029

Closed
@CAD97

Description

@CAD97

playground

enum WithBox {
    Sized(Box<Sized>),
    Unsized(Box<Unsized>),
}

enum WithUnitPtr {
    Sized(  /*   0usize    */ ptr::NonNull<()>),
    Unsized(ptr::NonNull<()>, usize           ),
}

fn main() {
    dbg!(size_of::<WithBox>());        // = 24
    dbg!(size_of::<WithUnitPtr>());    // = 24
    dbg!(size_of::<ManuallyNiched>()); // = 16
}

struct ManuallyNiched {
    a: usize,
    b: usize,
}

impl From<WithBox> for ManuallyNiched {
    fn from(this: WithBox) -> ManuallyNiched {
        match this {
            WithBox::Sized(this) => ManuallyNiched {
                a: 0,
                b: Box::into_raw(this) as usize,
            },
            WithBox::Unsized(this) => ManuallyNiched {
                b: this.len(),
                a: Box::into_raw(this) as *mut Sized as usize,
            },
        }
    }
}

impl From<ManuallyNiched> for WithBox {
    fn from(this: ManuallyNiched) -> WithBox {
        unsafe {
            match this.a {
                0 => WithBox::Sized(Box::from_raw(this.b as *mut _)),
                _ => WithBox::Unsized(Box::from_raw(slice::from_raw_parts_mut(
                    this.a as *mut _,
                    this.b,
                ))),
            }
        }
    }
}

Specifically, the tagged union of ptr::NonNull<{Sized type}> and ptr::NonNull<{!Sized type}> can niche together to be the size of ptr::NonNull<{!Sized type}> (for unsized types with non-zero sized metadata) by storing the discriminant for the sized pointer in the 0 niche of the non-null pointer to the unsized type (and the pointer to the sized type in the pointer metadata of the unsized type).

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-codegenArea: Code generationA-layoutArea: Memory layout of typesC-enhancementCategory: An issue proposing an enhancement or a PR with one.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