Skip to content

Commit dbb2869

Browse files
committed
Editorial fixes
| File | Change | |------|--------| | variables.md ~L1342 | Qualify scoped applicability: "local variable or parameter" (not fields). | | variables.md ~L1443 | Add normative restriction: scoped not on fields, array elements, return types. | | variables.md ~L203 | Make IsNullRef paragraph informative (wrap in note). | | variables.md ~L1441 | "asserts" → "requires". | | expressions.md ~L3521 | "may not" → "shall not" for ref field default. | | statements.md ~L382 | Better RS examples: `new RS(ref orders)` to show why scoped matters. | | expressions.md ~L7172 | Delete old ref-safe-context rule (subsumed); consolidate into two-rule formulation with §9.7.2 xref. | | structs.md ~L164 | Restore note: struct members = class members minus finalizer, plus ref fields. | | structs.md ~L795 | Constructor text: add "and all reference variable fields to null references". |
1 parent 77624af commit dbb2869

5 files changed

Lines changed: 16 additions & 14 deletions

File tree

standard/expressions.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3500,7 +3500,7 @@ A *default_value_expression* is a constant expression ([§12.26](expressions.md#
35003500
- one of the following value types: `sbyte`, `byte`, `short`, `ushort`, `int`, `uint`, `nint`, `nuint`, `long`, `ulong`, `char`, `float`, `double`, `decimal`, `bool`; or
35013501
- any enumeration type.
35023502

3503-
A reference variable field `rv` of type `T`, may not have an explicit initializer of `default`.
3503+
A reference variable field `rv` of type `T` shall not have an explicit initializer of `default`.
35043504

35053505
> *Note*: If one tries to initialize `rv` using `rv = default`, this does not set the reference variable to `null`. Instead, it attempts to set the value of the (possibly non-existent) referent to the default value for type `T`. *end note*
35063506
@@ -7348,9 +7348,7 @@ The operator `= ref` is called the ***ref assignment operator***. The expressio
73487348

73497349
The left operand shall be an expression that binds to a reference variable ([§9.7](variables.md#97-reference-variables-and-returns)), a reference parameter (other than `this`), an output parameter, an input parameter, or a discard. When the left operand is a discard, the right operand is evaluated but no variable reference is stored. Otherwise, the right operand shall be an expression that yields a *variable_reference* ([§9.5](variables.md#95-variable-references)) designating a value of the same type as the left operand.
73507350

7351-
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.
7352-
7353-
The left operand shall have the same safe-context as the right operand.
7351+
The ref-safe-context of the right operand shall be at least as wide as the ref-safe-context of the left operand, and the left operand shall have the same safe-context as the right operand (§9.7.2).
73547352

73557353
> *Note*: This requirement exists because the lifetime of the value pointed to by a ref location is invariant. The indirection prevents one from allowing any kind of variance here, even to narrower lifetimes. *end note*
73567354

standard/statements.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ For a discussion of `scoped`, see §scoped-modifier.
378378
> var orders = new Dictionary<int,Order>();
379379
> ref var j = ref i;
380380
> ref readonly var k = ref i;
381-
> scoped var r = new RS(); // ref struct RS {}
381+
> scoped var r = new RS(ref i); // ref struct RS { ref int Field; ... }
382382
> ```
383383
>
384384
> The implicitly typed local variable declarations above are precisely equivalent to the following explicitly typed declarations:
@@ -392,7 +392,7 @@ For a discussion of `scoped`, see §scoped-modifier.
392392
> Dictionary<int,Order> orders = new Dictionary<int,Order>();
393393
> ref int j = ref i;
394394
> ref readonly int k = ref i;
395-
> scoped RS r = new RS(); // ref struct RS {}
395+
> scoped RS r = new RS(ref i); // ref struct RS { ref int Field; ... }
396396
> ```
397397
>
398398
> The following are incorrect implicitly typed local variable declarations:

standard/structs.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,8 @@ struct_member_declaration
165165

166166
*fixed_size_buffer_declaration* ([§24.8.2](unsafe-code.md#2482-fixed-size-buffer-declarations)) is only available in unsafe code ([§24](unsafe-code.md#24-unsafe-code)).
167167

168+
> *Note*: A *struct_member_declaration* includes all *class_member_declaration* alternatives except *finalizer_declaration*, and adds *struct_field_declaration* which supports ref fields (§Ref-Fields). *end note*
169+
168170
Fields in structs support capabilities not supported in classes. See §Ref-Fields for details.
169171

170172
Except for the differences noted in [§16.5](structs.md#165-class-and-struct-differences), the descriptions of class members provided in [§15.3](classes.md#153-class-members) through [§15.12](classes.md#1512-static-constructors) apply to struct members as well.
@@ -794,7 +796,7 @@ readonly ref struct RoS
794796

795797
### 16.5.9 Constructors
796798

797-
A struct can declare instance constructors, with zero or more parameters. If a struct has no explicitly declared parameterless instance constructor, one is synthesized, with public accessibility, which always returns the value that results from setting all value type fields to their default value and all reference type fields to `null` ([§8.3.3](types.md#833-default-constructors)). In such a case, any instance field initializers are ignored when that constructor executes.
799+
A struct can declare instance constructors, with zero or more parameters. If a struct has no explicitly declared parameterless instance constructor, one is synthesized, with public accessibility, which always returns the value that results from setting all value type fields to their default value, all reference variable fields to null references, and all reference type fields to `null` ([§8.3.3](types.md#833-default-constructors)). In such a case, any instance field initializers are ignored when that constructor executes.
798800

799801
An explicitly declared parameterless instance constructor shall have public accessibility.
800802

standard/variables.md

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -200,9 +200,7 @@ The default value of a variable depends on the type of the variable and is deter
200200
201201
> *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*
202202
203-
To test if a ref variable has been assigned a referent, call `System.Runtime.CompilerServices.Unsafe.IsNullRef(ref fieldName)`.
204-
205-
> *Note*: One cannot test a ref variable to see if it has been assigned a referent, by using `fieldName == null`, as that tests the value of the (potentially non-existent) referent, not the reference itself. *end note*
203+
> *Note*: To test if a ref variable has been assigned a referent, call `System.Runtime.CompilerServices.Unsafe.IsNullRef(ref fieldName)`. One cannot test a ref variable to see if it has been assigned a referent by using `fieldName == null`, as that tests the value of the (potentially non-existent) referent, not the reference itself. *end note*
206204
207205
## 9.4 Definite assignment
208206
@@ -1350,7 +1348,7 @@ These values form a nesting relationship from narrowest (declaration-block) to w
13501348
>
13511349
> *end example.*
13521350
1353-
A reference variable can be scoped explicitly; see §scoped-modifier.
1351+
A reference variable that is a local variable or parameter can be scoped explicitly; see §scoped-modifier.
13541352
13551353
#### 9.7.2.2 Local variable ref safe context
13561354
@@ -1458,9 +1456,9 @@ A `new` expression that invokes a constructor obeys the same rules as a method i
14581456
14591457
### §scoped-modifier The scoped modifier
14601458
1461-
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 doesnt extend the lifetime of the variable.
1459+
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 doesnt extend the lifetime of the variable.
14621460
1463-
`scoped` shall only be applied to reference variables (which includes non-value parameters) and to variables of a ref struct type.
1461+
`scoped` shall only be applied to reference variables (which includes non-value parameters) and to variables of a ref struct type. `scoped` shall not be applied to fields, array elements, or return types.
14641462
14651463
Consider the following declarations and their safe contexts:
14661464
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
1-
public ref struct RS {}
1+
ref struct RS
2+
{
3+
public ref int Field;
4+
public RS(ref int i) { Field = ref i; }
5+
}

0 commit comments

Comments
 (0)