# C# Language Design Meeting for September 24th, 2025

## Agenda

- [Union Syntax Thunderdome Part 1](#union-syntax-thunderdome-part-1)

## Quote(s) of the Day

- "You'll all choke on your own bile and say that can't possibly be the solution"
- "I got a head start on showing [redacted] that they're wrong. You know, I gotta get my hand up there and make sure I'm first in line."
- "Let's get a yummy rare steak in the ground"

## Discussion

### Union Syntax Thunderdome Part 1

Champion issue: https://github.com/dotnet/csharplang/issues/9662  
Specification: https://github.com/dotnet/csharplang/blob/38fd5f33d285cb190268f98cea16223cc0a5b8bc/proposals/unions.md  
Proposals:
* https://github.com/dotnet/csharplang/blob/38fd5f33d285cb190268f98cea16223cc0a5b8bc/meetings/working-groups/discriminated-unions/allows.md
* https://github.com/dotnet/csharplang/blob/38fd5f33d285cb190268f98cea16223cc0a5b8bc/meetings/working-groups/discriminated-unions/brace-syntax.md

Today we begin the syntax thunderdome for unions: while we don't expect to make every decision today (and spoiler alert, we did not), we need to make enough progress today and
in the next couple of meetings for the compiler team to start implementation without later needing to significantly redesign the parsing stages. We have a few different options
on the table, and we started to break them down by philosophies. Specifically, we have 2 main flavors of union here: a union that states that its cases are pre-existing
types, and a union that states that its cases are types that should be generated inline. One major question, therefore, is whether or not we expect these different flavors to
mix; do we expect users to often declare intermixed unions of both pre-existing types and new types, or do we expect it to be homogenous. And, if we often expect it to be
homogenous, do we really need a syntax that allows both flavors in a single union declaration? One key insight is that the union of newly created types is just sugar over the
union of pre-existing types; we can likely formalize the former as literally desugaring into the latter, with the new types declared as nested types within the union. This then
potentially allows us to nicely relate this back to `enum`s; we can say that `enum`s are for declaring _new_ cases (whether that's numeric cases or types cases), and `union` is
specifically for bundling a group of existing types. We could then potentially allow a grow-up story for `enum`s where they can add new types of members. Some difficult hurdles
remain in that area though:

* How does the language decide whether an `enum` is number-based or type-based? Is the difference just in whether any of the cases has nested values? Is that too subtle?
    * Other languages do use just this nested value presence in similar fashions, like Swift and Rust, but neither are quite like C# enums.
    * Could we perhaps use a modifier like `enum class` or `enum struct` to convey this difference?
* How would such enums interact with `System.Enum`? Would we change the runtime to allow them to inherit from `System.Enum`? Would that be too large of a breaking change?
    * If they don't interact with `System.Enum`, is that too large a divergence to continue using the `enum` keyword?

We do think that this idea has some merit and needs to be explored, and several LDM members plan to do just that ahead of Monday's meeting. We also took some initial reads of
the room on the basic building blocks of unions. So far, LDM leans towards unions not having a dedicated shorthand syntax for declaring new types; they are made up of existing
types. We are not ruling out the separate `enum` of types idea that would desugar into a `union` with nested declarations, but to use an analogy to `class`es and `record`s,
`union`s would be the more general building block on which a potential `enum` of types feature would build, just as `class`es are the building block on which `record`s build.

We also thought about whether the cases of `union`s should be inside or outside the curly braces of the body. Again, there are no easy options here. If they are outside the
curly braces, our precedent for scoping visibility suggests that any nested types from inside the `union` are not visible without being qualified by the type of the `union`,
including any generic type arguments. However, in order to implement closed type hierarchies, we may need to have a list of the allowed implementations, similar to Java's
`permits` clause, both for compiler performance and for reader comprehension. If we do need to have such a clause for that case, it might be a good idea to unify that with
`union`s. On the other hand, `union`s could also reuse the `enum` syntax; again, if we expect to allow other member types to be defined in an `enum`, we will need to solve
the syntax question of both listing the cases and other members in the body of the enum, and `union` could potentially reuse that same syntax. Subjectively, we do have a
slight leaning that by writing the members inside the body, rather than at the declaration level, it implies that they are _new_ things, rather than existing things. Given
that, we have a very slight lean towards outside the body of the `union`, but will explore more proposals on Monday and hopefully make further concrete progress on this very
gnarly question.
