-
Notifications
You must be signed in to change notification settings - Fork 59
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
Layout of single-variant enums #79
Comments
We could resolve this with: The layout of multi-variant enums with one inhabited variant is the same For example, here: struct SomeStruct { x: u32 }
enum SingleVariantDataCarrying {
DataCarryingVariant(SomeStruct),
}
enum Void0 {}
enum Void1 {}
enum MultiVariantSingleInhabited {
DataCarryingVariant(SomeStruct),
Uninhabited0(Void0),
Uninhabited1(Void1),
} the layout of but doing so is blocked on resolving the layout of uninhabited types: #165 . |
Addresses part of rust-lang#79 .
That's not what is currently (or is planned to be) implemented, again because uninhabited types aren't all ZSTs and can be partially constructed. The plan of record is to only omit variants which are uninhabited and ZSTs. |
@rkruppe Makes sense. I think this might be then covered with a guarantee about layout for unions with a single (inhabited?) non-zero-sized field. |
@rkruppe those issues apply to structs though, not to enums. Surface Rust does not allow partial initialization of enums. But maybe MIR does... in the spirit of rust-lang/rust#63616, I wonder what happens with something like let x: Result<u32, (u32, !)> = Err((42, panic!())); |
Yes, that will have partial initialization in MIR. "Surface Rust allows partial initialization" was always just part of the story (and is even ruled out again right now!), the MIR-level motivation, specifically enabling aggressive move forwarding/emplacement without having to special case siblings of uninhabited places (to introduce fake temporary destinations), applies universally to structs, enums, and every other aggregate. |
Seems there was some discussion in 2020 about univariant enums. What I cant find is if there was ever a discussion - or, better, a decision - on supporting |
@heaths It's unclear to me what you expect transparent on a multi-variant enum like |
I see your point. Perhaps this is overly optimizing for a specific use case - FFI - but since my (and others') intention was to define native functions returning non-zero errors, would constraints make it easier to discriminate e.g. |
@heaths That's a niche optimization question, so you're probably looking for a different issue -- it's definitely not a "single-variant enum", even if it might layout-optimize down to 32 bits. |
I ran across rust-lang/rust#84277 as well, which eventually - hopefully - is a way to solve this seemingly common FFI scenario. I agree it's a niche optimization, though. |
@heaths Yes, that exact FFI scenario is written out specifically in the RFC: https://rust-lang.github.io/rfcs/3058-try-trait-v2.html#implementing-try-for-a-non-generic-type |
@heaths By the way, from this exchange I think there might have been a miscommunication: @scottmcm means it's a (niche optimization) question, not a niche (optimization question). That is, it's a question about niche-optimization (that is, efficient bit-packing of enums where the variants disallow some range of values), not a question about optimizations which are "niche" i.e. applicable only to a restricted set of scenarios. |
Discussed at T-opsem backlog bonanza. This is T-lang, not opsem @rustbot label: +T-lang +S-not-opsem |
Enums that contain a single variant and which do not have an
explicit
#[repr]
annotation are an important special case. Sincethere is only a single variant, the enum must be instantiated with
that variant, which means that the enum is in fact equivalent to a
struct. The question then is to what extent we should guarantee
that the two share an equivalent layout, and also how to define the
interaction with uninhabited types.
As presently implemented, the compiler will use the same layout for
structs and for single variant enums (as long as they do not have a
#[repr]
annotation that overrides that choice). So, for example, thestruct
SomeStruct
and the enumSomeEnum
would have an equivalentlayout (playground)::
Similarly, the struct
SomeStruct
and the enumSomeVariant
in thisexample would also be equivalent in their layout
(playground):
In fact, the compiler will use this optimized layout even for enums
that define multiple variants, as long as all but one of the variants
is uninhabited
(playground):
The text was updated successfully, but these errors were encountered: