meetings/2022/LDM-2022-01-03.md
https://github.com/dotnet/csharplang/issues/5599
We took another look at this corner case of list patterns, with an eye for trying to settle on a consistent and logical representation that will be both unsurprising to the user, and set the language up for success in the future if we ever want to build on list patterns in other ways. We generally agree that this is an extreme corner case: the overwhelming majority of slice patterns should be variable assignments, and those that aren't are almost certainly not going to be another a list of pattern with a finite number of elements in it. However, we think it's important to codify the language's expectations of how a well-behaved slice method should work, and that future pattern work could possibly suffer if we don't make those assumptions now.
Formally, our expectation is: a Slice method should never return null. It should return an empty slice, or throw if indexes are out
of range, but never return null. In order to resolve the pattern handling of this, we have 4 options:
Slice method violates the above expectation, the code might throw a null reference exception,
depending on how the slice is used... null pattern would never match, as the custom exception would be thrown when a null return from Slice was encountered. The only
workaround would be to fall out of pattern matching entirely.After some discussion, we were split between 2 and 4. We feel that 1, while an ok solution for this niche case, could potentially have
bad consequences long term for patterns if we want to evolve anything about slice patterns in the future. 3 is ok, but we're concerned
about the worse codegen for the 99% case here. Patterns can and do assume certain behaviors for the things they operate on: properties
might be called multiple times, or they might not be, and should return the same result across evaluations, for example. This is just
another similar expectation, this time on the Slice method. After further discussion, we think that the inability to workaround the
checks in 4 are enough of a concern to tilt the balance between the two.
We will adjust our expectations around slice patterns to assume that Slice will never return a null value, and we will not insert a
null test into the reachability or codegen DAGs.
https://github.com/dotnet/csharplang/issues/5552
There has been some feedback on parameterless constructors in C# 10 that we want to address now, while C# 10 is still new. Specifically,
when a parameterless struct constructor is synthesized has raised concerns about silent breaks for new StructType() when a user or
library updates their code.
In general, it's a bit unfortunate that C# allows new StructType() syntax. default(T) wasn't in C# 1 (it was introduced with C# 2's
generics), so that was the original way to get a default instance of a value type. We think there may be an opportunity to start correcting
this with a .NET 7 warning wave, but that will need more design, particularly around object initializers on struct types. In the meantime,
we have 3 options for addressing the concerns with the initial release of C# 10:
new RecordStructType() anyway).Console.WriteLine(new S().field1); // This prints 0
struct S
{
int field1 = 1; // No constructor is synthesized
int field2;
public S(int field2) => this.field2 = field2;
}
This will get easier in the future with primary constructors, making it simple to just append () on the end of the struct name to add
this constructor definition, but it will be unfortunate for now. Of the downsides in all of these options, this is the one we best
understand, and more importantly while it is the least ergonomic, it does fully solve the issue around accidentally removing the
parameterless constructor (which changes the behavior of source and is a binary break).
We will go with option 3, never synthesizing a parameterless constructor. If a struct has field initializers with no constructors, this is an error. It is a break over C# 10 as initially released, but the fix is both simple and backwards-compatible with the initial version of C# 10, so we think we're still within our ability to make this change.