Skip to content

Enums don't utilize niches across multiple data-carrying variants #121333

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
LunarLambda opened this issue Feb 20, 2024 · 0 comments
Open

Enums don't utilize niches across multiple data-carrying variants #121333

LunarLambda opened this issue Feb 20, 2024 · 0 comments
Labels
A-layout Area: Memory layout of types C-bug Category: This is a bug. C-optimization Category: An issue highlighting optimization opportunities or PRs implementing such S-has-mcve Status: A Minimal Complete and Verifiable Example has been found for this issue T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@LunarLambda
Copy link

Tested on latest stable and nightly.

I wanted to build an enum X such that

enum X {
    Inline(MyType /* size: 24, align: 8 */),
    Heap(Vec<MyType>),
}

is 24 bytes large.

I tried various things to exploit Vec's niches (0/null on ptr, > isize::MAX on capacity), including using explicit-zero padding.
Unfortunately for this very specific case it seems Vec lacks alignment niches on its pointer field to make this work, and/or I can't make a niche that's big enough for the compiler to prove the two variants are fully "disjoint" in their valid bit patterns.

However, even testing with much simpler types with much simpler niches I could not get the compiler to produce an optimal enum layout:

#[repr(u64)]
enum AlwaysZero {
    VALUE = 0
}

enum X {
    A(AlwaysZero),
    B(std::num::NonZeroU64)
}

X is 16 bytes here, even though AlwaysZero and NonZeroU64's niches are exact opposites of each other, so the entire enum should just be 8 bytes. It would be nice if rustc could support at least simple two-variant cases like this. I can see it coming in handy for things like Result and possibly Cow.

@LunarLambda LunarLambda added the C-bug Category: This is a bug. label Feb 20, 2024
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Feb 20, 2024
@jieyouxu jieyouxu added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. C-optimization Category: An issue highlighting optimization opportunities or PRs implementing such S-has-mcve Status: A Minimal Complete and Verifiable Example has been found for this issue and removed needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Feb 20, 2024
@the8472 the8472 added the A-layout Area: Memory layout of types label May 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-layout Area: Memory layout of types C-bug Category: This is a bug. C-optimization Category: An issue highlighting optimization opportunities or PRs implementing such S-has-mcve Status: A Minimal Complete and Verifiable Example has been found for this issue T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants