You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Tracking issue for RFC 2363, "Allow arbitrary enums to have explicit discriminants" #60553
Should discriminants of enumerations with fields be specified as variant attributes?
Should this apply only to enumerations with an explicit representation?
Reacted by Kelly Thomas Kline, Konstantin Gribov, Artyom Pavlov, Wanja Hentze, Jonas Schievink, Moggers, beef, mwberry, Robin Freyler, William and 23 more
Reacted by Esteban Kuber, Moggers, Sean Cross, beef, mwberry, William, Kyle Cooke, Troy Hinckley, Andrew Ares, terrarier2111 and 2 more
Mentoring-wise: I'd suggest trying out an example and then tracking down where the error comes from. I don't remember, it's either during parsing or in ast_validation.
Most of the compiler should already support this, where doing the uniform thing is easier.
The "niche" optimization might assume variants with any data have consecutive discriminants, but it should be easy to fix, and we can figure it out after an initial PR is open.
Sweet! Yes please open a PR with the feature gate and throw some tests in for good measure (there may already be tests checking for the "discriminator values can only be used with a field-less enum" error message, those should now be emitting a feature gate error instead)
The #![feature(arbitrary_enum_discriminant)] was implemented on 2019-06-26 in #60732 which was written by @jswrenn and reviewed by @pnkfelix and others.
Reacted by Rémy Rakic, Jack Wrenn and Esteban Kuber
Rust By Examplementions C-like enums, but does not go into their memory layout. Since this feature is only relevant to advance users who care about the memory layout of enums, Rust By Example is probably ill-suited for the topic.
Unresolved Questions
Should discriminants of enumerations with fields be specified as variant attributes?
Presently: no. Discriminants of all types of enumerations are specified with = followed by a constant expression. I implemented this approach because doing so was simplest, but I'd also argue this is the right approach since it means the syntax for specifying discriminants is consistent across variant types.
Should this apply only to enumerations with an explicit representation?
Presently: yes, this feature applies only to enumerations using a primitive representation. Since this feature is only relevant when you care about the precise memory layout of enums, this feature is only reasonable to use when the precise layout of an enum is well-specified.
There are a set of changes related to enums that we need to make, including discriminants, as casts, AsRepr, and similar. Lang has had a design meeting on that, and needs to have another once someone supplies a complete design that fits these pieces together.
Would anyone like to collaborate with me on this design? I'm very familiar with these issues, and have some design sketches on hand, but would love a collaborator help construct a cohesive vision of the future.
Reacted by Esteban Kuber, Troy Hinckley, Lachezar Lechev, Andrew Ares, Yukun Guo, SeniorMars, Xuan, Amaan Qureshi and MeatKO
I'm going to close as I believe this is now essentially complete as of 1.66.
There might be some longer-term decisions to make around as casting. There are some strange exceptions:
Fieldless enums with variants such as Tuple() or Struct{} allow as casting without a #[repr(…)], and have since 1.15.
// Allowed since 1.15, even without a #[repr]enumFieldless{Tuple(),Struct{},Unit,}assert_eq!(0,Fieldless::Tuple()asisize);assert_eq!(1,Fieldless::Struct{}asisize);assert_eq!(2,Fieldless::Unitasisize);
Similar to above, fieldless enums allow as casting as long as you don't specify an explicit discriminant. Using an explicit discriminant suddenly prevents all as casts.
Fieldless enums allow explicit discriminants on unit variants, but not struct or tuple (new 1.66). It's not clear to me why it was decided to allow this.
Activity
eddyb commentedon May 5, 2019
Mentoring-wise: I'd suggest trying out an example and then tracking down where the error comes from. I don't remember, it's either during parsing or in
ast_validation.Most of the compiler should already support this, where doing the uniform thing is easier.
The "niche" optimization might assume variants with any data have consecutive discriminants, but it should be easy to fix, and we can figure it out after an initial PR is open.
jswrenn commentedon May 9, 2019
Has anyone stepped up to implement this? If not, I'd like to take a stab.
The current error arises in parsing. I haven't fiddled with it yet, but I suspect a good first step is to remove the
elsebefore thisif:rust/src/libsyntax/parse/parser.rs
Lines 7781 to 7789 in 33cde4a
oli-obk commentedon May 9, 2019
I don't know of anyone
Go for it!
That looks like the right start, yes.
jswrenn commentedon May 9, 2019
I've started work on this here by removing the parsing restriction preventing non-unit variants from having explicit discriminants. As you predicted @eddyb, things seem to basically just work; e.g.:
As it stands, adding this feature required removing more lines of code than it involved writing new code! :D
Future work that comes to mind include writing tests and putting this behind a feature flag. Shall I go ahead and file an initial PR?
oli-obk commentedon May 10, 2019
Sweet! Yes please open a PR with the feature gate and throw some tests in for good measure (there may already be tests checking for the "discriminator values can only be used with a field-less enum" error message, those should now be emitting a feature gate error instead)
Auto merge of #60732 - jswrenn:arbitrary_enum_discriminant, r=pnkfelix
Centril commentedon Jun 25, 2019
The
#![feature(arbitrary_enum_discriminant)]was implemented on 2019-06-26 in #60732 which was written by @jswrenn and reviewed by @pnkfelix and others.jswrenn commentedon Jul 14, 2019
Documentation
I've submitted a PR to update the reference to reflect this feature (in its current state): rust-lang/reference#639.
I do not believe that either the Book or Rust By Example need updating:
Unresolved Questions
Presently: no. Discriminants of all types of enumerations are specified with
=followed by a constant expression. I implemented this approach because doing so was simplest, but I'd also argue this is the right approach since it means the syntax for specifying discriminants is consistent across variant types.Presently: yes, this feature applies only to enumerations using a primitive representation. Since this feature is only relevant when you care about the precise memory layout of enums, this feature is only reasonable to use when the precise layout of an enum is well-specified.
newpavlov commentedon Aug 18, 2019
What are layout guarantees for such enums? Ideally I would like to be able to write code likes this:
And I want for this type to have exactly the same memory layout as:
Meaning if
repr(C)is used:repr(C).Having such guarantees would allow in some cases some neat zero-cost translations of C types to safe Rust ones.
eddyb commentedon Aug 18, 2019
@newpavlov You get most of that (the placement and size of the discriminant) from just
#[repr(u8)], I'm not sure if#[repr(C)]adds more to that.Keep in mind that since your discriminants are the default ones (starting at
0and adding1for each variant), you don't need this feature!We defined all these back in rust-lang/rfcs#2195, for Servo <-> Firefox I believe.
35 remaining items
joshtriplett commentedon Jun 15, 2022
There are a set of changes related to enums that we need to make, including discriminants,
ascasts,AsRepr, and similar. Lang has had a design meeting on that, and needs to have another once someone supplies a complete design that fits these pieces together.jswrenn commentedon Jun 15, 2022
Would anyone like to collaborate with me on this design? I'm very familiar with these issues, and have some design sketches on hand, but would love a collaborator help construct a cohesive vision of the future.
Rollup merge of rust-lang#95710 - fee1-dead-contrib:stabilize_arbitra…
Rollup merge of rust-lang#95710 - fee1-dead-contrib:stabilize_arbitra…
Rollup merge of rust-lang#95710 - fee1-dead-contrib:stabilize_arbitra…
Rollup merge of rust-lang#95710 - fee1-dead-contrib:stabilize_arbitra…
Rollup merge of rust-lang#95710 - fee1-dead-contrib:stabilize_arbitra…
ehuss commentedon Jan 8, 2023
I'm going to close as I believe this is now essentially complete as of 1.66.
There might be some longer-term decisions to make around
ascasting. There are some strange exceptions:Tuple()orStruct{}allowascasting without a#[repr(…)], and have since 1.15.Similar to above, fieldless enums allow
ascasting as long as you don't specify an explicit discriminant. Using an explicit discriminant suddenly prevents allascasts.Fieldless enums allow explicit discriminants on unit variants, but not struct or tuple (new 1.66). It's not clear to me why it was decided to allow this.
I suspect further changes may require an RFC or some design decisions with the lang team.
Rollup merge of rust-lang#128795 - zachs18:e0517-update-for-rfc-2195,…
Rollup merge of rust-lang#128795 - zachs18:e0517-update-for-rfc-2195,…
Rollup merge of rust-lang#128795 - zachs18:e0517-update-for-rfc-2195,…
Rollup merge of rust-lang#128795 - zachs18:e0517-update-for-rfc-2195,…
Unrolled build for rust-lang#128795