-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Type alias enum variants #2338
Type alias enum variants #2338
Conversation
I have run into this in my projects several times. Fortunately, I have access to the original type definition, so I could add a "constructor" from variant to work around this. The absence of this functionality came as a surprise to me, although it is not a bug in a sense. Implementing this would reduce the frustration people experience when initially they implicitly thought it would work, but later found out it would not. Another question is how close this relates to using alias to construct unit and tuple. From a usage point of view, they are the same surprising unsupported functionality of alias. Do they differ a lot inside the compiler? Should we discuss both or it requires another RFC? At last, how much inconsistency would an implementation bring to the compiler if we must introduce them? |
@WiSaGaN thanks for the feedback. I don't know much about the compiler internals, but I would guess the aliasing of unit and tuple types would not be very tied up in the enum variant handling, so I think it would make more sense to handle that in a different RFC. It would make sense to me, though, for much of the same reasons that I wrote up in this RFC. |
Tracking issue for this feature - rust-lang/rust#26264. |
The previous (very much reasonable) decision in rust-lang/rust#26264 was to resolve variants exactly like inherent associated items - variants themselves as associated types and their constructors as associated values.
For variants that would mean
|
I agree with @petrochenkov that
In the end, I think the change to move arguments from the variant to the type warrants its own discussion, since it a lot of code already out there, whereas this RFC restricts itself to slightly extending the allowed syntax to make aliases more useful. To maintain consistency (which I think are important to the ergonomics of aliases in general) the same rules should IMO apply to aliased and non-aliased enums. |
cc #2218 ("Generics: Make enum variant syntax consistent with other types") |
This would help Stylo a lot, which has a ton of type aliases to enums, and we need to import both the type alias and the enum it is based on if we want to build values of that type. |
Nominated for discussion in a lang team meeting. |
Removing I-nominated. I recall that we were generally in support of this feature, I think @nikomatsakis or @cramertj had more comments. |
The meeting agenda/notes mentioned this:
|
We discussed this RFC in the lang team meeting, and would like to move it into formal review. It has addressed the open questions that prevented us from previously accepting a PR on this topic. @rfcbot fcp merge |
Team member @aturon has proposed to merge this. The next step is review by the rest of the tagged teams: No concerns currently listed. Once a majority of reviewers approve (and none object), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
@rfcbot concern #2338 (comment) |
@nikomatsakis since a majority of the reviewers has approved now, can this enter FCP? |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
if this rfc, were to be added to the compiler the following piece of code should compile correct? enum Bar<T> {
Test(i32),
Data(T),
}
type Foo<T> = Bar<T>;
fn main() {
let _may = Foo::Test::<i32>(1);
} I do think it is weird were we put the type annotation. i feel like it should be closer to the type like Vec::<i32>::new() It seems inconsistent to me. I am safe in assuming that there will be no more additional enum type annotation syntax? |
@warlord500 as explained quite clearly in the reference-level explanation, |
I am gonna apologize here! some of this comment, may come off as arrogant! also for possible any additional confusion this might add. Writing is not my strongest skill. I am gonna start off with, just because you find something clear doesn't In fact the very reason, I asked my question was to make sure I completely understood the RFC. As, I understand the RFC as now, this doesn't change grammar but does expand the possible interpretations of foo::Test::(1); access foo which can be module or enum or struct, if my understanding of rust the language is wrong please correct me. It is never a bad time to learn. If the first question's answer is no, then this RFC needs to be made clear in its entirety. thank you, for reading my extremely long rant! |
This RFC is indeed not intended to change the syntax. It just extends the semantics of the language so that referring to variants into aliased enums is now legal. I hope that clarifies things for you. |
thank you for short and sweet answer to my questions. @djc |
The final comment period is now complete. |
Huzzah! This RFC has been merged! Tracking issue: rust-lang/rust#49683 |
type Alias<T> = Option<T>; | ||
|
||
mod foo { | ||
pub use Alias::Some; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm inclined to think this shouldn't be allowed, or at least it shouldn't be part of the initial implementation. After all, even
pub use Option::Some;
does not work right now, although
pub use ::std::option::Option::Some;
does, however.
For me, the semantics are unclear, and I'd be inclined not to accept it by default.
Anyway, would appreciate the thoughts of @rust-lang/lang on this matter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this can't work right now.
Option::Some
is module-relative (enums and traits are kind of modules from name resolution's point of view), so they can be used in imports.
Alias::Some
is type-relative, and we need type checking to determine what Alias
actually refers to, so it cannot be used in imports due to phase separation.
Implement RFC 2338, "Type alias enum variants" This PR implements [RFC 2338](rust-lang/rfcs#2338), allowing one to write code like the following. ```rust #![feature(type_alias_enum_variants)] enum Foo { Bar(i32), Baz { i: i32 }, } type Alias = Foo; fn main() { let t = Alias::Bar(0); let t = Alias::Baz { i: 0 }; match t { Alias::Bar(_i) => {} Alias::Baz { i: _i } => {} } } ``` Since `Self` can be considered a type alias in this context, it also enables using `Self::Variant` as both a constructor and pattern. Fixes issues #56199 and #56611. N.B., after discussing the syntax for type arguments on enum variants with @petrochenkov and @eddyb (there are also a few comments on the [tracking issue](#49683)), the consensus seems to be treat the syntax as follows, which ought to be backwards-compatible. ```rust Option::<u8>::None; // OK Option::None::<u8>; // OK, but lint in near future (hard error next edition?) Alias::<u8>::None; // OK Alias::None::<u8>; // Error ``` I do not know if this will need an FCP, but let's start one if so. r? @petrochenkov
Implement RFC 2338, "Type alias enum variants" This PR implements [RFC 2338](rust-lang/rfcs#2338), allowing one to write code like the following. ```rust #![feature(type_alias_enum_variants)] enum Foo { Bar(i32), Baz { i: i32 }, } type Alias = Foo; fn main() { let t = Alias::Bar(0); let t = Alias::Baz { i: 0 }; match t { Alias::Bar(_i) => {} Alias::Baz { i: _i } => {} } } ``` Since `Self` can be considered a type alias in this context, it also enables using `Self::Variant` as both a constructor and pattern. Fixes issues #56199 and #56611. N.B., after discussing the syntax for type arguments on enum variants with @petrochenkov and @eddyb (there are also a few comments on the [tracking issue](#49683)), the consensus seems to be treat the syntax as follows, which ought to be backwards-compatible. ```rust Option::<u8>::None; // OK Option::None::<u8>; // OK, but lint in near future (hard error next edition?) Alias::<u8>::None; // OK Alias::None::<u8>; // Error ``` I do not know if this will need an FCP, but let's start one if so.
This RFC proposes to allow access to enum variants through type aliases. This enables better abstraction/information hiding by encapsulating enums in aliases without having to create another enum type and requiring the conversion from and into the "alias" enum.