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
Bitwise enum initializer: compile-time constant but not allowed as a type reference? #22709
I'm trying to have "flags" as a type on interfaces, so that bitwise operators can be used to distinguish between various types and adjust intellisense accordingly. This works perfectly for enums and const enums where all values are literals.
The compiler won't allow it for constant values that are not literals (e.g. bitwise expressions).
It seems like an unnecessary restriction since constant expressions can easily be converted to literals anyway (even intellisense shows them as literals when you mouse over) and they can also be used in const enum.
But no clarification/justification on why. See a small example below:
Code
enumEnumA{One=1}// No compiler error (as expected)interfaceInterfaceA{Enum: EnumA.One;// Mouseover gives: (enum member) EnumA.One = 1}enumEnumB{One=1<<0}// Compiler error: "Enum type 'EnumB' has members with initializers that are not literals."// why are non-literals constants not allowed?interfaceInterfaceB{Enum: EnumB.One;// Mouseover gives: (enum member) EnumB.One = 1}// Compiler error (as expected): In 'const' enum declarations member initializer most be constant expressionconstone=1;constenumEnumC{One=1<<0+one}// No compiler error (as expected)constenumEnumD{One=1<<0}
Expected behavior:
I would expect compile-time constants and literals to have the same kinds of restrictions because they evaluate to the same thing.
So either:
Intellisense should not show the computed value of a bitwise expression AND bitwise initializers should not be allowed in const enum, or:
Bitwise initializers in enums should be usable as a type reference
Actual behavior:
Intellisense shows the computed value of a bitwise expression and bitwise initializers are allowed in const enum, but they cannot be used as a type reference.
My understanding is we don't have member types for any types of binary operations. From ze handbook
Union enums and enum member types
There is a special subset of constant enum members that aren't calculated: literal enum members.
A literal enum member is a constant enum member with no initialized value, or with values that are initialized to
any string literal (e.g. "foo", "bar, "baz")
any numeric literal (e.g. 1, 100)
a unary minus applied to any numeric literal (e.g. -1, -100)
When all members in an enum have literal enum values, some special semantics come to play.
The first is that enum members also become types as well!
It's not clear to me right now why we have this specific subset in mind; maybe there was a reason, but I can't recall what might stop us from just making an enum member type for every enum member whose containing enum solely holds computed values.
I tried to track down the commit, it seems to be this one: f7753af
Although I don't see the actual changes in that commit, but searching for Enum_type_0_has_members_with_initializers_that_are_not_literals shows it's present here but not here and the aforementioned commit is the one between them. You tell me.. :)
Activity
RyanCavanaugh commentedon Mar 20, 2018
Seems like it should be allowed. Daniel Rosenwasser (@DanielRosenwasser) ?
DanielRosenwasser commentedon Mar 20, 2018
My understanding is we don't have member types for any types of binary operations. From ze handbook
It's not clear to me right now why we have this specific subset in mind; maybe there was a reason, but I can't recall what might stop us from just making an enum member type for every enum member whose containing enum solely holds computed values.
fkleuver commentedon Mar 20, 2018
I tried to track down the commit, it seems to be this one: f7753af
Although I don't see the actual changes in that commit, but searching for
Enum_type_0_has_members_with_initializers_that_are_not_literalsshows it's present here but not here and the aforementioned commit is the one between them. You tell me.. :)RyanCavanaugh commentedon Aug 7, 2018
See comments in #26241