# C# Language Design Meeting for July 12th, 2021

## Agenda

1. [C# 10 Feature Status](#c-10-feature-status)
2. [Speakable names for top-level statements](#speakable-names-for-top-level-statements)

## Quote of the Day

- "You do realize there was a quote of the day there when you said there are still holes in the interpolated strings feature?" _collective groan_ "I keep track of the important stuff"

## Discussion

### C# 10 Feature Status

https://github.com/dotnet/roslyn/blob/main/docs/Language%20Feature%20Status.md#c-next

We spent the first half of today going through the remaining features that are currently being worked on by the compiler team and prioritizing them for what is going to make
C# 10, and what will need to be pushed out to early preview for C# 11. Of the things still under C# Next, the current statuses are:

- Parameterless struct constructors - will be merged for 17.0p3. This includes integration with record structs.
- nameof(parameter) - This is becoming increasingly important as we add new features that reference other parameters in attributes. Nullable already existed, but we're additionally
adding `CallerArgumentExpression` and `InterpolatedStringHandlerArgument` in C# 10. However, it is unlikely to be prioritized enough for C# 10.
- Parameter!! - This has IDE impact, so while the compiler-side is basically done, it does need some more work. We additionally want more community bake time to let customers actually
use the feature before we ship it. We'll be aiming for early C# 11 previews.
- Relax ordering of partial and ref - This is not being worked on, and should be removed from the status page.
- CallerArgumentExpression - The feature work for this is very nearly done. Should be in for C# 10.
- Generic attributes - The feature work for this is complete. Needs a few more tests, then should be merged for C# 10.
- List patterns - We're aiming for an early preview in C# 11.
- Remaining lambda work - Wave 1 (conversion to Delegate/Expression and attributes) and wave 2 (explicit return types) have been merged. We are currently working on Wave 3 (natural type and synthesized delegate types). Should be in for C# 10.

### Speakable names for top-level statements

When we initially shipped top-level statements in C# 9, we made the decision that the type and method that the statements generated should be unspeakable. Our reasoning here was that
the only reason the type or method would be needed would be for reflection to obtain the assembly, and users could use another type in the assembly for this. However, as work continues
on the lighter ASP.NET feather templates, we are encountering scenarios where there actually _aren't_ any other types in the user's assembly, which makes obtaining the assembly for
unit testing very complex. To address this, we considered a mechanism to make the type and method speakable by user code. We have a few main axes of choice for a proposal, several of
which are tied together:

* Introducing a named type into a compilation could break that compilation. Do we want to make it conditional on whether the user already has a type with the name we choose?
* Do we want to tie generating the type to language version or not?
* Will we allow the type to be speakable from the current compilation, or only from assemblies that _reference_ the current compilation?
* Will the type be partial or not?
* Do we want just the type to be speakable, or the type and the method both?
* Do we want the type to be public or internal?

First, we looked at the breaking change. We believe we would name the type `Program` and the method `Main`, following long C# template tradition, so our real question is "who is going
to create a program that is using top-level statements and has a type named `Program`?". We believe this to be a sufficiently small number of users that we are ok with the breaking
change. At the same time, we also looked at whether we should only generate the type when the user's language version is set to the appropriate version, meaning that C# 9 would still
generate an unspeakable name. After some consideration, we don't think that it's worth it to have separate generation strategies, as it will complicate the code for very little chance
of breaking. It does mean that there is the potential for someone to upgrade the compiler and not the language version and observe a breaking change from a different assembly, but we're
ok with this.

Next, we looked at the various levels of speakability. Only allowing the type to speakable by external assemblies is the minimal change to make, but it feels oddly inconsistent. Similar
reactions were had for the method name: while we don't have a specific scenario currently for the method naming being speakable, we feel it would simplify the mental model for either
everything to be speakable, or nothing to be speakable. We've always had the view that top-level statements are simply a sugar over a Main method in some type, and now we solidify
that view by adjusting the sugar to this:

```cs
using System;

Console.WriteLine(GetInt());

static int GetInt() => 1;
```

desugars into:

```cs
using System;

partial class Program
{
    public static void Main()
    {
        Console.WriteLine(GetInt());

        static int GetInt() => 1;
    }
}
```

By only specifying `partial class`, the type defaults to `internal` visibility, and we allow any other `partial` parts to be explicit about the visibility of the type and change it
however they choose. We will also change the signature of main based on the content, as we already do today with `args` and `await`.


#### Conclusion

We will adopt the above desugaring for top-level statements. This will introduce a break for any programs that have a non-partial `Program` type in the global namespace, or have a
partial `Program` type in the global namespace that is either not a `class` or defines a method named `Main` if that program is using top-level statements.
