[Version 11.0] Feature support for ref fields and scoped#1614
[Version 11.0] Feature support for ref fields and scoped#1614RexJaeschke wants to merge 15 commits intodraft-v11from
Conversation
BillWagner
left a comment
There was a problem hiding this comment.
Keeping notes on my first read. Some concerns and questions to answer as I read through everything again.
|
|
||
| ### §UnscopedRefAttribute The UnscopedRef attribute | ||
|
|
||
| There are several cases in which a ref is treated as being implicitly scoped; that is, the ref is not allowed to escape a method. For example: |
There was a problem hiding this comment.
I'd consider putting the xref on this paragraph. The section on the scoped modifier defines what it means.
| > | ||
| > *end example.* | ||
|
|
||
| A reference variable can be scoped explicitly; see §scoped-modifier. |
There was a problem hiding this comment.
This needs more qualification. It's true for local variables and parameters, but not for reference fields in a ref struct.
| - For a ref reassignment `e1 = ref e2`, the ref-safe-context of `e2` shall be at least as wide a context as the *ref-safe-context* of `e1`. | ||
| - For a ref return statement `return ref e1`, the ref-safe-context of `e1` shall be the caller-context. | ||
|
|
||
| ### §scoped-modifier The scoped modifier |
There was a problem hiding this comment.
I don't see any restriction here or in the grammar that the scoped modifier can only be applied to local variables and parameters.
|
|
||
| > *Note*: Initialization to default values is typically done by having the memory manager or garbage collector initialize memory to all-bits-zero before it is allocated for use. For this reason, it is convenient to use all-bits-zero to represent the null reference. *end note* | ||
|
|
||
| To test if a ref variable has been assigned a referent, call `System.Runtime.CompilerServices.Unsafe.IsNullRef(ref fieldName)`. |
There was a problem hiding this comment.
Should this paragraph be informative rather than normative? Possibly combined with the note that follows.
|
|
||
| ### §scoped-modifier The scoped modifier | ||
|
|
||
| The contextual keyword `scoped` is used as a modifier to restrict the ref-safe-context ([§9.7.2](variables.md#972-ref-safe-contexts)) or safe-context ([§16.5.15](structs.md#16515-safe-context-constraint)) of a variable. The presence of this modifier asserts that related code doesn’t extend the lifetime of the variable. |
There was a problem hiding this comment.
I don't think "asserts" is the right verb here. Maybe state it this way:
| The contextual keyword `scoped` is used as a modifier to restrict the ref-safe-context ([§9.7.2](variables.md#972-ref-safe-contexts)) or safe-context ([§16.5.15](structs.md#16515-safe-context-constraint)) of a variable. The presence of this modifier asserts that related code doesn’t extend the lifetime of the variable. | |
| The contextual keyword `scoped` is used as a modifier to restrict the ref-safe-context ([§9.7.2](variables.md#972-ref-safe-contexts)) or safe-context ([§16.5.15](structs.md#16515-safe-context-constraint)) of a variable. The presence of this modifier requires that related code doesn’t extend the lifetime of the variable. |
| - one of the following value types: `sbyte`, `byte`, `short`, `ushort`, `int`, `uint`, `nint`, `nuint`, `long`, `ulong`, `char`, `float`, `double`, `decimal`, `bool`; or | ||
| - any enumeration type. | ||
|
|
||
| A reference variable field `rv` of type `T`, may not have an explicit initializer of `default`. |
There was a problem hiding this comment.
Two thinks to checK:
- Can a
refvariable berefinitialized to point to something (e.g.ref int iRef = ref parameter;) and to the default reference (e.g.ref int iRef = ref default;).
| > var orders = new Dictionary<int,Order>(); | ||
| > ref var j = ref i; | ||
| > ref readonly var k = ref i; | ||
| > scoped var r = new RS(); // ref struct RS {} |
There was a problem hiding this comment.
In all cases, I think a more realistic example for the Ref Struct type would be one that takes a single parameter that's a ref. That illustrates the reason for scoped restrictions:
scoped var r = new RS(ref orders);
Or similar. This should apply to all examles using RS
| @@ -569,7 +569,7 @@ argument_value | |||
| : expression | |||
| | 'in' variable_reference | |||
| | 'ref' variable_reference | |||
There was a problem hiding this comment.
(Need to verify, but I think scoped can be applied to both in and ref variables:
| | 'ref' variable_reference | |
| | 'in' 'scoped'? variable_reference | |
| | 'ref' 'scoped'? variable_reference |
|
|
||
| It is a compile time error if the ref-safe-context ([§9.7.2](variables.md#972-ref-safe-contexts)) of the left operand is wider than the ref-safe-context of the right operand. | ||
|
|
||
| The left operand shall have the same safe-context as the right operand. |
There was a problem hiding this comment.
This is a stronger restriction than the one on L7172. L7172 can be deleted, with the appropriate link to 9.7.2 added here.
| - The keyword `in` followed by a *variable_reference* ([§9.5](variables.md#95-variable-references)), indicating that the argument is passed as an input parameter ([§15.6.2.3.2](classes.md#156232-input-parameters)). A variable shall be definitely assigned ([§9.4](variables.md#94-definite-assignment)) before it can be passed as an input parameter. | ||
| - The keyword `ref` followed by a *variable_reference* ([§9.5](variables.md#95-variable-references)), indicating that the argument is passed as a reference parameter ([§15.6.2.3.3](classes.md#156233-reference-parameters)). A variable shall be definitely assigned ([§9.4](variables.md#94-definite-assignment)) before it can be passed as a reference parameter. | ||
| - The keyword `out` followed by a *variable_reference* ([§9.5](variables.md#95-variable-references)), indicating that the argument is passed as an output parameter ([§15.6.2.3.4](classes.md#156234-output-parameters)). A variable is considered definitely assigned ([§9.4](variables.md#94-definite-assignment)) following a function member invocation in which the variable is passed as an output parameter. | ||
| - The keyword `out` optionally followed by `scoped`, optionally followed by a *variable_reference* ([§9.5](variables.md#95-variable-references)), indicating that the argument is passed as an output parameter ([§15.6.2.3.4](classes.md#156234-output-parameters)). A variable is considered definitely assigned ([§9.4](variables.md#94-definite-assignment)) following a function member invocation in which the variable is passed as an output parameter. For a discussion of `scoped`, see §scoped-modifier. |
There was a problem hiding this comment.
Per above, I think these changes need to be applied to L581 and L582 for ref and in variables.
|
Notes on the open issues:
|
Under Construction
This is Rex's adaptation of the corresponding MS proposal.
Open Issues
Numerous places in the spec now point back to this section. It is very likely more needs to be said here.
The MS proposal has a section called “Implicitly scoped parameters.” From that, I have added text to say that an output parameter is implicitly scoped, but made no other changes regarding that section. Are other changes needed?
The MS proposal has a section called “Infer safe-context of declaration expressions.” I made no changes for that section. Are changes needed?
The MS proposal has a section called “Deconstruction expressions” whose contents are “[TBD].” What, if anything do we need to say about this proposal in that context?
The MS proposal has a section called “Return-only safe context.” I made no changes for that section; however, presumably, changes are needed.
The MS proposal has a section called “Rules for method invocation.” I made no changes for that section; however, presumably, changes are needed.
The MS proposal has a section called “Rules for object initializers.” I made no changes for that section; however, presumably, changes are needed.
The MS proposal has a section called “Method arguments must match.” I made no changes for that section; however, presumably, changes are needed.
The MS proposal has a section called “Parameter scope variance.” I made no changes for that section; however, presumably, changes are needed.
The MS proposal has a section called “Initializers with ref values in new and with expressions.” I made the grammar changes only. Perhaps other changes are needed based on the accompanying narrative.
The MS proposal has a section called “Changes in unsafe context.” I made no changes for that section, but surely some are needed.
The MS proposal has a section called “ScopedRefAttribute.” I made no changes for that section, as that appears to be an implementation detail.
The MS proposal has a section called “RefSafetyRulesAttribute.” I made no changes for that section, as that appears to be an implementation detail.
The MS proposal has a section called “Change the design to avoid compat breaks.” I made no changes for that section, but some are probably needed.
The MS proposal has a 14-page section (with numerous subsections) called “Related Information.” I made no changes for that section; it all looks like background reading, but perhaps one or more examples from here might be useful in the spec.