Skip to content

Commit a8a5e50

Browse files
Nigel-Ecmajskeet
authored andcommitted
Changes for ref-valued properties, indexers and methods
(This was originally in dotnet#837.) The grammar has been extended to be as prescriptive as reasonably possible as befits a language specification[1], this means that former statements such as it being illegal to have a set accessor for a ref-valued property are now covered by the grammar. However the usual verbose description of the grammar remains! The term ref-valued rather than ref-returning is used, a term closer to the language of fields. To distingush the two kinds of properties, which do follow different rules, the corresponding and somewhat ugly term non-ref-valued is used (non-ref-returning would be just as ugly). [1] The grammar used by a compiler may be less restrictive to support more descriptive error messages, that is of course an implementation issue! Fixes dotnet#825.
1 parent b50bce6 commit a8a5e50

File tree

7 files changed

+233
-89
lines changed

7 files changed

+233
-89
lines changed

standard/basic-concepts.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,7 @@ The ***scope*** of a name is the region of program text within which it is possi
588588
- The scope of a member declared by a *struct_member_declaration* ([§16.3](structs.md#163-struct-members)) is the *struct_body* in which the declaration occurs.
589589
590590
- The scope of a member declared by an *enum_member_declaration* ([§19.4](enums.md#194-enum-members)) is the *enum_body* in which the declaration occurs.
591-
- The scope of a parameter declared in a *method_declaration* ([§15.6](classes.md#156-methods)) is the *method_body* of that *method_declaration*.
591+
- The scope of a parameter declared in a *method_declaration* ([§15.6](classes.md#156-methods)) is the *method_body* or *ref_method_body* of that *method_declaration*.
592592
- The scope of a parameter declared in an *indexer_declaration* ([§15.9](classes.md#159-indexers)) is the *indexer_body* of that *indexer_declaration*.
593593
- The scope of a parameter declared in an *operator_declaration* ([§15.10](classes.md#1510-operators)) is the *operator_body* of that *operator_declaration*.
594594
- The scope of a parameter declared in a *constructor_declaration* ([§15.11](classes.md#1511-instance-constructors)) is the *constructor_initializer* and *block* of that *constructor_declaration*.

standard/classes.md

+175-57
Large diffs are not rendered by default.

standard/delegates.md

+18-9
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,33 @@ A *delegate_declaration* is a *type_declaration* ([§14.7](namespaces.md#147-typ
1212

1313
```ANTLR
1414
delegate_declaration
15-
: attributes? delegate_modifier* 'delegate' ('ref' 'readonly'?)? return_type identifier variant_type_parameter_list?
16-
'(' formal_parameter_list? ')' type_parameter_constraints_clause* ';'
15+
: attributes? delegate_modifier* 'delegate' return_type delegate_header
16+
| attributes? ref_delegate_modifier* 'delegate' ref_kind ref_return_type delegate_header
17+
;
18+
19+
delegate_header
20+
: identifier '(' formal_parameter_list? ')' ';'
21+
| identifier variant_type_parameter_list '(' formal_parameter_list? ')' type_parameter_constraints_clause* ';'
1722
;
1823
1924
delegate_modifier
25+
: ref_delegate_modifier
26+
| unsafe_modifier // unsafe code support
27+
;
28+
29+
ref_delegate_modifier
2030
: 'new'
2131
| 'public'
2232
| 'protected'
2333
| 'internal'
2434
| 'private'
25-
| unsafe_modifier // unsafe code support
2635
;
2736
```
2837

2938
*unsafe_modifier* is defined in [§23.2](unsafe-code.md#232-unsafe-contexts).
3039

3140
It is a compile-time error for the same modifier to appear multiple times in a delegate declaration.
3241

33-
A delegate declaration shall not supply any *type_parameter_constraints_clause*s unless it also supplies a *variant_type_parameter_list*.
34-
3542
A delegate declaration that supplies a *variant_type_parameter_list* is a generic delegate declaration. Additionally, any delegate nested inside a generic class declaration or a generic struct declaration is itself a generic delegate declaration, since type arguments for the containing type shall be supplied to create a constructed type ([§8.4](types.md#84-constructed-types)).
3643

3744
The `new` modifier is only permitted on delegates declared within another type, in which case it specifies that such a delegate hides an inherited member by the same name, as described in [§15.3.5](classes.md#1535-the-new-modifier).
@@ -40,11 +47,13 @@ The `public`, `protected`, `internal`, and `private` modifiers control the acces
4047

4148
The delegate’s type name is *identifier*.
4249

43-
As with methods ([§15.6.1](classes.md#1561-general)), if `ref` is present, the delegate returns-by-ref; otherwise, if *return_type* is `void`, the delegate returns-no-value; otherwise, the delegate returns-by-value. It is a compile-time error to have both `ref` and a *return_type* of `void`.
50+
As with methods ([§15.6.1](classes.md#1561-general)), if `ref` is present, the delegate returns-by-ref; otherwise, if *return_type* is `void`, the delegate returns-no-value; otherwise, the delegate returns-by-value.
4451

4552
The optional *formal_parameter_list* specifies the parameters of the delegate.
4653

47-
*return_type* indicates the return type of the delegate. The optional `ref` indicates that a *variable reference* ([§9.5](variables.md#95-variable-references)) is returned, with the optional `readonly` indicating that that variable is read-only.
54+
The *return_type* of a returns-by-value or returns-no-value delegate declaration specifies the type of the result, if any, returned by the delegate.
55+
56+
The *ref_return_type* of a returns-by-ref delegate declaration specifies the type of the variable referenced by the *variable_reference* ([§9.5](variables.md#95-variable-references)) returned by the delegate.
4857

4958
The optional *variant_type_parameter_list* ([§18.2.3](interfaces.md#1823-variant-type-parameter-lists)) specifies the type parameters to the delegate itself.
5059

@@ -76,7 +85,7 @@ The only way to declare a delegate type is via a *delegate_declaration*. Every d
7685
7786
## 20.3 Delegate members
7887
79-
Every delegate type inherits members from the `Delegate` class as described in [§15.3.4](classes.md#1534-inheritance). In addition, every delegate type must provide a non-generic `Invoke` method whose parameter list matches the *formal_parameter_list* in the delegate declaration, and whose return type matches the *return_type* in the delegate declaration. The `Invoke` method shall be at least as accessible as the containing delegate type. Calling the `Invoke` method on a delegate type is semantically equivalent to using the delegate invocation syntax ([§20.6](delegates.md#206-delegate-invocation)) .
88+
Every delegate type inherits members from the `Delegate` class as described in [§15.3.4](classes.md#1534-inheritance). In addition, every delegate type must provide a non-generic `Invoke` method whose parameter list matches the *formal_parameter_list* in the delegate declaration, whose return type matches the *return_type* or *ref_return_type* in the delegate declaration, and for returns-by-ref delegates whose *ref_kind* matches that in the delegate declaration. The `Invoke` method shall be at least as accessible as the containing delegate type. Calling the `Invoke` method on a delegate type is semantically equivalent to using the delegate invocation syntax ([§20.6](delegates.md#206-delegate-invocation)) .
8089
8190
Implementations may define additional members in the delegate type.
8291
@@ -92,7 +101,7 @@ A method or delegate type `M` is ***compatible*** with a delegate type `D` if al
92101
- One of the following is true:
93102
- `D` and `M` are both *returns-no-value*
94103
- `D` and `M` are returns-by-value ([§15.6.1](classes.md#1561-general), [§20.2](delegates.md#202-delegate-declarations)), and an identity or implicit reference conversion exists from the return type of `M` to the return type of `D`.
95-
- `D` and `M` are both returns-by-ref, and an identity conversion exists between the return type of `M` and the return type of `D`, and both have a *return_type* preceded by `ref readonly`, or both have a *return_type* preceded by `ref` only.
104+
- `D` and `M` are both returns-by-ref, an identity conversion exists between the return type of `M` and the return type of `D`, and both have the same *ref_kind*.
96105
97106
This definition of compatibility allows covariance in return type and contravariance in parameter types.
98107

standard/expressions.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -1539,7 +1539,7 @@ simple_name
15391539
A *simple_name* is either of the form `I` or of the form `I<A₁, ..., Aₑ>`, where `I` is a single identifier and `I<A₁, ..., Aₑ>` is an optional *type_argument_list*. When no *type_argument_list* is specified, consider `e` to be zero. The *simple_name* is evaluated and classified as follows:
15401540

15411541
- If `e` is zero and the *simple_name* appears within a local variable declaration space ([§7.3](basic-concepts.md#73-declarations)) that directly contains a local variable, parameter or constant with name `I`, then the *simple_name* refers to that local variable, parameter or constant and is classified as a variable or value.
1542-
- If `e` is zero and the *simple_name* appears within a generic method declaration but outside the *attributes* of its *method_header,* and if that declaration includes a type parameter with name `I`, then the *simple_name* refers to that type parameter.
1542+
- If `e` is zero and the *simple_name* appears within a generic method declaration but outside the *attributes* of its *method_declaration*, and if that declaration includes a type parameter with name `I`, then the *simple_name* refers to that type parameter.
15431543
- Otherwise, for each instance type `T` ([§15.3.2](classes.md#1532-the-instance-type)), starting with the instance type of the immediately enclosing type declaration and continuing with the instance type of each enclosing class or struct declaration (if any):
15441544
- If `e` is zero and the declaration of `T` includes a type parameter with name `I`, then the *simple_name* refers to that type parameter.
15451545
- Otherwise, if a member lookup ([§12.5](expressions.md#125-member-lookup)) of `I` in `T` with `e` type arguments produces a match:
@@ -4749,7 +4749,7 @@ The first operand of the `?:` operator shall be an expression that can be impli
47494749
If `ref` is present:
47504750

47514751
- An identity conversion must exist between the types of the two *variable_reference*s, and type of the result can be either type. If either type is `dynamic`, type inference prefers `dynamic` ([§8.7](types.md#87-the-dynamic-type)). If either type is a tuple type ([§8.3.11](types.md#8311-tuple-types)), type inference includes the element names when the element names in the same ordinal position match in both tuples.
4752-
- The result is a variable reference, which is writeable if both *variable_reference*s are writeable.
4752+
- The result is a variable reference, which is writeable if both *variable_reference*s are writeable.
47534753

47544754
> *Note*: When `ref` is present, the *conditional_expression* returns a variable reference, which can be assigned to a reference variable using the `= ref` operator or passed as a reference/input/output parameter. *end note*
47554755

standard/interfaces.md

+21-11
Original file line numberDiff line numberDiff line change
@@ -254,16 +254,21 @@ Interface methods are declared using *interface_method_declaration*s:
254254

255255
```ANTLR
256256
interface_method_declaration
257-
: attributes? 'new'? return_type identifier type_parameter_list?
258-
'(' formal_parameter_list? ')' type_parameter_constraints_clause* ';'
257+
: attributes? 'new'? return_type interface_method_header
258+
| attributes? 'new'? ref_kind ref_return_type interface_method_header
259+
;
260+
261+
interface_method_header
262+
: identifier '(' formal_parameter_list? ')' ';'
263+
| identifier type_parameter_list '(' formal_parameter_list? ')' type_parameter_constraints_clause* ';'
259264
;
260265
```
261266

262-
The *attributes*, *return_type*, *identifier*, and *formal_parameter_list* of an interface method declaration have the same meaning as those of a method declaration in a class ([§15.6](classes.md#156-methods)). An interface method declaration is not permitted to specify a method body, and the declaration therefore always ends with a semicolon. An *interface_method_declaration* shall not have *type_parameter_constraints_clause*s unless it also has a *type_parameter_list*.
267+
The *attributes*, *return_type*, *ref_return_type*, *identifier*, and *formal_parameter_list* of an interface method declaration have the same meaning as those of a method declaration in a class ([§15.6](classes.md#156-methods)). An interface method declaration is not permitted to specify a method body, and the declaration therefore always ends with a semicolon.
263268

264269
All formal parameter types of an interface method shall be input-safe ([§18.2.3.2](interfaces.md#18232-variance-safety)), and the return type shall be either `void` or output-safe. In addition, any output or reference formal parameter types shall also be output-safe.
265270

266-
> *Note*: Output parameters are required to be input-safe due to common implementation restrictions. *end note*
271+
> *Note*: Output parameters are required to be input-safe due to common implementation restrictions. *end note*
267272
268273
Furthermore, each class type constraint, interface type constraint and type parameter constraint on any type parameters of the method shall be input-safe.
269274

@@ -313,21 +318,24 @@ Interface properties are declared using *interface_property_declaration*s:
313318
```ANTLR
314319
interface_property_declaration
315320
: attributes? 'new'? type identifier '{' interface_accessors '}'
321+
| attributes? 'new'? ref_kind type identifier '{' ref_interface_accessor '}'
316322
;
317-
```
318323
319-
```ANTLR
320324
interface_accessors
321325
: attributes? 'get' ';'
322326
| attributes? 'set' ';'
323327
| attributes? 'get' ';' attributes? 'set' ';'
324328
| attributes? 'set' ';' attributes? 'get' ';'
325329
;
330+
331+
ref_interface_accessor
332+
: attributes? 'get' ';'
333+
;
326334
```
327335
328336
The *attributes*, *type*, and *identifier* of an interface property declaration have the same meaning as those of a property declaration in a class ([§15.7](classes.md#157-properties)).
329337

330-
The accessors of an interface property declaration correspond to the accessors of a class property declaration ([§15.7.3](classes.md#1573-accessors)), except that the accessor body shall always be a semicolon. Thus, the accessors simply indicate whether the property is read-write, read-only, or write-only.
338+
The accessors of an interface property declaration correspond to the accessors of a class property declaration ([§15.7.3](classes.md#1573-accessors)), except that the *accessor_body* shall always be a semicolon. Thus, the accessors simply indicate whether the property is read-write, read-only, or write-only.
331339

332340
The type of an interface property shall be output-safe if there is a get accessor, and shall be input-safe if there is a set accessor.
333341

@@ -350,15 +358,17 @@ The type of an interface event shall be input-safe.
350358
Interface indexers are declared using *interface_indexer_declaration*s:
351359

352360
```ANTLR
353-
interface_indexer_declaration:
354-
attributes? 'new'? type 'this' '[' formal_parameter_list ']'
355-
'{' interface_accessors '}'
361+
interface_indexer_declaration
362+
: attributes? 'new'? type 'this' '[' formal_parameter_list ']'
363+
'{' interface_accessors '}'
364+
| attributes? 'new'? ref_kind type 'this' '[' formal_parameter_list ']'
365+
'{' ref_interface_accessor '}'
356366
;
357367
```
358368

359369
The *attributes*, *type*, and *formal_parameter_list* of an interface indexer declaration have the same meaning as those of an indexer declaration in a class ([§15.9](classes.md#159-indexers)).
360370

361-
The accessors of an interface indexer declaration correspond to the accessors of a class indexer declaration ([§15.9](classes.md#159-indexers)), except that the accessor body shall always be a semicolon. Thus, the accessors simply indicate whether the indexer is read-write, read-only, or write-only.
371+
The accessors of an interface indexer declaration correspond to the accessors of a class indexer declaration ([§15.9](classes.md#159-indexers)), except that the *accessor_body* shall always be a semicolon. Thus, the accessors simply indicate whether the indexer is read-write, read-only, or write-only.
362372

363373
All the formal parameter types of an interface indexer shall be input-safe ([§18.2.3.2](interfaces.md#18232-variance-safety)). In addition, any output or reference formal parameter types shall also be output-safe.
364374

standard/lexical-structure.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1297,7 +1297,7 @@ Conditional compilation directives shall be written in groups consisting of, in
12971297

12981298
At most one of the contained conditional sections is selected for normal lexical processing:
12991299

1300-
- The *PP_Expression*s of the `#if` and `#elif` directives are evaluated in order until one yields `true`. If an expression yields `true`, the conditional section following the corresponding directive is selected.
1300+
- The *PP_Expression*s of the `#if` and `#elif` directives are evaluated in order until one yields `true`. If an expression yields `true`, the conditional section following the corresponding directive is selected.
13011301
- If all *PP_Expression*s yield `false`, and if a `#else` directive is present, the conditional section following the `#else` directive is selected.
13021302
- Otherwise, no conditional section is selected.
13031303

0 commit comments

Comments
 (0)