# C# Language Design Meeting for December 17th, 2025

## Agenda

- [Collection expression arguments parsing question](#collection-expression-arguments-parsing-question)
- [Null-conditionals evaluating to a pointer type](#null-conditionals-evaluating-to-a-pointer-type)
- [Triage](#triage)
    - [Top-Level Members](#top-level-members)
    - [Using local declaration improvements](#using-local-declaration-improvements)

## Quote of the Day

- "We can't do advent of triage? Just one more?"

## Discussion

### Collection expression arguments parsing question

Champion issue: https://github.com/dotnet/csharplang/issues/8887  
Spec: https://github.com/dotnet/csharplang/blob/01e436bf45790b7118c116100c27a8172148c58d/proposals/collection-expression-arguments.md#finalizing-an-open-concern-from-httpsgithubcomdotnetcsharplangblobmainmeetings2025ldm-2025-03-17mdconclusion  

We started today by revisiting an earlier temporary decision; when we were considering whether `with` would be a breaking change at the
top level for collection expressions, we initially decided that we would take the breaking change for preview, but since we hadn't yet
finalized our syntax and were planning on previewing it for .NET 10, we didn't want to potentially break users for syntax we weren't certain
of. Since then, we've had our debates, settled on `with` as the syntax, and now we want to revisit the breaking change downlevel. Our
default approach to parsing changes is to always parse with new language features, and issue errors when users don't have the appropriate
language version enabled. Searching through GitHub we are unable to find examples of code that will actually break in this, so we are
comfortable following our usual approach; the .NET 11 SDK/C# 15 compiler will always parse `with` as collection expression arguments,
regardless of the language version of the project.

We also wanted to talk about the formal definition of the feature, and in particular, how the grammar rules actually will work. Do we want
to have a rule where the `with` has to be the top-level expression in the collection expression element, or do we want a rule where, if we
encounter `with(` to start a collection expression element, that element is a `with` element, regardless of following content? Concretely,
the question is how do we want something like this to parse: `[with() + with()]`. With the top-level rule, this would just be a binary 
operator `+` with method calls to methods named `with` in either arm. With the "first token" rule, it would be a `with` element, followed by a
binary operator `+` whose left operand is missing, and the right operand is a method invocation named `with`. After some debate, we decided
that it is simpler to go with the "first token" rule, and matches our precedent with `spread` elements, where a `..` always starts a spread,
never a range. This makes the parsing simple, and parentheses can easily disambiguate for scenarios where the user really wants to call a method,
just like it works for range.

#### Conclusion

We will not take language version into account when parsing, and will always parse `with` elements as `with` elements. If a collection expression
element starts with `with(`, that means it is a `with` element, following the `..` spread precedent.

### Null-conditionals evaluating to a pointer type

Issue: https://github.com/dotnet/roslyn/issues/7502  
Spec: https://github.com/dotnet/csharpstandard/blob/41694caebb0fb759b75ef66b9d11d37006aab000/standard/expressions.md#12813-null-conditional-element-access

Next up, we discussed a potential compiler bug/specification bug. This has been open for a long time, but was recently resurfaced and we wanted to
investigate to clarify our definitions. The question hinges on what the definition of what a non-nullable value type is. If a pointer is a non-nullable
value type, then the rules as written state that the type would have to be `Nullable<int*>`, which is indeed illegal. But if pointers are not
non-nullable value types, then the cases would fall through to the last bullet of the spec and it should just work, as the specified transformation
would be legal for a pointer. Certainly on the surface, pointer types are nullable: `int* i = null;` is legal, as is comparing them with `null`. Given
that, and the definitions in [§8.2.1](https://github.com/dotnet/csharpstandard/blob/41694caebb0fb759b75ef66b9d11d37006aab000/standard/types.md#821-general),
we are comfortable treating this as a compiler bug, and will fix it to work. We will also leave the decision on clarifying the specification further
to the ECMA 334 committee.

#### Conclusion

Null-conditional expressions that produce a pointer type not being allowed is a compiler bug and will be fixed as such.

### Triage

Finally today, we did some triage on newly-championed issues over the past few months.

#### Top-Level Members

Champion issue: https://github.com/dotnet/csharplang/issues/9803  
Spec: https://github.com/dotnet/csharplang/blob/e878e7860d9b6420112fd7b99b910a79c7103132/proposals/top-level-members.md

There are some strong feelings on this one in the LDM; nothing that we think would hold us from doing a deep design dive on it, but by no means
is there agreement on the feature at this point. We'll put it into the working set to have that debate.

#### Using local declaration improvements

Champion issue: https://github.com/dotnet/csharplang/issues/8606  
Spec: https://github.com/dotnet/csharplang/blob/afad49721a7b9923efbbc36ae6c455d85b994543/proposals/using-with-a-discard.md

Finally, we looked at a proposal for creating `using` local declarations without actually having to declare a local, marrying the implicit scope
benefits of `using` locals with the lack of variable pollution available from `using` statements. We are interested, but want to rename the proposal
from the current state to better reflect that goal, rather than a specific implementation of achieving that goal.
