Merge remote-tracking branch 'origin/master'

# Conflicts:
#	meetings/2017/README.md
This commit is contained in:
Mads Torgersen 2017-08-14 08:47:13 -07:00
commit 206fd05991
3 changed files with 290 additions and 419 deletions

View file

@ -1,117 +1,117 @@
# C# Language Design Notes for Jul 5, 2017
## Agenda
Triage of features in the C# 7.2 milestone. They don't all fit: which should be dropped, which should be kept, and which should be pushed out?
1. Static delegates *(8.0)*
2. Native int and IntPtr operators *(7.X)*
3. Field target *(anytime)*
4. Utf8 strings *(8.0)*
5. Slicing *(7.X)*
6. Blittable *(7.2)*
7. Ref structs *(7.2)*
8. Ref readonly *(7.2)*
9. Conditional ref *(7.2)*
10. Ref extensions on structs *(7.2)*
11. Readonly locals and params *(X.X)*
12. ref structs in tuples *(don't)*
13. Overload resolution tie breakers with long tuples *(use underlying generics)*
# Static delegates
Won't have time, and should probably be in a major release.
## Conclusion
8.0 for now.
# Native int and IntPtr operators
This won't make 7.2.
## Conclusion
Let's try to keep in 7 wave as 7.X (in case we have more point releases) . Probably only one of these will become a feature, but keeping both for now until we decide.
# Field target
Bug fix, do this anytime.
## Conclusion
Make sure it is on the Roslyn backlog.
# Utf8 strings
There's a bigger story that needs to be worked out here. There needs to be decisions around interpolated strings, formattable strings etc. This feels low on the list, and we don't have enough data to design it yet.
## Conclusion
Next major release: 8.0.
# Slicing
We would want to add a `Range` type, a syntax `3..5` to create a `Range` and then people can write indexers over ranges to implement slicing.
We could make it an entirely target-typed thing, where something with a proper constructor could be initialized with a span. Lots to think about.
Either way, `Span<T>` APIs would eventually want to make use of this, but would not depend on it from the outset.
## Conclusion
This won't make 7.2 but keeping it 7.X to keep thinking about it.
# Blittable
Small language feature, useful for certain scenarios but not central to 7.2 value proposition.
## Conclusion
Let's do it if we get to it. Keep it 7.2, but low pri for that release.
# Ref structs
Essential to the scenario and also almost done.
Still need `stackalloc` rules worked out. We'd prefer to keep that part of the functionality in, but could delay it if necessary.
## Conclusion
Stay in 7.2.
# Ref readonly
Essential to the scenario and pretty much done.
## Conclusion
Keep in 7.2.
# Conditional ref
Not essential but already done.
## Conclusion
Keep in 7.2.
# Ref extensions on structs
Not essential but already done.
## Conclusion
Keep in 7.2.
# Readonly locals and params
Stands on its own. It has some commonality with 7.2 scenarios, but is not essentially tied. Could be done together with ref readonly locals later. Also it has a lot of design work still to be done.
## Conclusion
Push to X.X.
# ref structs in tuples
Tuples can't contain ref structs because those can't be type arguments.
## Conclusion
That's a big pandora's box to open, and we won't.
# Overload resolution tie breakers with long tuples
There's an esoteric difference between whether "specificity" tie breaker should special case long tuple as a flat list, or should work according to the underlying generics, which are nested.
## Conclusion
We stick with how it works now, which is the underlying generics.
# C# Language Design Notes for Jul 5, 2017
## Agenda
Triage of features in the C# 7.2 milestone. They don't all fit: which should be dropped, which should be kept, and which should be pushed out?
1. Static delegates *(8.0)*
2. Native int and IntPtr operators *(7.X)*
3. Field target *(anytime)*
4. Utf8 strings *(8.0)*
5. Slicing *(7.X)*
6. Blittable *(7.2)*
7. Ref structs *(7.2)*
8. Ref readonly *(7.2)*
9. Conditional ref *(7.2)*
10. Ref extensions on structs *(7.2)*
11. Readonly locals and params *(X.X)*
12. ref structs in tuples *(don't)*
13. Overload resolution tie breakers with long tuples *(use underlying generics)*
# Static delegates
Won't have time, and should probably be in a major release.
## Conclusion
8.0 for now.
# Native int and IntPtr operators
This won't make 7.2.
## Conclusion
Let's try to keep in 7 wave as 7.X (in case we have more point releases) . Probably only one of these will become a feature, but keeping both for now until we decide.
# Field target
Bug fix, do this anytime.
## Conclusion
Make sure it is on the Roslyn backlog.
# Utf8 strings
There's a bigger story that needs to be worked out here. There needs to be decisions around interpolated strings, formattable strings etc. This feels low on the list, and we don't have enough data to design it yet.
## Conclusion
Next major release: 8.0.
# Slicing
We would want to add a `Range` type, a syntax `3..5` to create a `Range` and then people can write indexers over ranges to implement slicing.
We could make it an entirely target-typed thing, where something with a proper constructor could be initialized with a span. Lots to think about.
Either way, `Span<T>` APIs would eventually want to make use of this, but would not depend on it from the outset.
## Conclusion
This won't make 7.2 but keeping it 7.X to keep thinking about it.
# Blittable
Small language feature, useful for certain scenarios but not central to 7.2 value proposition.
## Conclusion
Let's do it if we get to it. Keep it 7.2, but low pri for that release.
# Ref structs
Essential to the scenario and also almost done.
Still need `stackalloc` rules worked out. We'd prefer to keep that part of the functionality in, but could delay it if necessary.
## Conclusion
Stay in 7.2.
# Ref readonly
Essential to the scenario and pretty much done.
## Conclusion
Keep in 7.2.
# Conditional ref
Not essential but already done.
## Conclusion
Keep in 7.2.
# Ref extensions on structs
Not essential but already done.
## Conclusion
Keep in 7.2.
# Readonly locals and params
Stands on its own. It has some commonality with 7.2 scenarios, but is not essentially tied. Could be done together with ref readonly locals later. Also it has a lot of design work still to be done.
## Conclusion
Push to X.X.
# ref structs in tuples
Tuples can't contain ref structs because those can't be type arguments.
## Conclusion
That's a big pandora's box to open, and we won't.
# Overload resolution tie breakers with long tuples
There's an esoteric difference between whether "specificity" tie breaker should special case long tuple as a flat list, or should work according to the underlying generics, which are nested.
## Conclusion
We stick with how it works now, which is the underlying generics.

View file

@ -1,302 +0,0 @@
# C# Language Design Notes for 2017
Overview of meetings and agendas for 2017
## Jan 10, 2017
[C# Language Design Notes for Jan 10, 2017](LDM-2017-01-10.md)
1. Discriminated unions via "closed" types
## Jan 11, 2017
[C# Language Design Notes for Jan 11, 2017](LDM-2017-01-11.md)
1. Language aspects of [compiler intrinsics](https://github.com/dotnet/roslyn/issues/11475)
## Jan 17, 2017
[C# Language Design Notes for Jan 17, 2017](LDM-2017-01-17.md)
1. Constant pattern semantics: which equality exactly?
2. Extension methods on tuples: should tuple conversions apply?
## Jan 18, 2017
[C# Language Design Notes for Jan 18, 2017](LDM-2017-01-18.md)
1. Async streams (visit from Oren Novotny)
## Feb 21, 2017
[C# Language Design Notes for Feb 21, 2017](LDM-2017-02-21.md)
We triaged some of the [championed features](https://github.com/dotnet/csharplang/issues?q=is%3Aopen+is%3Aissue+label%3A%22Proposal+champion%22), to give them a tentative milestone and ensure they had a champion.
As part of this we revisited potential 7.1 features and pushed several out.
1. Implicit interface implementation in Visual Basic *(VB 16)*
2. Delegate and enum constraints *(C# X.X)*
3. Generic attributes *(C# X.0 if even practical)*
4. Replace/original *(C# X.0 if and when relevant)*
5. Bestest betterness *(C# 7.X)*
6. Null-coalescing assignments and awaits *(C# 7.X)*
7. Deconstruction in from and let clauses *(C# 7.X)*
8. Target-typed `new` expressions *(C# 7.X)*
9. Mixing fresh and existing variables in deconstruction *(C# 7.1)*
10. Implementing `==` and `!=` on tuple types *(C# 7.X)*
11. Declarations in embedded statements *(No)*
12. Field targeted attributes on auto-properties *(C# 7.1)*
## Feb 22, 2017
[C# Language Design Notes for Feb 22, 2017](LDM-2017-02-22.md)
We went over the proposal for `ref readonly`: [Champion "Readonly ref"](https://github.com/dotnet/csharplang/issues/38).
## Feb 28, 2017
[C# Language Design Notes for Feb 28, 2017](LDM-2017-02-28.md)
1. Conditional operator over refs (*Yes, but no decision on syntax*)
2. Async Main (*Allow Task-returning Main methods*)
## Mar 1, 2017
[C# Language Design Notes for Mar 1, 2017](LDM-2017-03-01.md)
1. Shapes and extensions (*exploration*)
2. Conditional refs (*original design adopted*)
## Mar 7, 2017
[C# Language Design Notes for Mar 7, 2017](LDM-2017-03-07.md)
We continued to flesh out the designs for features currently considered for C# 7.1.
1. Default expressions (*design adopted*)
2. Field target on auto-properties (*yes*)
3. private protected (*yes, if things work as expected*)
## Mar 8, 2017
[C# Language Design Notes for Mar 8, 2017](LDM-2017-03-08.md)
We looked at default interface member implementations.
1. Xamarin interop scenario
2. Proposal
3. Inheritance from interface to class
4. Overriding and base calls
5. The diamond problem
6. Binary compatibility
7. Other semantic challenges
## Mar 15, 2017
[C# Language Design Notes for Mar 8, 2017](LDM-2017-03-15.md)
Triage of championed features
1. JSON literals
2. Fixing of captured locals
3. Allow shadowing of parameters
4. Weak delegates
5. Protocols/duck typing/concepts/type classes
6. Zero and one element tuples
7. Deconstruction in lambda parameters
8. Private protected
## Mar 21, 2017
[C# Language Design Notes for Mar 21, 2017](LDM-2017-03-21.md)
Discussion of default interface member implementations, based on [this guided tour](https://github.com/dotnet/csharplang/issues/288).
1. Concerns raised on GitHub and elsewhere
2. Inheritance?
3. Breaking name lookup on `this`
4. Events
5. Modifiers
6. Methods
7. Properties
8. Overrides
9. Reabstraction
10. Most specific override
11. Static non-virtual members
12. Accessibility levels
13. Existing programs
## Mar 28, 2017
[C# Language Design Notes for Mar 28, 2017](LDM-2017-03-28.md)
Design some remaining 7.1 features
1. Fix pattern matching restriction with generics
2. Better best common type
## Mar 29, 2017
[C# Language Design Notes for Mar 29, 2017](LDM-2017-03-29.md)
1. Nullable scenarios
2. `Span<T>` safety
## Apr 5, 2017
[C# Language Design Notes for Apr 5, 2017](LDM-2017-04-05.md)
1. Non-virtual members in interfaces
2. Inferred tuple element names
3. Tuple element names in generic constraints
## Apr 11, 2017
[C# Language Design Notes for Apr 11, 2017](LDM-2017-04-11.md)
1. Runtime behavior of ambiguous default implementation
## Apr 18, 2017
[C# Language Design Notes for Apr 18, 2017](LDM-2017-04-18.md)
1. Default implementations for event accessors in interfaces
2. Reabstraction in a class of default-implemented member
3. `sealed override` with default implementations
4. Use of `sealed` keyword for non-virtual interface members
5. Implementing inaccessible interface members
6. Implicitly implementing non-public interface members
7. Not quite implementing a member
8. asynchronous `Main`
## Apr 19, 2017
[C# Language Design Notes for Apr 19, 2017](LDM-2017-04-19.md)
1. Improved best common type
2. Diamonds with classes
3. Structs and default implementations
4. Base invocation
## May 16, 2017
[C# Language Design Notes for May 16, 2017](LDM-2017-05-16.md)
1. Triage C# 7.1 features that didn't make it
2. Look at C# 7.2 features
3. GitHub procedure around new design notes and proposals
4. Triage of championed features
## May 17, 2017
[C# Language Design Notes for May 17, 2017](LDM-2017-05-17.md)
More questions about default interface member implementations
1. Conflicting override of default implementations
2. Can the Main entry point method be in an interface?
3. Static constructors in interfaces?
4. Virtual properties with private accessors
5. Does an override introduce a member?
6. Parameter names
## May 26, 2017
[C# Language Design Notes for May 26, 2017](LDM-2017-05-26.md)
1. Native ints
## May 31, 2017
[C# Language Design Notes for May 31, 2017](LDM-2017-05-31.md)
1. Default interface members: overriding or implementing?
2. Downlevel poisoning of ref readonly in signatures
3. Extension methods with ref this and generics
4. Default in operators
## Jun 13, 2017
[C# Language Design Notes for Jun 13, 2017](LDM-2017-06-13.md)
1. Native-size ints
2. Native-size floats
## Jun 14, 2017
[C# Language Design Notes for Jun 14, 2017](LDM-2017-06-14.md)
Several issues related to default implementations of interface members
1. Virtual properties with private accessors
2. Requiring interfaces to have a most specific implementation of all members
3. Member declaration syntax revisited
4. Base calls
## Jun 27, 2017
[C# Language Design Notes for Jun 27, 2017](LDM-2017-06-27.md)
1. User-defined operators in interfaces
2. return/break/continue as expressions
## Jun 28, 2017
[C# Language Design Notes for Jun 28, 2017](LDM-2017-06-28.md)
1. Tuple name round-tripping between C# 6.0 and C# 7.0
2. Deconstruction without `ValueTuple`
3. Non-trailing named arguments
## Jul 5, 2017
[C# Language Design Notes for Jul 5, 2017](LDM-2017-07-05.md)
Triage of features in the C# 7.2 milestone. They don't all fit: which should be dropped, which should be kept, and which should be pushed out?
1. Static delegates *(8.0)*
2. Native int and IntPtr operators *(7.X)*
3. Field target *(anytime)*
4. Utf8 strings *(8.0)*
5. Slicing *(7.X)*
6. Blittable *(7.2)*
7. Ref structs *(7.2)*
8. Ref readonly *(7.2)*
9. Conditional ref *(7.2)*
10. Ref extensions on structs *(7.2)*
11. Readonly locals and params *(X.X)*
12. ref structs in tuples *(don't)*
13. Overload resolution tie breakers with long tuples *(use underlying generics)*
## Jul 26, 2017
[C# Language Design Notes for Jul 24 and 26, 2017](LDM-2017-07-26.md)
We started putting a series of stakes in the ground for nullable reference types, based on the evolving strawman proposal [here](https://github.com/dotnet/csharplang/issues/790). We're doing our first implementation of the feature based on this, and can then refine as we learn things from usage.
1. Goals
2. Nullable reference types
3. Rarely-null members
## Aug 7, 2017
[C# Language Design Notes for Aug 7, 2017](LDM-2017-08-07.md)
We continued refining the nullable reference types feature set with the aim of producing a public prototype for experimentation and learning.
1. Warnings
2. Local variables revisited
3. Opt-in mechanisms
## Aug 9, 2017
[C# Language Design Notes for Aug 9, 2017](LDM-2017-08-09.md)
We discussed how nullable reference types should work in a number of different situations.
1. Default expressions
2. Array creation
3. Struct fields
4. Unconstrained type parameters

View file

@ -235,4 +235,177 @@ ref SpanLikeType Test2(ref SpanLikeType param1, Span<byte> param2)
```
----------------
Draft language specification
==========================
Below we describe a set of safety rules for ref-like types (`ref struct`s), which includes the ability to pass locals by reference to constructors or instance methods of the type, suitable for use in the language specification. A different, simpler set of safety rules are possible if locals cannot be passed by reference. This specification would also permit the safe reassignment of ref locals.
Overview
========
We associate with each expression at compile-time the concept of what scope that expression is permitted to escape to, "safe-to-escape". Similarly, for each lvalue we maintain a concept of what scope its ref is permitted to escape to, "ref-safe-to-escape". For a given lvalue expression, these may be different.
These are analogous to the "safe to return" of the ref locals feature, but it is more fine-grained. Where the "safe-to-return" of an expression records only whether (or not) it may escape the enclosing method as a whole, the safe-to-escape records which scope it may escape to (which scope it may not escape beyond). The basic safety mechanism is enforced as follows. Given an assignment from an expression E1 with a safe-to-escape scope S1, to an (lvalue) expression E2 with safe-to-escape scope S2, it is an error if S2 is a wider scope than S1. By construction, the two scopes S1 and S2 are in a nesting relationship, because a legal expression is always safe-to-return from some scope enclosing the expression.
The reason the safe-to-escape needs to be a scope rather than a boolean is to handle situations such as the following
``` c#
{
int i = 0;
// make a span wrapping local variable i
var s1 = new Span<int>(ref i);
{
int j = 0;
// make a span wrapping a further nested local variable j
var s2 = new Span<int>(ref j);
// error: captures a reference to j into an enclosing scope
s1 = s2;
}
// If permitted, here is where a problem would occur, as we'd be assigning into
// a local whose lifetime has ended.
s1[0] = 12; // assign to whichever local the span references
}
```
The precise rules for computing the *safe-to-return* status of an expression, and the rules governing the legality of expressions, follows.
# ref-safe-to-escape
The *ref-safe-to-escape* is a scope, enclosing an lvalue expression, to which it is safe for a ref to the lvalue to escape to. If that scope is the entire method, we say that a ref to the lvalue is *safe to return* from the method.
# safe-to-escape
The *safe-to-escape* is a scope, enclosing an expression, to which it is safe for the value to escape to. If that scope is the entire method, we say that a the value is *safe to return* from the method.
An expression whose type is not a `ref struct` type is *safe-to-return* from the entire enclosing method. Otherwise we refer to the rules below.
## Parameters
An lvalue designating a formal parameter is *ref-safe-to-escape* (by reference) as follows:
- If the parameter is a ref or out parameter, it is *ref-safe-to-escape* from the entire method (e.g. by a `return ref` statement); otherwise
- If the parameter is the `this` parameter of a struct type, it is *ref-safe-to-escape* to the top-level scope of the method (but not from the entire method itself);
- Otherwise the parameter is a value parameter, and it is *ref-safe-to-escape* to the top-level scope of the method (but not from the method itself). This includes parameters of `ref struct` type.
An expression that is an rvalue designating the use of a formal parameter is *safe-to-escape* (by value) from the entire method (e.g. by a `return` statement). This applies to the `this` parameter as well.
## Locals
An lvalue designating a local variable is *ref-safe-to-escape* (by reference) as follows:
- If the variable is a `ref` variable, then its *ref-safe-to-escape* is taken from the *ref-safe-to-escape* of its initializing expression; otherwise
- The variable is *ref-safe-to-escape* the scope in which it was declared.
An expression that is an rvalue designating the use of a local variable is *safe-to-escape* (by value) as follows:
- If the variable's type is a `ref struct` type, then the variable's declaration requires an initializer, and the variable's *safe-to-escape* scope is taken from that initializer.
> ***Open Issue:*** can we permit locals of `ref struct` type to be uninitialized at the point of declaration? If so, what would we record as the variable's *safe-to-escape* scope?
## Field reference
An lvalue designating a reference to a field, `e.F`, is *ref-safe-to-escape* (by reference) as follows:
- If `e` is of a reference type, it is *ref-safe-to-escape* from the entire method; otherwise
- If `e` is of a value type, its *ref-safe-to-escape* is taken from the *ref-safe-to-escape* of `e`.
An rvalue designating a reference to a field, `e.F`, has a *safe-to-escape* scope that is the same as the *safe-to-escape* of `e`.
## ?: and other multi-operand operators
For an operator with multiple operands that yields an rvalue, such as `e1 + e2` or `c ? e1 : e2`, the *safe-to-escape* of the result is the narrowest scope among the *safe-to-escape* of the operands of the operator.
For an operator with multiple operands that yields an lvalue, such as `c ? ref e1 : ref e2`, the *ref-safe-to-escape* of the operands must agree, and that is the *ref-safe-to-escape* of the resulting lvalue.
## Method invocation
An lvalue resulting from a ref-returning method invocation `e1.M(e2, ...)` is *ref-safe-to-escape* the smallest of the following scopes:
- The entire enclosing method
- the *ref-safe-to-escape* of all `ref` and `out` argument expressions (excluding the receiver)
- the *safe-to-escape* of all argument expressions (including the receiver)
> Note: the last bullet is necessary to handle code such as
> ``` c#
> var sp = new Span(...)
> return ref sp[0];
> ```
> or
> ``` c#
> return ref M(sp, 0);
> ```
An rvalue resulting from a method invocation `e1.M(e2, ...)` is *safe-to-escape* from the smallest of the following scopes:
- The entire enclosing method
- the *ref-safe-to-escape* of all `ref` and `out` argument expressions (excluding the receiver)
- the *safe-to-escape* of all argument expressions (including the receiver)
> Note that these rules are identical to the above rules for *ref-safe-to-escape*, but apply only when the return type is a `ref struct` type.
## Property invocations
A property invocation (either `get` or `set`) it treated as a method invocation of the underlying method by the above rules.
## `stackalloc`
A stackalloc expression is an rvalue that is *safe-to-escape* to the top-level scope of the method (but not from the entire method itself).
## Constructor invocations
A `new` expression that invokes a constructor obeys the same rules as a method invocation that is considered to return the type being constructed.
## `default` expressions
A `default` expression is *safe-to-escape* from the entire enclosing method.
## Other operators
***TODO: What others need to be handled? Should survey the language syntactic forms that are capable of producing a `ref struct` type.***
# Language Constraints
We wish to ensure that no `ref` local variable, and no variable of `ref struct` type, refers to stack memory or variables that are no longer alive. We therefore have the following language constraints:
- Neither a ref parameter, nor a ref local, nor a parameter or local of a `ref struct` type can be lifted into a lambda.
- Neither a ref parameter nor a parameter of a `ref struct` type may be an argument on an iterator method or an `async` method.
- A ref local may not be in scope at the point of a `yield return` statement or an `await` expression.
- A `ref struct` type may not be used as a type argument, or as an element type in a tuple type.
- A `ref struct` type may not be the declared type of a field, except that it may be the declared type of an instance field of another `ref struct`.
- A `ref struct` type may not be the element type of an array.
- A value of a `ref struct` type may not be boxed:
- There is no conversion from a `ref struct` type to the type `object` or the type `System.ValueType`.
- A `ref struct` type may not be declared to implement any interface
- No instance method declared in `object` or in `System.ValueType` but not overridden in a `ref struct` type may be called with a receiver of that `ref struct` type.
- No instance method of a `ref struct` type may be captured by method conversion to a delegate type.
- For a ref reassignment `ref e1 = ref e2`, the *ref-safe-to-escape* of `e2` must be at least as wide a scope as the *ref-safe-to-escape* of e1.
- For a ref return statement `return ref e1`, the *ref-safe-to-escape* of `e1` must be *ref-safe-to-escape* from the entire method. (TODO: Do we also need a rule that `e1` must be *safe-to-escape* from the entire method, or is that redundant?)
- For a return statement `return e1`, the *safe-to-escape* of `e1` must be *safe-to-escape* from the entire method.
- For an assignment `e1 = e2`, if the type of `e1` is a `ref struct` type, then the *safe-to-escape* of `e2` must be at least as wide a scope as the *safe-to-escape* of e1.
- In a method invocation, the following constraints apply:
- If there is a `ref` or `out` argument to a `ref struct` type (including the receiver), with *safe-to-escape* E1, then
- no `ref` or `out` argument (excluding the receiver) may have a narrower *ref-safe-to-escape* than E1; and
- no argument (including the receiver) may have a narrower *safe-to-escape* than E1.
> ***Open Issue:*** We need some rule that permits us to produce an error when needing to spill a stack value of a `ref struct` type at an await expression, for example in the code
> ``` c#
> Foo(new Span<int>(...), await e2);
> ```
> ***Open Issue:*** This treatment does not yet consider local functions. The required rule might be of the form that "a local function may not refer to a local or parameter of `ref struct` type declared in an enclosing scope.
> ***Open Issue:*** This treatment does not yet consider `in` parameters. The required rule might be that a value argument to an `in` parameter has a *ref-safe-to-escape* that is the smallest enclosing expression whose containing syntactic construct is a statement, ctor-initializer, field initializer, method declaration, or lambda expression. This may break the invariant that the *ref-safe-to-escape* is some enclosing scope, as the result of the call can be captured in a ref local, which can then be used later. Perhaps we need to forbid capturing it in a ref local.
> ***Open Issue:*** This treatment does not yet consider an argument expression of the form `ref d.F` where d is of type dynamic. The required rule may be similar to the treatment of `in` parameters.