Skip to content

Latest commit

 

History

History
80 lines (61 loc) · 5.28 KB

LDM-2023-03-08.md

File metadata and controls

80 lines (61 loc) · 5.28 KB

C# Language Design Meeting for March 8th, 2023

Agenda

Quote(s) of the Day

  • "It sounds like we're not unified on unions"
  • "Anyone feel like we found the weeds?"
  • "I shouldn't have used my pizza example"

Discussion

Discriminated Unions

#7010
#7016

Last time, we looked at the summary of the discriminated union working group's investigations. There's a lot there; we also had an additional proposal from a language design member emeritus, who lead the previous investigation into DUs, on a form of efficient tagged unions. One thing that is apparent is that, even with the working group's summary, there is a massive design space here. Another point that becomes obvious quickly is that generics throw many wrenches into any design: you either have a problem where things like List<(A | B)> cannot be freely converted to List<(A | B | C)>, or there are inefficiencies in representing value types that likely preclude union usage in a number of places. Looking to the major .NET language with union types, F#, they implement tagged unions (though they are considering anonymous type unions).

We talked some about how tagged unions implemented via structs is effectively struct inheritance: indeed, it's hard to conceive of a struct inheritance implementation that would not effectively turn into a tagged discriminated union. There are some interesting parts to this implementation strategy though: would a union with simple inline values be able to be more efficiently represented than a union with a nested struct value? For example:

union { MyFourInts(int, int, int, int), MyThreeInts(int, int, int) }
union { MyFourInts(StructOfFourInts), MyThreeInts(StructOfThreeInts) }

If those have different layouts that make the former more compact than the latter, that could be unfortunate, particularly if the layout was guaranteed in such a way that we couldn't improve it in the future.

We also thought a bit about how tags will interact with pattern matching. The natural syntax we would want to use likely conflicts with type patterns: can we make that work? And, in particular, will there be a way to declare a variable that encapsulates all the state of a particular tag? The tags aren't types, but maybe we can paper over that for the purposes of pattern matching, using tuples to contain all the state for a particular tag?

We ultimately think there is room for multiple types of unions in C#: a tagged, struct-based variant, and a reference type variant. However, we aren't ready to make more progress yet; we'll work on determining the next steps for the working group.

Limited Breaking Changes in C#

#7033

Continuing in today's LDM theme of light, easy, non-controversial topics, we took a look at a proposal for making limited breaking changes in C#. We posted this to csharplang a few days ago, and the response so far has been mostly positive; plenty of suggestions of how we might tweak it to add more granularity, suggestions to go further (a la Rust editions), and questions on the cadence. There have only been a few negative reactions to the idea, however, which is an encouraging sign overall. GitHub can't be our only source of sentiment on this, though, as it's a self-selecting group; more user research will be needed via other avenues.

We brought up that this might change the way the C# compiler approaches certain problems. Today, the compiler tries very hard to not change its semantic behavior while binding. When we see a user taking advantage of a language feature in a newer language version than what they are targeting, we simply produce an error and continue binding. This would change the compiler to introduce new warnings in lower language versions, and cause the compiler to potentially bind in different fashions for higher and lower versions. We need to be cognizant of that, and have an idea of how the compiler change would work before committing to a design that we can't implement.

We also thought about the documentation issue. Today, our documentation is updated for new language versions, so if we make breaking changes, users on older versions might slowly get left behind our documentation. Inversely, there are many non-Microsoft sources of documentation (StackOverflow, blogs, tutorial videos, etc.) that never get updated for new content; users trying to copy and paste or learn from these sources might be hurt. This has already happened with top-level statements; our tools and docs updated, but many popular 3rd-party intros and tutorials have not. The changes we're discussing here might not be as much of a concern, however; the cases we've discussed so far are exceptionally narrow cases of changing how an identifier is interpreted.

A read of the room indicates that we should continue to pursue this topic, so the working group will continue to flesh out the proposal, gather feedback from user groups, and flesh out the proposal details for future review.