diff --git a/standard/classes.md b/standard/classes.md index 70cb2b229..600a798b6 100644 --- a/standard/classes.md +++ b/standard/classes.md @@ -2094,6 +2094,7 @@ ref_method_modifier | 'override' | 'abstract' | 'extern' + | 'readonly' // direct struct members only | unsafe_modifier // unsafe code support ; @@ -2132,7 +2133,7 @@ Grammar notes: > *Note*: The overlapping of, and priority between, alternatives here is solely for descriptive convenience; the grammar rules could be elaborated to remove the overlap. ANTLR, and other grammar systems, adopt the same convenience and so *method_body* has the specified semantics automatically. *end note* -A *method_declaration* may include a set of *attributes* ([§22](attributes.md#22-attributes)) and one of the permitted kinds of declared accessibility ([§15.3.6](classes.md#1536-access-modifiers)), the `new` ([§15.3.5](classes.md#1535-the-new-modifier)), `static` ([§15.6.3](classes.md#1563-static-and-instance-methods)), `virtual` ([§15.6.4](classes.md#1564-virtual-methods)), `override` ([§15.6.5](classes.md#1565-override-methods)), `sealed` ([§15.6.6](classes.md#1566-sealed-methods)), `abstract` ([§15.6.7](classes.md#1567-abstract-methods)), `extern` ([§15.6.8](classes.md#1568-external-methods)) and `async` ([§15.15](classes.md#1515-async-functions)) modifiers. +A *method_declaration* may include a set of *attributes* ([§22](attributes.md#22-attributes)) and one of the permitted kinds of declared accessibility ([§15.3.6](classes.md#1536-access-modifiers)), the `new` ([§15.3.5](classes.md#1535-the-new-modifier)), `static` ([§15.6.3](classes.md#1563-static-and-instance-methods)), `virtual` ([§15.6.4](classes.md#1564-virtual-methods)), `override` ([§15.6.5](classes.md#1565-override-methods)), `sealed` ([§15.6.6](classes.md#1566-sealed-methods)), `abstract` ([§15.6.7](classes.md#1567-abstract-methods)), `extern` ([§15.6.8](classes.md#1568-external-methods)) and `async` ([§15.15](classes.md#1515-async-functions)). Additionally a *method_declaration* that is contained directly by a *struct_declaration* may include the `readonly` modifier (§cands-diffs-methods). A declaration has a valid combination of modifiers if all of the following are true: @@ -3281,6 +3282,7 @@ property_modifier | 'override' | 'abstract' | 'extern' + | 'readonly' // direct struct members only | unsafe_modifier // unsafe code support ; @@ -3301,7 +3303,7 @@ ref_property_body *unsafe_modifier* ([§23.2](unsafe-code.md#232-unsafe-contexts)) is only available in unsafe code ([§23](unsafe-code.md#23-unsafe-code)). -There are two kinds of *property_declaration*: +A *property_declaration* may include a set of *attributes* ([§22](attributes.md#22-attributes)) and any one of the permitted kinds of declared accessibility ([§15.3.6](classes.md#1536-access-modifiers)), the `new` ([§15.3.5](classes.md#1535-the-new-modifier)), `static` ([§15.7.2](classes.md#1572-static-and-instance-properties)), `virtual` ([§15.6.4](classes.md#1564-virtual-methods), [§15.7.6](classes.md#1576-virtual-sealed-override-and-abstract-accessors)), `override` ([§15.6.5](classes.md#1565-override-methods), [§15.7.6](classes.md#1576-virtual-sealed-override-and-abstract-accessors)), `sealed` ([§15.6.6](classes.md#1566-sealed-methods)), `abstract` ([§15.6.7](classes.md#1567-abstract-methods), [§15.7.6](classes.md#1576-virtual-sealed-override-and-abstract-accessors)) and `extern` ([§15.6.8](classes.md#1568-external-methods)). Additionally a *property_declaration* that is contained directly by a *struct_declaration* may include the `readonly` modifier (§16.4.11). - The first declares a non-ref-valued property. Its value has type *type*. This kind of property may be readable and/or writeable. - The second declares a ref-valued property. Its value is a *variable_reference* ([§9.5](variables.md#95-variable-references)), that may be `readonly`, to a variable of type *type*. This kind of property is only readable. @@ -3366,6 +3368,7 @@ accessor_modifier | 'internal' 'protected' | 'protected' 'private' | 'private' 'protected' + | 'readonly' // direct struct members only ; accessor_body @@ -3392,6 +3395,7 @@ For a ref-valued property the *ref_get_accessor_declaration* consists optional a The use of *accessor_modifier*s is governed by the following restrictions: - An *accessor_modifier* shall not be used in an interface or in an explicit interface member implementation. +- The *accessor_modifier* `readonly` is permitted only in a *property_declaration* or *indexer_declaration* that is contained directly by a *struct_declaration* (§16.4.11, §cands-diffs-indexers). - For a property or indexer that has no `override` modifier, an *accessor_modifier* is permitted only if the property or indexer has both a get and set accessor, and then is permitted only on one of those accessors. - For a property or indexer that includes an `override` modifier, an accessor shall match the *accessor_modifier*, if any, of the accessor being overridden. - The *accessor_modifier* shall declare an accessibility that is strictly more restrictive than the declared accessibility of the property or indexer itself. To be precise: @@ -4024,6 +4028,7 @@ event_modifier | 'override' | 'abstract' | 'extern' + | 'readonly' // direct struct members only | unsafe_modifier // unsafe code support ; @@ -4043,7 +4048,7 @@ remove_accessor_declaration *unsafe_modifier* ([§23.2](unsafe-code.md#232-unsafe-contexts)) is only available in unsafe code ([§23](unsafe-code.md#23-unsafe-code)). -An *event_declaration* may include a set of *attributes* ([§22](attributes.md#22-attributes)) and any one of the permitted kinds of declared accessibility ([§15.3.6](classes.md#1536-access-modifiers)), the `new` ([§15.3.5](classes.md#1535-the-new-modifier)), `static` ([§15.6.3](classes.md#1563-static-and-instance-methods), [§15.8.4](classes.md#1584-static-and-instance-events)), `virtual` ([§15.6.4](classes.md#1564-virtual-methods), [§15.8.5](classes.md#1585-virtual-sealed-override-and-abstract-accessors)), `override` ([§15.6.5](classes.md#1565-override-methods), [§15.8.5](classes.md#1585-virtual-sealed-override-and-abstract-accessors)), `sealed` ([§15.6.6](classes.md#1566-sealed-methods)), `abstract` ([§15.6.7](classes.md#1567-abstract-methods), [§15.8.5](classes.md#1585-virtual-sealed-override-and-abstract-accessors)), and `extern` ([§15.6.8](classes.md#1568-external-methods)) modifiers. +An *event_declaration* may include a set of *attributes* ([§22](attributes.md#22-attributes)) and any one of the permitted kinds of declared accessibility ([§15.3.6](classes.md#1536-access-modifiers)), the `new` ([§15.3.5](classes.md#1535-the-new-modifier)), `static` ([§15.6.3](classes.md#1563-static-and-instance-methods), [§15.8.4](classes.md#1584-static-and-instance-events)), `virtual` ([§15.6.4](classes.md#1564-virtual-methods), [§15.8.5](classes.md#1585-virtual-sealed-override-and-abstract-accessors)), `override` ([§15.6.5](classes.md#1565-override-methods), [§15.8.5](classes.md#1585-virtual-sealed-override-and-abstract-accessors)), `sealed` ([§15.6.6](classes.md#1566-sealed-methods)), `abstract` ([§15.6.7](classes.md#1567-abstract-methods), [§15.8.5](classes.md#1585-virtual-sealed-override-and-abstract-accessors)) and `extern` ([§15.6.8](classes.md#1568-external-methods)) modifiers. Additionally an *event_declaration* that is contained directly by a *struct_declaration* may include the `readonly` modifier (§cands-diffs-methods). Event declarations are subject to the same rules as method declarations ([§15.6](classes.md#156-methods)) with regard to valid combinations of modifiers. @@ -4304,6 +4309,7 @@ indexer_modifier | 'override' | 'abstract' | 'extern' + | 'readonly' // direct struct members only | unsafe_modifier // unsafe code support ; @@ -4325,7 +4331,7 @@ ref_indexer_body *unsafe_modifier* ([§23.2](unsafe-code.md#232-unsafe-contexts)) is only available in unsafe code ([§23](unsafe-code.md#23-unsafe-code)). -There are two kinds of *indexer_declaration*: +An *indexer_declaration* may include a set of *attributes* ([§22](attributes.md#22-attributes)) and any one of the permitted kinds of declared accessibility ([§15.3.6](classes.md#1536-access-modifiers)), the `new` ([§15.3.5](classes.md#1535-the-new-modifier)), `virtual` ([§15.6.4](classes.md#1564-virtual-methods)), `override` ([§15.6.5](classes.md#1565-override-methods)), `sealed` ([§15.6.6](classes.md#1566-sealed-methods)), `abstract` ([§15.6.7](classes.md#1567-abstract-methods)) and `extern` ([§15.6.8](classes.md#1568-external-methods)) modifiers. Additionally an *indexer_declaration* that is contained directly by a *struct_declaration* may include the `readonly` modifier (§cands-diffs-methods). - The first declares a non-ref-valued indexer. Its value has type *type*. This kind of indexer may be readable and/or writeable. - The second declares a ref-valued indexer. Its value is a *variable_reference* ([§9.5](variables.md#95-variable-references)), that may be `readonly`, to a variable of type *type*. This kind of indexer is only readable. diff --git a/standard/structs.md b/standard/structs.md index de8126882..487b79723 100644 --- a/standard/structs.md +++ b/standard/structs.md @@ -57,7 +57,6 @@ The `readonly` modifier indicates that the *struct_declaration* declares a type A readonly struct has the following constraints: - Each of its instance fields shall also be declared `readonly`. -- None of its instance properties shall have a *set_accessor_declaration* ([§15.7.3](classes.md#1573-accessors)). - It shall not declare any field-like events ([§15.8.2](classes.md#1582-field-like-events)). When an instance of a readonly struct is passed to a method, its `this` is treated like an input argument/parameter, which disallows write access to any instance fields (except by constructors). @@ -154,6 +153,7 @@ Structs differ from classes in several important ways: - Instance field declarations for a struct are not permitted to include variable initializers ([§16.4.8](structs.md#1648-field-initializers)). - A struct is not permitted to declare a parameterless instance constructor ([§16.4.9](structs.md#1649-constructors)). - A struct is not permitted to declare a finalizer. +- Event declarations, property declarations, property accessors, indexer declarations, and method declarations are permitted to have the modifier `readonly` while that is not generally permitted for those same member kinds in classes. ### 16.4.2 Value semantics @@ -402,6 +402,8 @@ As described in [§16.4.5](structs.md#1645-default-values), the default value of > > *end example* +A *field_declaration* declared directly inside a *struct_declaration* having the *struct_modifier* `readonly` shall have the *field_modifier* `readonly`. + ### 16.4.9 Constructors Unlike a class, a struct is not permitted to declare a parameterless instance constructor. Instead, every struct implicitly has a parameterless instance constructor, 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)). A struct can declare instance constructors having parameters. @@ -496,12 +498,56 @@ Static constructors for structs follow most of the same rules as for classes. Th > *Note*: The creation of default values ([§16.4.5](structs.md#1645-default-values)) of struct types does not trigger the static constructor. (An example of this is the initial value of elements in an array.) *end note* -### 16.4.11 Automatically implemented properties +### 16.4.11 Properties + +A *property_declaration* ([§15.7.1](classes.md#1571-general)) for an instance property in a *struct_declaration* may contain the *property_modifier* `readonly`. However, a static property shall not contain that modifier. + +It is a compile-time error to attempt to modify the state of an instance struct variable via a readonly property declared in that struct. + +It is a compile-time error for an automatically implemented property having a `readonly` modifier, to also have a `set` accessor. + +It is a compile-time error for an automatically implemented property in a `readonly` struct to have a `set` accessor. + +An automatically implemented property declared inside a `readonly` struct need not have a `readonly` modifier, as its `get` accessor is implicitly assumed to be readonly. + +It is a compile-time error to have a `readonly` modifier on a property itself as well as on either of its `get` and `set` accessors. + +It is a compile-time error for a property to have a readonly modifier on all of its accessors. + +> *Note*: To correct the error, move the modifier from the accessors to the property itself. *end note* Automatically implemented properties ([§15.7.4](classes.md#1574-automatically-implemented-properties)) use hidden backing fields, which are only accessible to the property accessors. > *Note*: This access restriction means that constructors in structs containing automatically implemented properties often need an explicit constructor initializer where they would not otherwise need one, to satisfy the requirement of all fields being definitely assigned before any function member is invoked or the constructor returns. *end note* +### §cands-diffs-methods Methods + +A *method_declaration* ([§15.6.1](classes.md#1561-general)) for an instance method in a *struct_declaration* may contain the *method_modifier* `readonly`. However, a static method shall not contain that modifier. + +It is a compile-time error to attempt to modify the state of an instance struct variable via a readonly method declared in that struct. + +Although a readonly method may call a sibling, non-readonly method, or property or indexer get accessor, doing so results in the creation of an implicit copy of `this` as a defensive measure. + +A readonly method may call a sibling property or indexer set accessor that is readonly. If a sibling member’s accessor is not explicitly or implicitly readonly, a compile-error occurs. + +All *method_declaration*s of a partial method shall have a `readonly` modifier, or none of them shall have it. + +### §cands-diffs-indexers Indexers + +An *indexer_declaration* ([§15.9](classes.md#159-indexers)) for an instance indexer in a *struct_declaration* may contain the *indexer_modifier* `readonly`. + +It is a compile-time error to attempt to modify the state of an instance struct variable via a readonly indexer declared in that struct. + +It is a compile-time error to have a `readonly` modifier on an indexer itself as well as on either of its `get` or `set` accessors. + +It is a compile-time error for an indexer to have a readonly modifier on all of its accessors. + +> *Note*: To correct the error, move the modifier from the accessors to the indexer itself. *end note* + +### §cands-diffs-events Events + +An *event_declaration* ([§15.8.1](classes.md#1581-general)) for an instance, non-field-like event in a *struct_declaration* may contain the *event_modifier* `readonly`. However, a static event shall not contain that modifier. + ### 16.4.12 Safe context constraint #### 16.4.12.1 General