# C# Language Design Meeting for July 20th, 2020

## Agenda

1. [Finishing Triage](#finishing-triage)
    a. [Extend with expression to anonymous type](#Extend-with-expression-to-anonymous-type)
    b. [Required properties](#Required-properties)
    c. [Shebang support](#shebang-support)
2. [Private reference fields in structs with `SkipLocalsInit`](#Private-reference-fields-in-structs-with-`SkipLocalsInit`)

## Quote of the Day

"If you go get a beer from the fridge or wherever you keep them and drink it right now, I'll refund you."

## Discussion

### Finishing Triage

#### Extend with expression to anonymous type

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

We don't see any reason why we couldn't extend `with` expressions to handle anonymous types, and we universally support
the idea. We do see room for further improvement as well. Struct types should be generally possible to `with`, and in
particular tuples should feel first class here. Some other ideas for future improvements that we'll need to keep in mind
when designing anonymous types is an ability to specify a `withable` constraint: perhaps that's a thing we could do via
typeclasses, but if that's a thing that should be specifiable then we'll want to make sure that whatever we do for structs
and anonymous types works well with it.

##### Conclusion

Triaged into C# 10 for discussion with the other `with` enhancements

#### Required properties

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

A smaller group is currently fleshing this proposal out in the direction of initializer debt, and is looking to talk more
about it in the next few months.

##### Conclusion

Triaged for C# 10.

#### Shebang support

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

This is part of the next step in the C# scripting discussion. In particular, this proposal details just one, very small
piece of the puzzle here, namely the ability have a C# file startup an environment. There is significantly more work to
be done in the language and tooling to effectively modernize the loose-files support for C#. Today, C# code has a core
concept that cs files themselves do not contain information about the runtime environment. They don't specify the target
runtime, nuget dependencies, where tools can be found, or anything else similar (beyond some `#ifdef` blocks). Supporting
this would be intentionally eroding this aspect, which we need to make sure we're doing with intention and design. There
is support among LDT members for this scenario, so we'll continue to look at.

##### Conclusion

Triaged into C# 10 for discussion. We acknowledge that we may well not ship anything in this space as part of C# 10, but
we want to start discussing possible futures here in the coming X months, not X years.

### Private fields in structs with `SkipLocalsInit`

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

Proposal 1: https://github.com/dotnet/roslyn/issues/30194#issuecomment-657858716
Proposal 2: https://github.com/dotnet/roslyn/issues/30194#issuecomment-657900257

This topic was brought up last week when we realized there was a potential hole in `SkipLocalsInit` with definite
assignment, where we realized it's possible to observe uninitialized memory via private fields. When importing metadata,
the native compiler ignored private fields, including private fields in structs, and did not require them to be considered
definitely assigned before usage. This behavior was preserved when we implemented Roslyn, as attempting to break it was
too large of a change for organizations to adopt. Both of these proposals ensure that, with `SkipLocalsInit` on a method,
it's considered an error to not definitely assign here, which was fine with LDM as this is a new feature and cannot break
anyone. We then looked at the differences between the two proposals, namely whether the definite assignment diagnostic
should be a warning or an error when users opt into to a new warning wave. We found the arguments around incremental
adoption compelling: we don't want users to be blocked off from adopting new warning waves and making their code at least
a little safer by issuing errors that cannot be ignored. If users want to ensure that these warnings are fixed in their
code, they can use `warnAsError` to turn these specific warnings or all warnings into errors, as you can today.

#### Conclusion

Proposal 1 has been chosen:

1. If a method has the [SkipLocalsInit] attribute, or the compilation has the "strict" feature enabled, we use the strong
version of analysis for its body. Otherwise
2. If a sufficiently high /warnversion (>= 5) is enabled, we run the strong version of analysis, and
  a. If it reports no diagnostics, we are done.
  b. If it reports diagnostics, we run the weak version of analysis. Errors that are common to the two runs are reported
  as errors, and errors only reported by the strong version are downgraded to a warning.
3. Otherwise we run the weak version of analysis.

### Future record direction

See https://github.com/dotnet/csharplang/issues/3707 for the full list. We briefly went through the list here to gauge
support from LDT members on the various proposals. We didn't get particularly in depth on any one part, but some
highlights:

* `init` fields and methods - We rejected these in 9, deciding to wait for community feedback. We believe this is still
the right decision, and want to hear user scenarios before proceeding further.
* Final initializers - We briefly entertained the idea of having an `init { }` syntax to guarantee that a block is called
after a method. This was later rejected as too complicated after design review. Like `init`, we need to get a better
handle on the user scenarios.
* Required members - We have broad support for doing something in this space.
* Factores - We have broad support for doing something in this space.
* User-defined cloning - Will likely need to be designed hand-in-hand with factories
* Cross-inheritance between records and non-records - part of the initial record goal was that `record` is pure syntactic
sugar. If that's still a goal, then we need to do more work here.
* Generalized primary constructors - Mixed support here. We need to do more design work.
* Primary constructor bodies - Might be done for the former. We need to flesh this out so we can determine how to apply
attributes to record constructors.
* Discriminated unions - We need to determine whether this will be a simple syntactic shorthand for a general sealed type
hierarchy feature, or if this will be the only way to declare such hierarchies.
