meetings/2025/LDM-2025-06-23.md
Champion issue: https://github.com/dotnet/csharplang/issues/8697
Specifications:
Previously, we'd decided to use the existing Expression factory methods for expression trees. This works in most cases, but
falls over in scenarios that need multiple extension operators, such as && or ||. For these scenarios, the ideal fix would
be to add a new factory method, but we don't think this is something that we can do at this time. Therefore, we'll simply note
the issue in documentation, and if we make future changes to expression trees, we could potentially address this shortcoming then.
Proposed rules approved. && and || implemented via extensions will not be allowed in expression trees.
ref encoding and conflict checksConfirm that
refshould not be included in extension type name
After some discussion here, we realized that the question has some fundamental issues that need to go back to the working group.
https://github.com/dotnet/roslyn/issues/79043 demonstrates an issue with our current conflict checking rules; because we do not
consider refness when doing signature conflict checking, we prevent this scenario from migrating to new extensions. We also
don't think this is particularly edge case code; it's certainly not mainstream, but it's not a truly niche thing. The proposed rules
for ref name encoding would be at odds with allowing this code to be valid C#; while that particular scenario would be okay
because the constraints would force the creation of two different skeleton containers, the constraints are not the important bit
that allows the code to be valid. What allows the code to be valid is the refness, and it would be odd to have a form that is
allowed in C# but we can't actually emit in many cases. Given this, the working group will take another look at the conflict rules
and bring back a new proposal for how to encode these bits.
We confirmed support here. Existing extensions support extern, so the new ones will too.
Confirm that we want betterness rules to apply even when the receiver is a type
Next, we looked at the proposed static member betterness rules. The existing rules are based on the model that there is an implicit
parameter here, the type itself, and that therefore everything that goes into standard parameter checking should go into
betterness for static invocations. We don't feel that this is a convincing argument, as there is no value to applying refness to here.
Further, it would mean that users would need to understand that it would be a source-breaking change to move an extension from an
extension(in int) block to an extension(int) block, because it could affect the tiebreaking with another library's extensions.
We therefore conclude that static extension lookup will only look at the type being extended when doing resolution, not any other
tiebreaking criteria.
For static extension members, we will only use the type for the extra "parameter".
Confirm that we don't want some betterness across all members before we determine the winning member kind
We're concerned here that if we don't support some form of betterness, it will block users from being able to move things that are currently written as extension methods but would be better written as extension properties. These APIs are expressed as well as they can be today, given that we don't have extension properties today. We feel strongly that these APIs should be able to work, but we are also uncertain as to whether we can reasonably deliver this experience before C# 14 releases. The status quo does protect our ability to design rules that by and large do the "right" thing by default, invoking methods where appropriate and calling properties when appropriate. We'll therefore proceed with this, and work on a design for making this "just work".
Ambiguity rules will be left in place while we work on creating rules for making code work as the user would expect.