74 lines
3.1 KiB
Markdown
74 lines
3.1 KiB
Markdown
# 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:
|
|
|
|
``` c#
|
|
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.
|
|
|
|
|
|
|
|
|
|
|