# C# Language Design Meeting for December 15th, 2021

## Agenda

1. [Required parsing](#required-parsing)
2. [Warnings for parameterless struct constructor](#warnings-for-parameterless-struct-constructor)

## Quote of the Day

- "Please don't make that the quote of the day. We want to project responsibility to the community."

## Discussion

### Required parsing

https://github.com/dotnet/csharplang/issues/5439

The main question here is whether we should allow types named `required` in the language in C# 11, without escaping the name with an `@`. We did
a similar thing for `record` in C# 9, but in that scenario `record` had true syntactic ambiguities. For `required`, there aren't true syntactic
ambiguities: just like with `async`, it is possible to fully disambiguate types named `required` and `required` used as a modifier with enough
lookahead. However, we have started taking a harder stance against types named with all lowercase 'a'-'z' characters: in .NET 7, we will be report
a warning on such type names in general. While we still want to make sure that we're choosing names for new keywords that are unlikely to conflict
with user-defined types, we think `required` is unlikely to be a type name, even beyond the general C# convention of not naming in lowercase, as
`required` is not a noun. Even for `record`, which is a noun and reasonable one to use (for a record in a DB, as an example), we heard little to
no complaints about erroring on it. Therefore, we are comfortable making `required` illegal as a type name without using an `@` to escape it.

#### Conclusion

`required` will be disallowed as a type name in C# 11. In general, we are ok with taking over all-lowercase identifiers that can be confused for
type names, so long as we do our due diligence in making sure that we're not breaking existing common usages.

### Warnings for parameterless struct constructor

https://github.com/dotnet/csharplang/issues/5546

This issue around `new S()` where `S` is a struct without a parameterless constructor is a particularly thorny area. There are three main paths
we could take to resolve it, each with significant downsides:

1. Warn on field initializers when a parameterless constructor will not be created. This is painful for users trying to share initializer logic
across multiple other constructors, and is also painful for record structs. If a user wants to change anything about a record struct parameter
(ie, turn the property into a field, make one property `init`-only, add a validation check) there is no alternative _but_ making a field initializer.
2. Warn when calling `new S()` if `S` doesn't have a parameterless constructor. This is an extremely broad hammer, as this code has been legal
since C# 1. It also has bad interactions with generics, as `where T : struct` implies `where T : new()`. We think this option is like attempting to
use a sledgehammer to drive in a finishing nail.
3. A more limited version of 2 where we only warn if the struct in question has field initializers. This heuristic breaks almost immediately, as
we have no way to determing whether a struct from metadata has field initializers.

This might be a place that an analyzer implementing option 1 would make more sense than a compiler warning: analyzers can be more configurable than
analyzer warnings, both in their severity levels, and in accepting additional options to tune the analyzer. An analyzer will also be able to do
more heuristics than we feel comfortable doing in the language, such as detecting when initializers are only using the primary constructor parameters
in record structs.

We also looked at the second issue listed in the bug, but determined that it is already an error, and we did not need to make any further changes.

#### Conclusion

We'll look at doing an analyzer implementing a warning on structs with field initializers that do not generate a parameterless constructor, with
some amount of heuristic suppression for scenarios where it is unavoidable.
