-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Determine how to handle casting of arbitrary discriminants with different enum styles #88621
Comments
@rust-lang/lang Nominating to verify what we should do. It was observed that the following has been allowed forever: // Works with or without repr.
enum Fieldless {
Foo(),
Bar{},
Baz,
}
fn main() {
assert_eq!(Fieldless::Foo() as u8, 0);
assert_eq!(Fieldless::Bar{} as u8, 1);
assert_eq!(Fieldless::Baz as u8, 2);
} Given that this has always been allowed, I'm thinking it would be awkward to reject the same code if it has an explicit discriminant. I'm not even certain it is possible to do that (at least not easily). I don't see a way to check whether or not a variant has a discriminant expression where the castability is checked here. So, I think some options are:
I don't know which would be the best option (or if there are other options?). I guess I slightly lean towards 1 or maybe 3. |
I think we should take option 3 for now and add a future-compat lint to prevent |
I believe adding something like this to Personally, I lean strongly towards " |
I don't think that would handle relative variants like: #[repr(u8)]
enum E {
V1 = 1,
V2(),
V3{}
}
let x = E::V2() as u8; |
d.variants.iter().any(|v| matches!(v.discr, VariantDiscr::Explicit(_)) && v.ctor_kind != CtorKind::Const) should do the job. We can add this to |
PR for option 2: #89234 |
Discussed today during T-lang meeting -- people in the meeting (not quorum, FWIW) were surprised that new |
(Marking as a regression for tracking the revert) |
…wesleywiser Revert enum discriminants Reverts stabilization of arbitrary enum discriminants per rust-lang#88621 (comment). Reopens rust-lang#60553.
Disallow non-c-like but "fieldless" ADTs from being casted to integer if they use arbitrary enum discriminant Code like ```rust #[repr(u8)] enum Enum { Foo /* = 0 */, Bar(), Baz{} } let x = Enum::Bar() as u8; ``` seems to be unintentionally allowed so we couldn't disallow them now ~~, but we could disallow them if arbitrary enum discriminant is used before 1.56 hits stable~~ (stabilization was reverted). Related: rust-lang#88621 `@rustbot` label +T-lang
Disallow non-c-like but "fieldless" ADTs from being casted to integer if they use arbitrary enum discriminant Code like ```rust #[repr(u8)] enum Enum { Foo /* = 0 */, Bar(), Baz{} } let x = Enum::Bar() as u8; ``` seems to be unintentionally allowed so we couldn't disallow them now ~~, but we could disallow them if arbitrary enum discriminant is used before 1.56 hits stable~~ (stabilization was reverted). Related: rust-lang#88621 ``@rustbot`` label +T-lang
Disallow non-c-like but "fieldless" ADTs from being casted to integer if they use arbitrary enum discriminant Code like ```rust #[repr(u8)] enum Enum { Foo /* = 0 */, Bar(), Baz{} } let x = Enum::Bar() as u8; ``` seems to be unintentionally allowed so we couldn't disallow them now ~~, but we could disallow them if arbitrary enum discriminant is used before 1.56 hits stable~~ (stabilization was reverted). Related: rust-lang#88621 `@rustbot` label +T-lang
Closing as this is essentially resolved due to the stabilization in 1.66. See #60553 (comment) for some final thoughts. |
Well, this is "resolved" in a sense that we have unblocked |
This is an issue to track making a decision on how to handle certain styles of enums with respect to the new
arbitrary_enum_discriminant
which has been stabilized in 1.56 (#86860) which will be released October 21st 2021. I think it would be good to make a decision before it reaches stable.I have a concern that this introduces three styles of enums, and I think it would be best to only have two styles. In summary, as of 1.56, they will be:
Kind 1: Unit-only variants:
Kind 2: Tuple or struct variants without fields:
Kind 3: Tuple or struct variants with fields:
The question mainly centers on how
Kind2
should be treated. #88203 is a proposal to make it treated the same asKind1
(that is, does not requirerepr
). Another proposal is to make it treated the same asKind3
(does not allow casting), PR up at #89234. Another option it to leave it as-is, and keep three styles.Only
Kind1
is allowed in 1.55 and older versions.(As an aside, this also highlights that our current terminology of "Fieldless enums" is confusing, since it has historically meant only
Kind1
style, but it can be confused withKind2
since those do not have fields, either.)More discussion at https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/arbitrary.20enum.20discriminants/near/251899236
The text was updated successfully, but these errors were encountered: