From 6997fb00b6f93a3ef910bc1fc3bd920f41253bf7 Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Sun, 27 Nov 2022 11:29:58 -0500 Subject: [PATCH 01/11] allow readonly modifier in some members' grammar --- standard/classes.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/standard/classes.md b/standard/classes.md index 70cb2b229..53ec2413c 100644 --- a/standard/classes.md +++ b/standard/classes.md @@ -2094,6 +2094,7 @@ ref_method_modifier | 'override' | 'abstract' | 'extern' + | 'readonly' | 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)), `async` ([§15.15](classes.md#1515-async-functions)), and `readonly` modifiers. However, it is a compile-time error for the *method_modifier* `readonly` to be used in a *method_declaration* that is not contained directly by a *struct_declaration* (§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' | 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)), `extern` ([§15.6.8](classes.md#1468-external-methods)), and `readonly` modifiers. However, it is a compile-time error for the *property_modifier* `readonly` to be used in a *property_declaration* that is not contained directly by a *struct_declaration* (([§15.4.11](structs.md#16411-properties)). - 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' ; 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. +- It is a compile-time error for the *accessor_modifier* `readonly` to be used in a *property_declaration* or *indexer_declaration* that is not contained directly by a *struct_declaration* (§cands-diffs-properties, §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' | 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)), `extern` ([§15.6.8](classes.md#1568-external-methods)), and `readonly` modifiers. However, it is a compile-time error for the *event_modifier* `readonly` to be used in an *event_declaration* that is not contained directly by a *struct_declaration* (§cands-diffs-events). 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' | 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)), `extern` ([§15.6.8](classes.md#1568-external-methods)), and `readonly` modifiers. However, it is a compile-time error for the *indexer_modifier* `readonly` to be used in an *indexer_declaration* that is not contained directly by a *struct_declaration* (§cands-diffs-indexers). - 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. From 8adf4905126c9332180ffbfa0ab475b1bb3c2f19 Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Sun, 27 Nov 2022 11:42:02 -0500 Subject: [PATCH 02/11] Add support for readonly members in structs --- standard/structs.md | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/standard/structs.md b/standard/structs.md index de8126882..cf70afe0d 100644 --- a/standard/structs.md +++ b/standard/structs.md @@ -154,6 +154,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. +- Some kinds of members in structs 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 +403,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. @@ -502,6 +505,48 @@ Automatically implemented properties ([§15.7.4](classes.md#1574-automatically-i > *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* +A *property_declaration* ([§14.7.1](classes.md#1471-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 for a property to have a `readonly` modifier on both the `get` and the `set` accessors. + +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. + +If the `get` accessor has a `readonly` modifier, the `set` shall exist and shall not have that modifier. + +### §cands-diffs-methods Methods + +A *method_declaration* ([§14.6.1](classes.md#1461-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. + +### §cands-diffs-indexers Indexers + +An *indexer_declaration* ([§14.9](classes.md#149-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 both the `get` and the `set` accessors. + +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. + +If the `get` accessor has a `readonly` modifier, the `set` shall exist and shall not have that modifier. + +### §cands-diffs-events Events + +An *event_declaration* ([§14.8.1](classes.md#1481-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 From 4042ebb477bdf986629d75d46718b443fcc9a0da Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Sun, 27 Nov 2022 11:49:44 -0500 Subject: [PATCH 03/11] Update classes.md --- standard/classes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/classes.md b/standard/classes.md index 53ec2413c..b3a211db7 100644 --- a/standard/classes.md +++ b/standard/classes.md @@ -3395,7 +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. -- It is a compile-time error for the *accessor_modifier* `readonly` to be used in a *property_declaration* or *indexer_declaration* that is not contained directly by a *struct_declaration* (§cands-diffs-properties, §cands-diffs-indexers). +- It is a compile-time error for the *accessor_modifier* `readonly` to be used in a *property_declaration* or *indexer_declaration* that is not contained directly by a *struct_declaration* (§cands-diffs-properties, §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: From 1fbab5d07ae2787bd5e1229b128d2ae15da87fbe Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Sun, 27 Nov 2022 12:05:33 -0500 Subject: [PATCH 04/11] mention partial and readonly --- standard/structs.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/standard/structs.md b/standard/structs.md index cf70afe0d..5a2146774 100644 --- a/standard/structs.md +++ b/standard/structs.md @@ -531,6 +531,8 @@ Although a readonly method may call a sibling, non-readonly method, or property 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* ([§14.9](classes.md#149-indexers)) for an instance indexer in a *struct_declaration* may contain the *indexer_modifier* `readonly`. From 9a4faeaf1129ba6cb94b9633d220e1c45b4380fe Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Tue, 26 Sep 2023 10:07:15 -0400 Subject: [PATCH 05/11] section renumber fixes, link fixes --- standard/classes.md | 4 ++-- standard/structs.md | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/standard/classes.md b/standard/classes.md index b3a211db7..4efca2b78 100644 --- a/standard/classes.md +++ b/standard/classes.md @@ -3303,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)). -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)), `extern` ([§15.6.8](classes.md#1468-external-methods)), and `readonly` modifiers. However, it is a compile-time error for the *property_modifier* `readonly` to be used in a *property_declaration* that is not contained directly by a *struct_declaration* (([§15.4.11](structs.md#16411-properties)). +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)), `extern` ([§15.6.8](classes.md#1568-external-methods)), and `readonly` modifiers. However, it is a compile-time error for the *property_modifier* `readonly` to be used in a *property_declaration* that is not contained directly by a *struct_declaration* (([§16.4.11](structs.md#16411-automatically-implemented-properties)). - 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. @@ -3395,7 +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. -- It is a compile-time error for the *accessor_modifier* `readonly` to be used in a *property_declaration* or *indexer_declaration* that is not contained directly by a *struct_declaration* (§cands-diffs-properties, §cands-diffs-indexers). +- It is a compile-time error for the *accessor_modifier* `readonly` to be used in a *property_declaration* or *indexer_declaration* that is not 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: diff --git a/standard/structs.md b/standard/structs.md index 5a2146774..719c5e17e 100644 --- a/standard/structs.md +++ b/standard/structs.md @@ -505,7 +505,7 @@ Automatically implemented properties ([§15.7.4](classes.md#1574-automatically-i > *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* -A *property_declaration* ([§14.7.1](classes.md#1471-general)) for an instance property in a *struct_declaration* may contain the *property_modifier* `readonly`. However, a static property shall not contain that modifier. +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. @@ -523,7 +523,7 @@ If the `get` accessor has a `readonly` modifier, the `set` shall exist and shall ### §cands-diffs-methods Methods -A *method_declaration* ([§14.6.1](classes.md#1461-general)) for an instance method in a *struct_declaration* may contain the *method_modifier* `readonly`. However, a static method shall not contain that modifier. +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. @@ -535,7 +535,7 @@ All *method_declaration*s of a partial method shall have a `readonly` modifier, ### §cands-diffs-indexers Indexers -An *indexer_declaration* ([§14.9](classes.md#149-indexers)) for an instance indexer in a *struct_declaration* may contain the *indexer_modifier* `readonly`. +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. @@ -547,7 +547,7 @@ If the `get` accessor has a `readonly` modifier, the `set` shall exist and shall ### §cands-diffs-events Events -An *event_declaration* ([§14.8.1](classes.md#1481-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. +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 From e58cbcd9f0dc557b40072588eefce53fbb25d012 Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Thu, 12 Oct 2023 16:22:35 -0400 Subject: [PATCH 06/11] remove constraint --- standard/structs.md | 1 - 1 file changed, 1 deletion(-) diff --git a/standard/structs.md b/standard/structs.md index 719c5e17e..65f9c67b5 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). From f18083f58cd810944bd4f22c966f2c74d0eca62a Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Wed, 14 May 2025 21:29:12 +0100 Subject: [PATCH 07/11] Update standard/classes.md Co-authored-by: Nigel-Ecma <6654683+Nigel-Ecma@users.noreply.github.com> --- standard/classes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/classes.md b/standard/classes.md index 4efca2b78..9352176f6 100644 --- a/standard/classes.md +++ b/standard/classes.md @@ -2133,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)), `async` ([§15.15](classes.md#1515-async-functions)), and `readonly` modifiers. However, it is a compile-time error for the *method_modifier* `readonly` to be used in a *method_declaration* that is not contained directly by a *struct_declaration* (§cands-diffs-methods). +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: From 62ff34d002f58b1ce099779bce1d51dce70ce8d0 Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Wed, 14 May 2025 16:32:58 -0400 Subject: [PATCH 08/11] Apply suggestions from code review Co-authored-by: Nigel-Ecma <6654683+Nigel-Ecma@users.noreply.github.com> --- standard/classes.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/standard/classes.md b/standard/classes.md index 9352176f6..a77d22e5b 100644 --- a/standard/classes.md +++ b/standard/classes.md @@ -2094,7 +2094,7 @@ ref_method_modifier | 'override' | 'abstract' | 'extern' - | 'readonly' + | 'readonly' // direct struct members only | unsafe_modifier // unsafe code support ; @@ -3282,7 +3282,7 @@ property_modifier | 'override' | 'abstract' | 'extern' - | 'readonly' + | 'readonly' // direct struct members only | unsafe_modifier // unsafe code support ; @@ -3368,7 +3368,7 @@ accessor_modifier | 'internal' 'protected' | 'protected' 'private' | 'private' 'protected' - | 'readonly' + | 'readonly' // direct struct members only ; accessor_body @@ -4028,7 +4028,7 @@ event_modifier | 'override' | 'abstract' | 'extern' - | 'readonly' + | 'readonly' // direct struct members only | unsafe_modifier // unsafe code support ; @@ -4309,7 +4309,7 @@ indexer_modifier | 'override' | 'abstract' | 'extern' - | 'readonly' + | 'readonly' // direct struct members only | unsafe_modifier // unsafe code support ; From 9c2e4f3828c97c4bd0bfc48a9e4eb2c998eb38f9 Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Tue, 3 Jun 2025 14:27:44 -0400 Subject: [PATCH 09/11] Apply suggestions from code review Co-authored-by: Nigel-Ecma <6654683+Nigel-Ecma@users.noreply.github.com> Co-authored-by: Jon Skeet --- standard/classes.md | 8 ++++---- standard/structs.md | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/standard/classes.md b/standard/classes.md index a77d22e5b..91c0e8497 100644 --- a/standard/classes.md +++ b/standard/classes.md @@ -3303,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)). -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)), `extern` ([§15.6.8](classes.md#1568-external-methods)), and `readonly` modifiers. However, it is a compile-time error for the *property_modifier* `readonly` to be used in a *property_declaration* that is not contained directly by a *struct_declaration* (([§16.4.11](structs.md#16411-automatically-implemented-properties)). +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 (§cands-diffs-methods). - 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. @@ -3395,7 +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. -- It is a compile-time error for the *accessor_modifier* `readonly` to be used in a *property_declaration* or *indexer_declaration* that is not contained directly by a *struct_declaration* (§16.4.11, §cands-diffs-indexers). +- 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: @@ -4048,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)), `extern` ([§15.6.8](classes.md#1568-external-methods)), and `readonly` modifiers. However, it is a compile-time error for the *event_modifier* `readonly` to be used in an *event_declaration* that is not contained directly by a *struct_declaration* (§cands-diffs-events). +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. @@ -4331,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)). -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)), `extern` ([§15.6.8](classes.md#1568-external-methods)), and `readonly` modifiers. However, it is a compile-time error for the *indexer_modifier* `readonly` to be used in an *indexer_declaration* that is not contained directly by a *struct_declaration* (§cands-diffs-indexers). +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 65f9c67b5..bf00d2751 100644 --- a/standard/structs.md +++ b/standard/structs.md @@ -153,7 +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. -- Some kinds of members in structs are permitted to have the modifier `readonly` while that is not generally permitted for those same member kinds in classes. +- 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 From 7bec950a74d5a1977d4731fcd7e61744f0268026 Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Tue, 3 Jun 2025 15:00:12 -0400 Subject: [PATCH 10/11] Make updates based on May meeting Apply suggestions and edit recommendations from the May meeting. --- standard/structs.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/standard/structs.md b/standard/structs.md index bf00d2751..716a5c92a 100644 --- a/standard/structs.md +++ b/standard/structs.md @@ -518,7 +518,9 @@ It is a compile-time error for a property to have a `readonly` modifier on both 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. -If the `get` accessor has a `readonly` modifier, the `set` shall exist and shall not have that modifier. +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* ### §cands-diffs-methods Methods @@ -542,7 +544,9 @@ It is a compile-time error to have a `readonly` modifier on both the `get` and t 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. -If the `get` accessor has a `readonly` modifier, the `set` shall exist and shall not have that modifier. +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 From fa8542a7347c8a79214ffd502895ff7bc4e8570a Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Tue, 3 Jun 2025 15:09:18 -0400 Subject: [PATCH 11/11] Address struct and property diffs for `readonly` See https://github.com/dotnet/csharpstandard/pull/673#discussion_r2120395758 --- standard/classes.md | 2 +- standard/structs.md | 14 +++++--------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/standard/classes.md b/standard/classes.md index 91c0e8497..600a798b6 100644 --- a/standard/classes.md +++ b/standard/classes.md @@ -3303,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)). -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 (§cands-diffs-methods). +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. diff --git a/standard/structs.md b/standard/structs.md index 716a5c92a..487b79723 100644 --- a/standard/structs.md +++ b/standard/structs.md @@ -498,11 +498,7 @@ 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 - -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* +### 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. @@ -514,14 +510,16 @@ It is a compile-time error for an automatically implemented property in a `reado 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 for a property to have a `readonly` modifier on both the `get` and the `set` accessors. - 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. @@ -540,8 +538,6 @@ An *indexer_declaration* ([§15.9](classes.md#159-indexers)) for an instance ind 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 both the `get` and the `set` accessors. - 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.