# C# Language Design Meeting for September 23rd, 2020

## Agenda

1. General improvements to the `struct` experience

## Quote of the day

- "This makes C# developers queasy. Refs can never be null! The runtime says that's not true, the C# type system is a lie."

## Discussion

Most of this session was dedicated to explaining the proposal itself, which can be found [here](https://github.com/dotnet/csharplang/blob/master/proposals/low-level-struct-improvements.md).
We covered the section `Provide ref fields` in full, but did not get beyond that in this session. What follows are some noted comments on the
proposal, as we did not have long discussions about the merits of the feature itself.

* The general driving principles of this proposal are to ease friction points in the language around structs. Today we have `Span<T>`, which is
a very useful type, but it uses a magic BCL-internal type called `ByReference<T>`. Span uses it to great effect, but because there are no compile
rules around its safety we can't expose it publicly. This leads to 3rd parties using reflection to get it, which just results in badness all
around. We'd like to allow the semantics to be fully specifiable in C# and enable it not just for the BCL, but for all types of structs. The LDM
generally agrees with this goal.
* There will need to be some metadata tool updates. In order for safe-to-escape analysis to work, we will have to ensure that all `ref` fields,
even private fields, appear in reference assemblies and similar locations to ensure that the compiler can correctly determine lifetimes.
* The rules around returning a ref to a ref parameter are not especially intuitive. We acknowledge that they are necessary given the lifetime
rules today with methods returning a `Span`, but we could introduce a `CapturesAttribute` or something similar to indicate that a `ref` parameter
is captured by the method, and thus allow passing it directly as a `ref` to `new Span<T>`.
    * There is a workaround for this behavior: instead of taking a `ref T` in the constructor, take a `Span<T>`, which will ensure that all the
    lifetimes line up. While this workaround is viable, we're somewhat worried it won't be straightforward enough of a solution.
* Allowing `ref` assignment after the fact could be done in a later version of C#. It's a good deal of work in the compiler (likely an entirely
new flow analysis pass) to correctly update the lifetimes, and we're not yet certain that the scenario is worth the effort. If this proves to be
a friction point for users, we can revisit.
* One scenario this spec does not consider is `ref` assignment in an object initializer, which is still part of the object construction phase.
This should be allowable, and we need to update the draft specification to address this case.
* `ref null` is going to be an annoying problem. Given that you can `default` structs in any of a number of ways, at some point it will be possible
to observe a `default` ref struct that has a `null` `ref`. While the runtime does have an `Unsafe.IsNullRef` helper method, it feels unnatural that
code that is entirely safe C# should have to use a method from the `Unsafe` class. Further, these newly-observable `null` `ref`s will will end up
everywhere, in much the same way that `null` ends up everywhere. We may need to think more about this problem.
