- "Obviously what the data means is that after we make
field
a keyword, usage of it as the name of a field will skyrocket, because that's what correlation means, right?"
Champion issue: #140
Specification: https://github.com/dotnet/csharplang/blob/e44ebf7095e462ef5f9bbd869386a70cbd85e6d0/proposals/field-keyword.md#syntax-locations-for-keywords
Usage data
We started today by looking at real world usage data for field
and value
as keywords, to allow us to evaluate how breaking of a change we are looking at. Our current strategy, making both field
and value
keywords within property accessors, even when used as a nested expression, turns out to be extremely breaking. Internal repos show hundreds of errors, with more waiting further in the build process; the errors stopped
the build in root projects, which would have to be fixed up to then allow the build to progress further. Surprisingly (to the LDM, at least), value
is actually more breaking than field
is, and by a pretty big
order of magnitude: our analyses find that, across various sources, value
is used in a way that would break with this proposal 8-12 times more than field
is. We're pretty concerned by the level of break here, even
with fixers, for a couple of reasons:
- A decent amount of the break was in generated (either through a separate tool or through a Roslyn source generator) code. Even with a fixer, that generated code would likely just be overwritten the next time the generator runs.
- Our original supposition that, because
value
already has special meaning in property bodies it would be fairly simple to unify withfield
, turns out to be completely false.
Given these issues, we have a few proposals on how to deal with this, scaling back the break to have less of an impact:
- Accept the break, exactly as shown.
- Scale back the keyword recognition to only consider primary_expressions. For
value
, this fixes a lot of the errors; in Roslyn at least, it only results in a single build error, wherevalue
was used in a lambda inside the getter body. - 2, but separate out
value
entirely, and leave it alone. Just make the breaking change forfield
, and only in the primary_expression scenario.
To tackle this question, we started by looking at the two separate parts: should we scope the break down, and should we remove any breaks on value
? Our first pass here was maximally breaking, as we wanted to see how
bad the reality actually would be. It turns out to be unacceptably breaking, so we are in strong agreement to scope down the break to just primary_expressions. Next, we took a second look at value
. While scoping
down the break would eliminate a very large percentage of the real-world breaks that we see here, it wouldn't eliminate them; Roslyn itself would break, just as the very first example. Our breaking change philosophy
was that any breaking changes need to be well-motivated, and looking at the actual data in comparison to our original suppositions, we now think that we don't have enough motivation to take a change to value
. Even
though changing value
would make it more consistent with field
, we don't think we have enough justification to make it worth it. Therefore, we go with option 3.
field
will only be recognized as a keyword when used as a primary_expression within an accessor body. Any changes to value
will be removed from this proposal and its behavior will continue unaffected.
Champion issue: #7905
Specification: https://github.com/dotnet/csharplang/blob/4578db732a7d4aece52a07d1c822846b381f40b2/proposals/first-class-span-types.md#delegate-extension-receiver-break
Finally today, we took a look at a potential breaking change that could be caused first-class spans, and the proposed mitigation for it. This is a somewhat complicated case: the main issue is that because method group
resolution of an extension method called in extension form can actually apply a conversion to the receiver, that conversion could potentially be something that can't be boxed. This isn't really a problem today, because
the only conversions allowed here are identity, reference, or boxing conversions; these are all things that are already on the heap, so capturing the receiver into the method closure is perfectly fine. Span
s, though,
cannot be captured into the method group closure, so if there is ever a method group converted to a delegate type, and it uses a span conversion on the receiver, that will be an error. Since these conversions can be
prioritized, it means that currently valid code will become an error, particularly as the BCL adds new Span
-taking overloads. Given the 100% error rate of the scenario, we are fine with adding a special rule to exclude
Span
conversions when doing method group overload resolution on an extension method called in extension form.
Mitigation is approved.