-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Enum improvements #3103
Enum improvements #3103
Conversation
…number expression). fixes microsoft#2790 If an invalid enum constant expression is found, continue incrementing with the last valid initialized value. If an enum expression references another enum member, then emit a reference to the other value.
Hi @jbondc, I'm your friendly neighborhood Microsoft Pull Request Bot (You can call me MSBOT). Thanks for your contribution! The agreement was validated by Microsoft and real humans are currently evaluating your PR. TTYL, MSBOT; |
Hi @jbondc, thanks for the PR. While I'm not sure if @vladima was working on it at the time, in the future please be mindful of the assignee of an issue if there is one, and ask if it would be okay to pick the issue up. I have a few questions about your work though:
Is there any reason for this behavior change? I don't see the previous behavior as an actual issue, and I'd rather not introduce new behavior for the sake of what one might feel is slightly more correct. Both are just as broken.
For something like this, it would warrant formal proposal beforehand. |
I see what you mean now - can you write a test case like the following so that we can see the effect this PR would have? tests/cases/conformance/enumsMembersWithInitializersThatReferenceLaterMembers01.ts enum E1 {
a = c,
b = 2,
c = 3,
}
declare enum E2 {
a = c,
b = 2,
c = 3,
}
const enum E3 {
a = c,
b = 2,
c = 3,
}
declare const enum E4 {
a = c,
b = 2,
c = 3,
}
enum E5 {
a = c,
b,
c,
}
declare enum E6 {
a = c,
b,
c,
}
const enum E7 {
a = c,
b,
c,
}
declare const enum E8 {
a = c,
b,
c,
} |
Good catch, I'm thinking:
Would be the emit if a member references another member before it's emitted, does that seem right? Alternative is it's an error to reference an enum member before it's declared. |
Proposal #3105 though will likely make refinements in the upcoming weeks. |
@jbondc "Why no errors after...". Because inundating users with errors that all stem from an initial bad issue is not good compiler behavior. We try to avoid this sort of cascading when we can. |
Noted, wasn't my intent to work on enums. Stumbled on it as it overlaps with number literal types, at least how I'd plan to implement it. |
Unify error message for const & ambiant enum.
@@ -145,7 +145,7 @@ var E8; | |||
var E9; | |||
(function (E9) { | |||
E9[E9["A"] = 0] = "A"; | |||
E9[E9["B"] = 0] = "B"; | |||
E9["B"] = E9.A; |
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.
👎 this breaks existing reverse mapping behavior.
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.
E9[E9.A] // "A"
E9[E9.B] // "A"
That's what I would expect, this pattern works well with string enums #3192
Don't think the current behavior is more correct where the last declared member overrides the mapping:
E9[E9.A] // "B"
E9[E9.B] // "B"
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.
If there's a BC concern I guess I could emit:
E9[E9["A"] = 0] = "A";
E9["B"] = E9.A;
E9[0] = "B";
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.
That's what I would expect, this pattern works well with string enums
But string enums weren't officially approved at all.
Don't think the current behavior is more correct where the last declared member overrides the mapping
Perhaps for most cases, but this is still a breaking change; the compiler did not give an error in these scenarios.
Can you explain why this change was originally necessary?
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.
It's a simpler model to work with (that the original declaration doesn't change).
// lib.ts
enum foo {
a = 1
b = 2
}
// thirdparty.ts
enum foo {
c = 1
}
Why is 'thirdparty.ts' allowed to modify the reverse mapping?
About string enums, I've implemented it here:
master...jbondc:setTypes-v2
There's some wonkyness still but overall think it will scale well with literals/set type guards.
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.
Oops missing file here:
jbondc@5991931
Need to cleanup & pass tests but maybe will clarify what I'm trying to do and how it relates to enums.
@DanielRosenwasser To follow up on the reverse mapping issue, here's a recent issue/use case within the compiler:
When debugging, I would normally see:
But if you uncomment 'ConstantBinding', I now get:
That's clearly not my intent and quite annoying behavior. |
Or just this one:
What I really expect is
|
Started to look at implementing #1003 and struggled understanding enums.
This patch addresses the following issues:
Note that I'm still confused about what 'constant' means for an enum #538
Thinking that enum should allow for NumericLiteral, it's an
enum<number>
.You could have a more restricted/subset enum:
Or if you don't want signed: