csharplang/meetings/2020/LDM-2020-09-23.md
2020-10-12 16:00:42 -07:00

3.3 KiB

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. 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 refs will will end up everywhere, in much the same way that null ends up everywhere. We may need to think more about this problem.