Skip to content

Missing niche optimization in non-trivial enum #148566

@dragostis

Description

@dragostis

In the following example:

use std::{mem, num::NonZero};

struct Foo {
    a: NonZero<u32>,
    b: u32,
}

enum Bar {
    Foo([Foo; 2]),
    Bar {
        a: u32,
        b: *mut Foo,
    }
}

fn main() {
    println!("{}", mem::size_of::<Bar>()); // 24
}

Bar is 24 bytes when it could be optimized to 16 by aliasing Bar::Foo first element's a field with the 32-bit padding from Bar::Bar by offsetting a to 4 instead of 0. Thus, the 0 bit pattern of a/padding would be the discriminant for Bar::Bar and any other pattern would be the discriminant for Bar::Foo.

Maybe this optimization is not possible because a discriminant needs to be unique?

EDIT: a better way to triage this

use std::{mem, num::NonZero};

struct Foo {
    a: NonZero<u32>,
    b: u32,
}

enum BarSmall {
    Foo([Foo; 2]),
    Bar((u32, [u8; 8])),
}

enum BarBig {
    Foo([Foo; 2]),
    Bar((u32, u64)),
}

fn main() {
    println!("{}", mem::size_of::<BarSmall>()); // 16
    println!("{}", mem::size_of::<BarBig>()); // 24
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-enumArea: Enums (discriminated unions, or more generally ADTs (algebraic data types))C-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing suchneeds-triageThis issue may need triage. Remove it if it has been sufficiently triaged.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions