csharplang/meetings/2017/LDM-2017-08-28.md
2018-01-25 13:11:49 -08:00

3.1 KiB

C# Language Design Notes for Aug 28, 2017

Warning: These are raw notes, and still need to be cleaned up. Read at your own peril!

Agenda

Ref-like types safety rules

https://github.com/dotnet/csharplang/blob/master/proposals/span-safety.md#draft-language-specification

The need for ref-like types quickly arises, when you need to flow more than one span, etc.

The fact that span is array like is not very interesting for the safety rules. The interesting thing is that it embeds a reference. Indexing is not a core concern in the general case.

Once you can embed refs in struct, the question: How can you assign them?

With assignment, you can now assign to ref parameters of ref-like structs, so every assignment is a potential return.

"Let's not refer to local data" does not work here:

  • we want the feature to refer to local data. stackalloc, etc.
    • lightweight params, etc.
  • we want to protect our future ability to allow this even if we could live with it now

So: We need to allow local data inside ref-like structs.

We tie a scope to variables holding ref-like structs. That scope is based on what the variable is initialized with. We call this the "escape level".

Essentially, on the assignment we check that the assigned-to variable's scope is no wider than the assigned value's scope.

The rules assume that everyone plays by them.

Special craziness for multiple arguments, some which are refs, some which are refs to ref-like:

void M(ref Span<int> x, ref int y) 
{
    // One of two things must be true about this:
    //  1. This is an error
    //  2. The caller has guaranteed this is safe
    x = new Span<int>(ref y); 
}

We need to do this on the caller, who knows most about the situation. The caller therefore has to assume that there is cross-assignment in the callee.

Q: Could you track the escape level during flow analysis, changing it locally? It's possible we could, but it seems extremely complex. We propose strict rules now; a flow analysis later would be more permissive, if we can figure it out. That's an important property!

"ref safe to escape" is how far you can escape the variable. "safe to escape" is how far you can escape a value. Only relevant if that value is a ref-like struct that can contain a ref.

Quality of error messages: We'll do a decent job, but a) it rarely gets complicated/cascading, b) we can improve them later if they turn out not to be good enough. Rust has error messages about this kind of thing that are just stellar, but this is bread-and-butter code in Rust, whereas it's exceptional here.

Defer: Should uninitialized ref-struct locals be allowed? Defer: Should default values of ref-struct types be allowed?

Methods can return by-ref, ref-like and by-ref ref-like! We say that by-ref ref-like parameters are not returnable!

Open issue with ref dynamic: Treat them like in parameters, in how we deal with compiler-generated temps.

Language restrictions:

  • Local functions - it's a shame that we can't factor out this stuff to local functions, because of the closure rule. But we can fix it later if necessary.