-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Create enum-like-unions.md #9711
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
Open
MadsTorgersen
wants to merge
2
commits into
main
Choose a base branch
from
madst-unions
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+167
−0
Open
Changes from 1 commit
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
98 changes: 98 additions & 0 deletions
98
meetings/working-groups/discriminated-unions/enum-like-unions.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
# Enum-like unions | ||
|
||
## Summary | ||
|
||
**Enum-like unions** are "enum-like" in the same sense that field-like events are "field-like": They are introduced by the same keyword, and to the consumer they are the same kind of thing (unions/events), but their body uses an alternative, terser, syntax that is similar to another kind of declaration (enums/fields): | ||
|
||
```csharp | ||
public union Gate { Locked, Closed, Open(float percent) } | ||
``` | ||
|
||
## Motivation | ||
|
||
For straightforward "discriminated union" scenarios, it is desirable to have a very terse syntax for declaring fresh case types, and it is helpful to lean into enum syntax (curly braces, simple names, commas) to manifest the analogy. Both these claims are borne out by other programming languages. | ||
|
||
However, to a consumer such unions aren't observably different from ones declared with type references, just like field-like events aren't observably different from other events. Sharing the `union` keyword makes the shared semantics clear. | ||
|
||
Also, this proposal leaves open a path to unify "struct-like" and "enum-like" declarations in the future. | ||
|
||
## Detailed design | ||
|
||
```antlr | ||
union_declaration | ||
: attributes? struct_modifier* 'partial'? 'union' identifier type_parameter_list? union_declarator | ||
; | ||
|
||
union_declarator | ||
: struct_like_union_declarator | ||
| enum_like_union_declarator | ||
; | ||
|
||
struct_like_union_declarator | ||
: '(' type (',' type)* ')' type_parameter_constraints_clause* | ||
(`{` struct_member_declaration* `}` | ';') | ||
; | ||
|
||
enum_like_union_declarator | ||
: type_parameter_constraints_clause* `{` enum_like_union_member_list `}` | ||
; | ||
|
||
enum_like_union_member_list | ||
: enum_like_union_member (',' enum_like_union_member)* (`,`)? | ||
; | ||
|
||
enum_like_union_member | ||
: identifier (`(` parameter_list? `)`)? | ||
; | ||
``` | ||
|
||
Note that the `struct_like_union_declarator` shown here just reflects the current plan of record, but could change as part of other decisions. It's exact shape is not part of this proposal. | ||
MadsTorgersen marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
### Semantics | ||
|
||
Enum-like unions are translated into struct-like unions, where enum-like union members are translated into nested record declarations (with primary constructor parameter lists if they contain parameter lists `(...)`) and added to the resulting unions case type list. | ||
|
||
### Examples | ||
|
||
```csharp | ||
public union Gate { Locked, Closed, Open(float percent) } | ||
|
||
union Pet | ||
{ | ||
Cat(string Name, string Personality), | ||
Dog(string Name, bool Friendly), | ||
Bird(string Name, string Species), | ||
None | ||
} | ||
|
||
public union Option<T> | ||
{ | ||
None, | ||
Some(T value), | ||
} | ||
``` | ||
|
||
MadsTorgersen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
## Drawbacks | ||
|
||
- Is it too subtle that the presence or absence of a list of case type references determines whether the `{...}` body is enum-like or struct-like? | ||
MadsTorgersen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
- Does the `enum` keyword need to be present to stress the analogy to enums? | ||
|
||
- Like enums, enum-like unions cannot declare struct members such as function members or nested types. Their body is reserved for case members. | ||
|
||
- Types declared as enum-like union members cannot declare their own bodies. This represents quite a cliff, as doing so for even one member requires the whole union to be rewritten as a struct-like union. | ||
|
||
## Alternatives | ||
|
||
- Use other keywords or additional keywords to further differentiate an enum-like union declaration from a struct-like one. | ||
|
||
- Allow the `enum_like_union_member_list` to be followed by a `;` and a list of `struct_member_declaration`s so that enum-like unions also can have e.g. function members. | ||
- This could also be allowed in actual enum declarations, maintaining the analogy. | ||
|
||
- Fully unify struct-like and enum-like declarations by allowing both a list of case type references and a list of enum-like union members in the same union declaration. This would be a superset of the proposal, but would go against the current decision to keep the two kinds of union declarations separate. | ||
|
||
## Open questions | ||
|
||
None. | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.