diff --git a/standard/README.md b/standard/README.md index d414ddba4..cfa83a50a 100644 --- a/standard/README.md +++ b/standard/README.md @@ -237,8 +237,6 @@ - [§10.2.19](conversions.md#10219-implicit-object-creation-conversions) Implicit object-creation conversions - [§10.2.20](conversions.md#10220-implicit-conditional-expression-conversions) Implicit conditional expression conversions - [§10.2.21](conversions.md#10221-anonymous-function-type-conversion) Anonymous function type conversion - - [§10.2.22](conversions.md#10222-implicit-collection-expression-conversions) Implicit collection expression conversions - - [§10.2.23](conversions.md#10223-implicit-inline-array-conversions) Implicit inline array conversions - [§10.3](conversions.md#103-explicit-conversions) Explicit conversions - [§10.3.1](conversions.md#1031-general) General - [§10.3.2](conversions.md#1032-explicit-numeric-conversions) Explicit numeric conversions @@ -369,9 +367,8 @@ - [§12.8.12](expressions.md#12812-element-access) Element access - [§12.8.12.1](expressions.md#128121-general) General - [§12.8.12.2](expressions.md#128122-array-access) Array access - - [§12.8.12.3](expressions.md#128123-inline-array-element-access) Inline array element access - - [§12.8.12.4](expressions.md#128124-string-access) String access - - [§12.8.12.5](expressions.md#128125-indexer-access) Indexer access + - [§12.8.12.3](expressions.md#128123-string-access) String access + - [§12.8.12.4](expressions.md#128124-indexer-access) Indexer access - [§12.8.13](expressions.md#12813-null-conditional-element-access) Null Conditional Element Access - [§12.8.14](expressions.md#12814-this-access) This access - [§12.8.15](expressions.md#12815-base-access) Base access @@ -392,7 +389,6 @@ - [§12.8.22](expressions.md#12822-stack-allocation) Stack allocation - [§12.8.23](expressions.md#12823-the-nameof-operator) The nameof operator - [§12.8.24](expressions.md#12824-anonymous-method-expressions) Anonymous method expressions - - [§12.8.25](expressions.md#12825-collection-expressions) Collection expressions - [§12.9](expressions.md#129-unary-operators) Unary operators - [§12.9.1](expressions.md#1291-general) General - [§12.9.2](expressions.md#1292-unary-plus-operator) Unary plus operator @@ -662,7 +658,6 @@ - [§15.11.3](classes.md#15113-instance-variable-initializers) Instance variable initializers - [§15.11.4](classes.md#15114-constructor-execution) Constructor execution - [§15.11.5](classes.md#15115-default-constructors) Default constructors - - [§15.11.6](classes.md#15116-primary-constructors) Primary constructors - [§15.12](classes.md#1512-static-constructors) Static constructors - [§15.13](classes.md#1513-finalizers) Finalizers - [§15.14](classes.md#1514-async-functions) Async Functions @@ -685,23 +680,22 @@ - [§15.15.6.2](classes.md#151562-the-getenumerator-or-getasyncenumerator-method) The GetEnumerator or GetAsyncEnumerator method - [§15.16](classes.md#1516-record-classes) Record classes - [§15.16.1](classes.md#15161-general) General - - [§15.16.2](classes.md#15162-class-members) Class members - - [§15.16.3](classes.md#15163-instance-constructors) Instance constructors - - [§15.16.4](classes.md#15164-implicit-record-class-members) Implicit record class members - - [§15.16.4.1](classes.md#151641-general) General - - [§15.16.4.2](classes.md#151642-copy-constructors) Copy constructors - - [§15.16.4.3](classes.md#151643-equality-members) Equality members - - [§15.16.4.4](classes.md#151644-copy-and-clone-members) Copy and clone members - - [§15.16.4.5](classes.md#151645-printing-members) Printing members - - [§15.16.4.6](classes.md#151646-positional-record-class-members) Positional record class members - - [§15.16.4.6.1](classes.md#1516461-general) General - - [§15.16.4.6.2](classes.md#1516462-primary-constructor) Primary constructor - - [§15.16.4.6.3](classes.md#1516463-properties) Properties - - [§15.16.4.6.4](classes.md#1516464-deconstruct) Deconstruct - - [§15.17](classes.md#1517-declaring-a-collection-type) Declaring a collection type - - [§15.17.1](classes.md#15171-general) General - - [§15.17.2](classes.md#15172-collection-construction) Collection construction - - [§15.18](classes.md#1518-record-class-and-non-record-class-differences) Record class and non-record class differences + - [§15.16.2](classes.md#15162-class-base-specification) Class base specification + - [§15.16.3](classes.md#15163-record-class-body) Record class body + - [§15.16.4](classes.md#15164-class-members) Class members + - [§15.16.5](classes.md#15165-instance-constructors) Instance constructors + - [§15.16.6](classes.md#15166-implicit-record-class-members) Implicit record class members + - [§15.16.6.1](classes.md#151661-general) General + - [§15.16.6.2](classes.md#151662-copy-constructors) Copy constructors + - [§15.16.6.3](classes.md#151663-equality-members) Equality members + - [§15.16.6.4](classes.md#151664-copy-and-clone-members) Copy and clone members + - [§15.16.6.5](classes.md#151665-printing-members) Printing members + - [§15.16.6.6](classes.md#151666-positional-record-class-members) Positional record class members + - [§15.16.6.6.1](classes.md#1516661-general) General + - [§15.16.6.6.2](classes.md#1516662-primary-constructor) Primary constructor + - [§15.16.6.6.3](classes.md#1516663-properties) Properties + - [§15.16.6.6.4](classes.md#1516664-deconstruct) Deconstruct + - [§15.17](classes.md#1517-record-class-and-non-record-class-differences) Record class and non-record class differences - [§16](structs.md#16-structs) Structs - [§16.1](structs.md#161-general) General - [§16.2](structs.md#162-struct-declarations) Struct declarations @@ -714,51 +708,50 @@ - [§16.3](structs.md#163-struct-members) Struct members - [§16.3.1](structs.md#1631-general) General - [§16.3.2](structs.md#1632-readonly-members) Readonly members - - [§16.4](structs.md#164-primary-constructors) Primary constructors - - [§16.5](structs.md#165-record-structs) Record structs - - [§16.5.1](structs.md#1651-general) General - - [§16.5.2](structs.md#1652-struct-members) Struct members - - [§16.5.3](structs.md#1653-implicit-record-struct-members) Implicit record struct members - - [§16.5.3.1](structs.md#16531-general) General - - [§16.5.3.2](structs.md#16532-primary-constructors) Primary constructors - - [§16.5.3.3](structs.md#16533-equality-members) Equality members - - [§16.5.3.4](structs.md#16534-printing-members) Printing members - - [§16.5.3.5](structs.md#16535-positional-record-struct-members) Positional record struct members - - [§16.5.3.5.1](structs.md#165351-general) General - - [§16.5.3.5.2](structs.md#165352-primary-constructor) Primary constructor - - [§16.5.3.5.3](structs.md#165353-properties) Properties - - [§16.5.3.5.4](structs.md#165354-deconstruct) Deconstruct - - [§16.6](structs.md#166-inline-arrays) Inline arrays - - [§16.7](structs.md#167-record-struct-and-non-record-struct-differences) Record struct and non-record struct differences - - [§16.8](structs.md#168-class-and-struct-differences) Class and struct differences - - [§16.8.1](structs.md#1681-general) General - - [§16.8.2](structs.md#1682-value-semantics) Value semantics - - [§16.8.3](structs.md#1683-inheritance) Inheritance - - [§16.8.4](structs.md#1684-assignment) Assignment - - [§16.8.5](structs.md#1685-default-values) Default values - - [§16.8.6](structs.md#1686-boxing-and-unboxing) Boxing and unboxing - - [§16.8.7](structs.md#1687-meaning-of-this) Meaning of this - - [§16.8.8](structs.md#1688-fields) Fields - - [§16.8.8.1](structs.md#16881-field-initializers) Field initializers - - [§16.8.8.2](structs.md#16882-ref-fields) Ref fields - - [§16.8.9](structs.md#1689-constructors) Constructors - - [§16.8.10](structs.md#16810-static-constructors) Static constructors - - [§16.8.11](structs.md#16811-properties) Properties - - [§16.8.12](structs.md#16812-methods) Methods - - [§16.8.13](structs.md#16813-indexers) Indexers - - [§16.8.14](structs.md#16814-events) Events - - [§16.8.15](structs.md#16815-safe-context-constraint) Safe context constraint - - [§16.8.15.1](structs.md#168151-general) General - - [§16.8.15.2](structs.md#168152-parameter-safe-context) Parameter safe context - - [§16.8.15.3](structs.md#168153-local-variable-safe-context) Local variable safe context - - [§16.8.15.4](structs.md#168154-field-safe-context) Field safe context - - [§16.8.15.5](structs.md#168155-operators) Operators - - [§16.8.15.6](structs.md#168156-method-and-property-invocation) Method and property invocation - - [§16.8.15.7](structs.md#168157-method-arguments-must-match) Method arguments must match - - [§16.8.15.8](structs.md#168158-infer-safe-context-of-declaration-expressions) Infer safe-context of declaration expressions - - [§16.8.15.9](structs.md#168159-object-initializer-safe-context) Object initializer safe context - - [§16.8.15.10](structs.md#1681510-stackalloc) stackalloc - - [§16.8.15.11](structs.md#1681511-constructor-invocations) Constructor invocations + - [§16.4](structs.md#164-record-structs) Record structs + - [§16.4.1](structs.md#1641-general) General + - [§16.4.2](structs.md#1642-struct-members) Struct members + - [§16.4.3](structs.md#1643-record-struct-body) Record struct body + - [§16.4.4](structs.md#1644-implicit-record-struct-members) Implicit record struct members + - [§16.4.4.1](structs.md#16441-general) General + - [§16.4.4.2](structs.md#16442-primary-constructors) Primary constructors + - [§16.4.4.3](structs.md#16443-equality-members) Equality members + - [§16.4.4.4](structs.md#16444-printing-members) Printing members + - [§16.4.4.5](structs.md#16445-positional-record-struct-members) Positional record struct members + - [§16.4.4.5.1](structs.md#164451-general) General + - [§16.4.4.5.2](structs.md#164452-primary-constructor) Primary constructor + - [§16.4.4.5.3](structs.md#164453-properties) Properties + - [§16.4.4.5.4](structs.md#164454-deconstruct) Deconstruct + - [§16.5](structs.md#165-record-struct-and-non-record-struct-differences) Record struct and non-record struct differences + - [§16.6](structs.md#166-class-and-struct-differences) Class and struct differences + - [§16.6.1](structs.md#1661-general) General + - [§16.6.2](structs.md#1662-value-semantics) Value semantics + - [§16.6.3](structs.md#1663-inheritance) Inheritance + - [§16.6.4](structs.md#1664-assignment) Assignment + - [§16.6.5](structs.md#1665-default-values) Default values + - [§16.6.6](structs.md#1666-boxing-and-unboxing) Boxing and unboxing + - [§16.6.7](structs.md#1667-meaning-of-this) Meaning of this + - [§16.6.8](structs.md#1668-fields) Fields + - [§16.6.8.1](structs.md#16681-field-initializers) Field initializers + - [§16.6.8.2](structs.md#16682-ref-fields) Ref fields + - [§16.6.9](structs.md#1669-constructors) Constructors + - [§16.6.10](structs.md#16610-static-constructors) Static constructors + - [§16.6.11](structs.md#16611-properties) Properties + - [§16.6.12](structs.md#16612-methods) Methods + - [§16.6.13](structs.md#16613-indexers) Indexers + - [§16.6.14](structs.md#16614-events) Events + - [§16.6.15](structs.md#16615-safe-context-constraint) Safe context constraint + - [§16.6.15.1](structs.md#166151-general) General + - [§16.6.15.2](structs.md#166152-parameter-safe-context) Parameter safe context + - [§16.6.15.3](structs.md#166153-local-variable-safe-context) Local variable safe context + - [§16.6.15.4](structs.md#166154-field-safe-context) Field safe context + - [§16.6.15.5](structs.md#166155-operators) Operators + - [§16.6.15.6](structs.md#166156-method-and-property-invocation) Method and property invocation + - [§16.6.15.7](structs.md#166157-method-arguments-must-match) Method arguments must match + - [§16.6.15.8](structs.md#166158-infer-safe-context-of-declaration-expressions) Infer safe-context of declaration expressions + - [§16.6.15.9](structs.md#166159-object-initializer-safe-context) Object initializer safe context + - [§16.6.15.10](structs.md#1661510-stackalloc) stackalloc + - [§16.6.15.11](structs.md#1661511-constructor-invocations) Constructor invocations - [§17](arrays.md#17-arrays) Arrays - [§17.1](arrays.md#171-general) General - [§17.2](arrays.md#172-array-types) Array types @@ -883,8 +876,6 @@ - [§23.5.12](attributes.md#23512-required-member-attributes) Required member attributes - [§23.5.12.1](attributes.md#235121-the-setsrequiredmembers-attribute) The SetsRequiredMembers attribute - [§23.5.12.2](attributes.md#235122-the-requiredmember-attribute) The RequiredMember attribute - - [§23.5.13](attributes.md#23513-the-collectionbuilder-attribute) The CollectionBuilder attribute - - [§23.5.14](attributes.md#23514-the-inlinearray-attribute) The InlineArray attribute - [§23.6](attributes.md#236-attributes-for-interoperation) Attributes for interoperation - [§24](unsafe-code.md#24-unsafe-code) Unsafe code - [§24.1](unsafe-code.md#241-general) General diff --git a/standard/arrays.md b/standard/arrays.md index 7a55bc748..c01574da6 100644 --- a/standard/arrays.md +++ b/standard/arrays.md @@ -314,5 +314,5 @@ When an array creation expression includes both explicit dimension lengths and a A warning shall be produced for a *variable_initializer* when all the following conditions are true: -- The variable initializer represents an implicit or explicit identity conversion of a primary constructor parameter ([§15.11.6](classes.md#15116-primary-constructors)); +- The variable initializer represents an implicit or explicit identity conversion of a primary constructor parameter (§prim-constructor); - The primary constructor parameter is captured into the state of the enclosing type. diff --git a/standard/attributes.md b/standard/attributes.md index 4ac871c4c..3b17a5e7f 100644 --- a/standard/attributes.md +++ b/standard/attributes.md @@ -512,8 +512,8 @@ A number of attributes affect the language in some way. These attributes include - `System.Runtime.CompilerServices.InterpolatedStringHandlerAttribute` and `System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute`, which are used to declare a custom interpolated string expression handler ([§23.5.11.1](attributes.md#235111-custom-interpolated-string-expression-handlers)) and to call one of its constructors, respectively. - `System.Diagnostics.CodeAnalysis.UnscopedRefAttribute` ([§23.5.8](attributes.md#2358-the-unscopedref-attribute)), which allows an otherwise implicitly scoped ref to be treated as not being scoped. - `System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute` ([§23.5.12.1](attributes.md#235121-the-setsrequiredmembers-attribute)) and `System.Runtime.CompilerServices.RequiredMemberAttribute` ([§23.5.12.2](attributes.md#235122-the-requiredmember-attribute)), which are used in required-member contexts ([§15.7.1](classes.md#1571-general)). -- `System.Runtime.CompilerServices.CollectionBuilderAttribute` ([§23.5.13](attributes.md#23513-the-collectionbuilder-attribute)), which designates a collection type as having a collection-creation method. -- `System.Runtime.CompilerServices.InlineArrayAttribute` ([§23.5.14](attributes.md#23514-the-inlinearray-attribute)), which marks a struct type as an inline array type ([§16.6](structs.md#166-inline-arrays)). +- `System.Runtime.CompilerServices.CollectionBuilderAttribute` (§collection-builder-attr), which designates a collection type as having a collection-creation method. +- `System.Runtime.CompilerServices.InlineArrayAttribute` (§InlineArrayAttribute), which marks a struct type as an inline array type (§InlineArray). The Nullable static analysis attributes ([§23.5.7](attributes.md#2357-code-analysis-attributes)) can improve the correctness of warnings generated for nullabilities and null states ([§8.9.5](types.md#895-nullabilities-and-null-states)). @@ -806,7 +806,7 @@ When an optional parameter is annotated with one of the caller-info attributes, Caller-info attributes can occur on optional parameters anywhere, including in delegate declarations. However, the specific caller-info attributes have restrictions on the types of the parameters they can attribute, so that there will always be an implicit conversion from a substituted value to the parameter type. -It is an error to have the same caller-info attribute on a parameter of both the defining and implementing part of a partial method declaration. Only caller-info attributes in the defining part are applied, whereas caller-info attributes occurring only in the implementing part are ignored. +It is an error to have the same caller-info attribute on a parameter of both the defining and implementing part of a partial method or partial indexer declaration. Only caller-info attributes in the defining part are applied, whereas caller-info attributes occurring only in the implementing part are ignored. Caller information does not affect overload resolution. As the attributed optional parameters are still omitted from the source code of the caller, overload resolution ignores those parameters in the same way it ignores other omitted optional parameters ([§12.6.4](expressions.md#1264-overload-resolution)). @@ -1579,9 +1579,9 @@ This attribute indicates that the constructor it decorates sets all required mem This attribute indicates that the current type has one or more required members ([§15.7.1](classes.md#1571-general)), or that a specific member of that type is required. However, it is an error for this attribute to be used explicitly. Instead, the presence of the modifier `required` results in the type or member being treated as if it were decorated with this attribute. -### 23.5.13 The CollectionBuilder attribute +### §collection-builder-attr The CollectionBuilder attribute -This attribute designates a collection type as having a collection-creation method ([§15.17.1](classes.md#15171-general)). +This attribute designates a collection type as having a collection-creation method (§declaring-a-collection-type-general). The constructor takes a builder type and the name of the method to be invoked to construct an instance of the collection type. @@ -1589,9 +1589,9 @@ The attribute can be applied to a class, struct, ref struct, or interface. The a The builder type shall be a non-generic class or struct. -### 23.5.14 The InlineArray attribute +### §InlineArrayAttribute The InlineArray attribute -This attribute is used to identify a non-record struct as an inline array type. For further information and examples of its use, see [§16.6](structs.md#166-inline-arrays). +This attribute is used to identify a non-record struct as an inline array type. For further information and examples of its use, see §InlineArray. ## 23.6 Attributes for interoperation diff --git a/standard/basic-concepts.md b/standard/basic-concepts.md index 2fe81f80c..6b7045ba7 100644 --- a/standard/basic-concepts.md +++ b/standard/basic-concepts.md @@ -123,7 +123,7 @@ The application startup and termination process is semantically equivalent to th - Awaiting ([§12.9.9](expressions.md#1299-await-expressions)) the result of invoking the entry-point method, if its return type is a `Task` type. - In either case if the entry point requires an argument the application parameter array is supplied as its value. -> *Note*: Invoking the entry-point method will cause the static constructor, if any, of the enclosing type to be executed first ([§15.12](classes.md#1512-static-constructors), [§16.8.10](structs.md#16810-static-constructors)). *end note* +> *Note*: Invoking the entry-point method will cause the static constructor, if any, of the enclosing type to be executed first ([§15.12](classes.md#1512-static-constructors), [§16.6.10](structs.md#16610-static-constructors)). *end note* - The application is terminated - If the run results in an `int` value it serves as the termination status code; diff --git a/standard/classes.md b/standard/classes.md index 355c8fcb1..d9a1d173b 100644 --- a/standard/classes.md +++ b/standard/classes.md @@ -36,13 +36,13 @@ non_record_class_with_positional_members ; ``` -There are two kinds of class: ***non-record class***, as declared by *non_record_class_declaration*, and ***record class***, as declared by *record_class_declaration*. A non-record class is the kind of class that C# has supported since the language’s inception. Record classes were added much later and are discussed in [§15.16](classes.md#1516-record-classes). The differences between the two kinds are discussed in [§15.18](classes.md#1518-record-class-and-non-record-class-differences). +There are two kinds of class: ***non-record class***, as declared by *non_record_class_declaration*, and ***record class***, as declared by *record_class_declaration*. A non-record class is the kind of class that C# has supported since the language’s inception. Record classes were added much later and are discussed in [§15.16](classes.md#1516-record-classes). The differences between the two kinds are discussed in [§15.17](classes.md#1517-record-class-and-non-record-class-differences). A *non_record_class_declaration* can have one of two almost identical forms: *non_record_class_without_positional_members* and *non_record_class_with_positional_members*. A *non_record_class_without_positional_members* consists of an optional set of *attributes* ([§23](attributes.md#23-attributes)), followed by an optional set of *class_modifier*s ([§15.2.2](classes.md#1522-class-modifiers)), followed by an optional `partial` modifier ([§15.2.7](classes.md#1527-partial-type-declarations)), followed by the keyword `class` and an *identifier* that names the class, followed by an optional *type_parameter_list* ([§15.2.3](classes.md#1523-type-parameters)), followed by an optional *class_base* specification ([§15.2.4](classes.md#1524-class-base-specification)), followed by an optional set of *type_parameter_constraints_clause*s ([§15.2.5](classes.md#1525-type-parameter-constraints)), followed by a *class_body* ([§15.2.6](classes.md#1526-class-body)). -A *non_record_class_with_positional_members* has the same syntax but requires a *delimited_parameter_list*, as shown above in that grammar rule. For a discussion of *delimited_parameter_list*, see [§15.11.6](classes.md#15116-primary-constructors). +A *non_record_class_with_positional_members* has the same syntax but requires a *delimited_parameter_list*, as shown above in that grammar rule. For a discussion of *delimited_parameter_list*, see §prim-constructor. A class having a required member ([§15.7.1](classes.md#1571-general)) directly (that is, not through inheritance) shall be treated as if it were decorated with the attribute `System.Runtime.CompilerServices.RequiredMemberAttribute` ([§23.5.12.2](attributes.md#235122-the-requiredmember-attribute)). @@ -227,7 +227,7 @@ interface_type_list A warning shall be produced for an in or by-value argument in a *base_argument_list* when all the following conditions are true: -- The argument represents an implicit or explicit identity conversion of a primary constructor parameter ([§15.11.6](classes.md#15116-primary-constructors)); +- The argument represents an implicit or explicit identity conversion of a primary constructor parameter (§prim-constructor); - The argument is not part of an expanded params argument; - The primary constructor parameter is captured into the state of the enclosing type. @@ -822,7 +822,7 @@ The *class_body*s `{}`, `{};`, and `;` are equivalent, and the *class_body*s `{ ### 15.2.7 Partial type declarations -The modifier `partial` is used when defining a class, struct, or interface type in multiple parts. The `partial` modifier is a contextual keyword ([§6.4.4](lexical-structure.md#644-keywords)) and has special meaning in a *class_declaration*, a *struct_declaration*, or an *interface_declaration*. (A partial type may contain partial method declarations ([§15.6.9](classes.md#1569-partial-methods)). +The modifier `partial` is used when defining a class, struct, or interface type in multiple parts. The `partial` modifier is a contextual keyword ([§6.4.4](lexical-structure.md#644-keywords)) and has special meaning in a *class_declaration*, a *struct_declaration*, or an *interface_declaration*. (A partial type may contain partial method declarations ([§15.6.9](classes.md#1569-partial-methods)), partial property declarations (§partial-properties), and partial indexer declarations (§partial-indexers)). Each part of a ***partial type*** declaration shall include a `partial` modifier and shall be declared in the same namespace or containing type as the other parts. The `partial` modifier indicates that additional parts of the type declaration might exist elsewhere, but the existence of such additional parts is not a requirement; it is valid for the only declaration of a type to include the `partial` modifier. It is valid for only one declaration of a partial type to include the base class or implemented interfaces. However, all declarations of a base class or implemented interfaces shall match, including the nullability of any specified type arguments. @@ -888,7 +888,7 @@ The handling of attributes specified on the type or type parameters of different ### 15.3.1 General -The members of a class consist of the members introduced by its *class_member_declaration*s, the members inherited from the direct base class, and any members implicitly provided by the implementation ([§15.16.4](classes.md#15164-implicit-record-class-members)). +The members of a class consist of the members introduced by its *class_member_declaration*s, the members inherited from the direct base class, and any members implicitly provided by the implementation ([§15.16.6](classes.md#15166-implicit-record-class-members)). ```ANTLR class_member_declaration @@ -1746,7 +1746,7 @@ The value of a field is obtained in an expression using a *simple_name* ([§12.8 A field declaration that declares multiple fields is equivalent to multiple declarations of single fields with the same attributes, modifiers, and type. -> *Note*: Inside a `ref struct`, a field may also be declared as a reference variable; see [§16.8.8.2](structs.md#16882-ref-fields). *end note* +> *Note*: Inside a `ref struct`, a field may also be declared as a reference variable; see [§16.6.8.2](structs.md#16682-ref-fields). *end note* @@ -2133,7 +2133,7 @@ A variable initializer for an instance field cannot reference the instance being ### 15.6.1 General -[§15.6](classes.md#156-methods) and its subclauses cover method declarations in classes. That text is augmented by information about declaring methods in structs ([§16.8](structs.md#168-class-and-struct-differences)) and interfaces ([§19.4.3](interfaces.md#1943-interface-methods)). +[§15.6](classes.md#156-methods) and its subclauses cover method declarations in classes. That text is augmented by information about declaring methods in structs ([§16.6](structs.md#166-class-and-struct-differences)) and interfaces ([§19.4.3](interfaces.md#1943-interface-methods)). A ***method*** is a member that implements a computation or action that can be performed by an object or class. Methods are declared using *method_declaration*s: @@ -2219,7 +2219,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* ([§23](attributes.md#23-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.14](classes.md#1514-async-functions)) modifiers. Additionally a *method_declaration* that is contained directly by a *struct_declaration* may include the `readonly` modifier ([§16.8.12](structs.md#16812-methods)). +A *method_declaration* may include a set of *attributes* ([§23](attributes.md#23-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.14](classes.md#1514-async-functions)) modifiers. Additionally a *method_declaration* that is contained directly by a *struct_declaration* may include the `readonly` modifier ([§16.6.12](structs.md#16612-methods)). A *method_declaration* has a valid combination of modifiers if all of the following are true. (These rules are modified slightly in the context of an interface; see [§19.4.1](interfaces.md#1941-general).): @@ -3503,8 +3503,8 @@ Properties are declared using *property_declaration*s: ```ANTLR property_declaration - : attributes? property_modifier* type member_name property_body - | attributes? property_modifier* ref_kind type member_name ref_property_body + : attributes? property_modifier* 'partial'? type member_name property_body + | attributes? property_modifier* 'partial'? ref_kind type member_name ref_property_body ; property_modifier @@ -3541,7 +3541,7 @@ ref_property_body *unsafe_modifier* ([§24.2](unsafe-code.md#242-unsafe-contexts)) is only available in unsafe code ([§24](unsafe-code.md#24-unsafe-code)). -A *property_declaration* may include a set of *attributes* ([§23](attributes.md#23-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.8.11](structs.md#16811-properties)). +A *property_declaration* may include a set of *attributes* ([§23](attributes.md#23-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.6.11](structs.md#16611-properties)). However, a partial property (§partial-properties) shall not have an `abstract` modifier. - 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. @@ -3660,7 +3660,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 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.8.11](structs.md#16811-properties), [§16.8.13](structs.md#16813-indexers)). +- The *accessor_modifier* `readonly` is permitted only in a *property_declaration* or *indexer_declaration* that is contained directly by a *struct_declaration* ([§16.6.11](structs.md#16611-properties), [§16.6.13](structs.md#16613-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 or init 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: @@ -4184,7 +4184,7 @@ Init accessors (both auto- and manually-implemented) are permitted on properties ### 15.7.4 Automatically implemented properties -An automatically implemented property (or auto-property for short), is a non-abstract, non-extern, non-ref-valued property with semicolon-only *accessor_body*s. An auto-property shall have a get accessor and may optionally have a set or init accessor. +An automatically implemented property (or auto-property for short), is a non-abstract, non-extern, non-partial, non-ref-valued property with semicolon-only *accessor_body*s. An auto-property shall have a get accessor and may optionally have a set or init accessor. When a property is specified as an automatically implemented property, a hidden backing field is automatically available for the property, and the accessors are implemented to read from and write to that backing field. The hidden backing field is inaccessible, it can be read and written only through the automatically implemented property accessors, even within the containing type. If the auto-property has no set or init accessor, the backing field is considered `readonly` ([§15.5.3](classes.md#1553-readonly-fields)). Just like a `readonly` field, a read-only auto-property may also be assigned to in the body of a constructor of the enclosing class. Such an assignment assigns directly to the read-only backing field of the property. If the auto-property has an init accessor, the backing field may be assigned to during the construction phase of an object ([§15.7.3.3](classes.md#15733-init-accessors)). @@ -4521,6 +4521,93 @@ When an init accessor appears in a virtual property, all overrides for it shall > > *end example* +### §partial-properties Partial properties + +When a *property_declaration* includes `partial`, that property is said to be a ***partial property***. Partial properties may only be declared as members of partial types ([§15.2.7](classes.md#1527-partial-type-declarations)). + +Partial properties may be defined in one part of a type declaration and implemented in another, or be defined and implemented in the same part. + +There are two kinds of partial property declarations: If the body of each of the property’s accessors is a semicolon and the property has no `extern` modifier, the declaration is said to be a ***defining partial property declaration***. Otherwise, the declaration is said to be an ***implementing partial property declaration***. + +*Note*: As the syntactic form of a property with semicolon accessor bodies is reserved for a defining partial declaration, a partial property cannot be automatically implemented ([§15.7.4](classes.md#1574-automatically-implemented-properties)). *end note* + +Partial properties are useful for allowing one part of a type declaration to customize the behavior of another part, e.g., one that is generated by a tool. + +> *Example*: +> +> +> ```csharp +> // part containing defining partial declarations +> public partial class C +> { +> public partial string Prop1 { get; set; } +> public virtual partial string Prop2 { get; set; } +> } +> +> // part containing implementing partial declarations +> public partial class C +> { +> private string _field = ""; +> +> public partial string Prop1 { get => _field; set => _field = value; } +> virtual public partial string Prop2 { set => _field = value; get => _field; } +> } +> ``` +> +> *end example* + +Across the parts of a type declaration, there shall be only one defining partial property declaration with a given signature, and there shall be only one implementing partial property declaration with a given signature. + +The signature-matching requirements are as follows: + +1. Type and ref-kind differences between partial property declarations result in a compile-time error. +1. Differences in tuple element names within partial property declarations result in a compile-time error. +1. The property declarations and their accessor declarations shall have the same modifiers, though the modifiers may appear in a different order. However, this does not apply to the `extern` modifier, which may only appear on an implementing partial declaration. In the case of private accessibility on the property, both shall be implicitly private (that is, with no accessibility modifier) or both shall be explicitly `private`. Likewise, the corresponding accessors shall have the same implicit or same explicit accessibilities. +1. All other syntactic differences in the signatures of partial property declarations result in a compile-time warning, with the following exceptions: + +- Attribute lists on or within partial property declarations do not need to match. Instead, merging of attributes in corresponding positions is performed in an unspecified order. Duplicates are not removed. +- Nullable context differences do not cause warnings. In other words, a difference where one of the types is nullable-oblivious and the other type is either nullable-annotated or not-nullable-annotated does not result in any warnings. + +1. Nullability differences that do not involve oblivious nullability result in warnings. When analyzing an accessor body, the implementation part signature is used. The definition part signature is used when analyzing use sites. + +> *Example*: +> +> +> ```csharp +> partial class C1 +> { +> private string _field; +> public partial string Prop { get; private set; } +> +> // Error: implementation set accessor modifier mismatch +> public partial string Prop { get => _field; set => _field = value; } +> } +> +> partial class C2 +> { +> private string _field; +> public partial string Prop { get; init; } +> +> // Error: implementation of 'Prop' must have an init accessor +> public partial string Prop { get => _field; set => _field = value; } +> } +> +> partial class C3 +> { +> private string _field; +> public partial string Prop { get; } +> +> // Error: implementation of 'Prop' cannot have a set accessor +> public partial string Prop { get => _field; set => _field = value; } +> } +> ``` +> +> *end example* + +In *property_declaration*, the identifier `partial` is recognized as a contextual keyword ([§6.4.4](lexical-structure.md#644-keywords)) only if it immediately precedes the property’s type. A partial property cannot explicitly implement interface properties. + +Only a defining partial property participates in lookup. + ## 15.8 Events ### 15.8.1 General @@ -4568,7 +4655,7 @@ remove_accessor_declaration *unsafe_modifier* ([§24.2](unsafe-code.md#242-unsafe-contexts)) is only available in unsafe code ([§24](unsafe-code.md#24-unsafe-code)). -An *event_declaration* may include a set of *attributes* ([§23](attributes.md#23-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 ([§16.8.12](structs.md#16812-methods)). +An *event_declaration* may include a set of *attributes* ([§23](attributes.md#23-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 ([§16.6.12](structs.md#16612-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. @@ -4814,8 +4901,8 @@ An ***indexer*** is a member that enables an object to be indexed in the same wa ```ANTLR indexer_declaration - : attributes? indexer_modifier* indexer_declarator indexer_body - | attributes? indexer_modifier* ref_kind indexer_declarator ref_indexer_body + : attributes? indexer_modifier* 'partial'? indexer_declarator indexer_body + | attributes? indexer_modifier* 'partial'? ref_kind indexer_declarator ref_indexer_body ; indexer_modifier @@ -4851,7 +4938,7 @@ ref_indexer_body *unsafe_modifier* ([§24.2](unsafe-code.md#242-unsafe-contexts)) is only available in unsafe code ([§24](unsafe-code.md#24-unsafe-code)). -An *indexer_declaration* may include a set of *attributes* ([§23](attributes.md#23-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 ([§16.8.12](structs.md#16812-methods)). +An *indexer_declaration* may include a set of *attributes* ([§23](attributes.md#23-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 ([§16.6.12](structs.md#16612-methods)). However, a partial indexer (§partial-indexers) shall not have an `abstract` modifier. - 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. @@ -5023,7 +5110,7 @@ When an indexer declaration includes an `extern` modifier, the indexer is said t Indexers and properties are very similar in concept, but differ in the following ways: - A property is identified by its name, whereas an indexer is identified by its signature. -- A property is accessed through a *simple_name* ([§12.8.4](expressions.md#1284-simple-names)) or a *member_access* ([§12.8.7](expressions.md#1287-member-access)), whereas an indexer element is accessed through an *element_access* ([§12.8.12.5](expressions.md#128125-indexer-access)). +- A property is accessed through a *simple_name* ([§12.8.4](expressions.md#1284-simple-names)) or a *member_access* ([§12.8.7](expressions.md#1287-member-access)), whereas an indexer element is accessed through an *element_access* ([§12.8.12.4](expressions.md#128124-indexer-access)). - A property can be a static member, whereas an indexer is always an instance member. - A get accessor of a property corresponds to a method with no parameters, whereas a get accessor of an indexer corresponds to a method with the same parameter list as the indexer. - A set accessor of a property corresponds to a method with a single parameter named `value`, whereas a set accessor of an indexer corresponds to a method with the same parameter list as the indexer, plus an additional parameter named `value`. @@ -5036,6 +5123,60 @@ Aside from these differences, all rules defined in [§15.7.3](classes.md#1573-ac This replacing of property/properties with indexer/indexers when reading [§15.7.3](classes.md#1573-accessors), [§15.7.5](classes.md#1575-accessibility) and [§15.7.6](classes.md#1576-virtual-sealed-override-and-abstract-accessors) applies to defined terms as well. Specifically, *read-write property* becomes ***read-write indexer***, *read-init property* becomes ***read-init indexer***, *read-only property* becomes ***read-only indexer***, and *write-only property* becomes ***write-only indexer***, and *init-only property* becomes ***init-only indexer***. +### §partial-indexers Partial indexers + +When an *indexer_declaration* includes `partial`, that indexer is said to be a ***partial indexer***. Partial indexers may only be declared as members of partial types ([§15.2.7](classes.md#1527-partial-type-declarations)). + +Partial indexers may be defined in one part of a type declaration and implemented in another, or be defined and implemented in the same part. + +There are two kinds of partial indexer declarations: If the body of each of the indexer’s accessors is a semicolon and the indexer has no `extern` modifier, the declaration is said to be a ***defining partial indexer declaration***. Otherwise, the declaration is said to be an ***implementing partial indexer declaration***. + +Partial indexers are useful for allowing one part of a type declaration to customize the behavior of another part, e.g., one that is generated by a tool. + +> *Example*: +> +> +> ```csharp +> // part containing defining partial indexer declaration +> public partial class C +> { +> public partial int this[int x] { get; private set; } +> } +> +> // part containing implementing partial indexer declaration +> public partial class C +> { +> private int[] _store = new int[100]; +> public partial int this[int x = 10] // default argument value is ignored +> { +> get => this._store[x]; +> private set => this._store[x] = value; +> } +> } +> ``` +> +> *end example* + +Across the parts of a type declaration, there shall be only one defining partial indexer declaration with a given signature, and there shall be only one implementing partial indexer declaration with a given signature. + +The signature-matching requirements are as follows: + +1. Type and ref-kind differences between partial indexer declarations result in a compile-time error. +1. Differences in tuple element names within partial indexer declarations result in a compile-time error. +1. The property declarations and their accessor declarations shall have the same modifiers, though the modifiers may appear in a different order. However, this does not apply to the `extern` modifier, which may only appear on an implementing partial declaration. In the case of private accessibility on the indexer, both shall be implicitly private (that is, with no accessibility modifier) or both shall be explicitly `private`. Likewise, the corresponding accessors shall have the same implicit or same explicit accessibilities. +1. All other syntactic differences in the signatures of partial property declarations result in a compile-time warning, with the following exceptions: + + - Attribute lists on or within partial indexer declarations do not need to match. Instead, merging of attributes in corresponding positions is performed in an unspecified order. Duplicates are not removed. + - Nullable context differences do not cause warnings. In other words, a difference where one of the types is nullable-oblivious and the other type is either nullable-annotated or not-nullable-annotated does not result in any warnings. + - Default argument values need not match, and any default arguments values in the implementing partial indexer declaration are ignored. + +1. A warning is reported when parameter names differ across defining and implementing declarations. The parameter names from the definition part are used at use sites. +1. Nullability differences that do not involve oblivious nullability result in warnings. When analyzing an accessor body, the implementation part signature is used. The definition part signature is used when analyzing use sites. + +In *indexer_declaration*, the identifier `partial` is recognized as a contextual keyword ([§6.4.4](lexical-structure.md#644-keywords)) only if it immediately precedes the indexer’s type. A partial indexer cannot explicitly implement interface indexers. + +Only a defining partial indexer participates in lookup. + ## 15.10 Operators ### 15.10.1 General @@ -5630,7 +5771,7 @@ If overload resolution is unable to determine a unique best candidate for the ba > > *end example* -### 15.11.6 Primary constructors +### §prim-constructor Primary constructors For a class type with a *delimited_parameter_list* the implementation shall provide a public constructor whose signature corresponds to the value parameters, if any, of the type declaration. This constructor is called the ***primary constructor*** for that type, and causes the implicitly declared default constructor, to be suppressed. It is an error to have a primary constructor and an explicit constructor with the same signature in the type. If the type declaration does not include a *delimited_parameter_list*, no primary constructor is provided. @@ -6367,25 +6508,25 @@ At most only one partial type declaration of a partial record class may provide Parameters in *delimited_parameter_list* shall not have `ref`, `out` or `this` modifiers; however, `in` and `params` modifiers are permitted. -### 15.16.2 Class members +### 15.16.4 Class members It is an error for a member of a record class to be named `Clone`. It is an error for an instance field of a record class to have an unsafe type. -### 15.16.3 Instance constructors +### 15.16.5 Instance constructors -A positional record class ([§15.16.1](classes.md#15161-general)) has a primary constructor; see [§15.16.4.6.2](classes.md#1516462-primary-constructor) for more information. +A positional record class ([§15.16.1](classes.md#15161-general)) has a primary constructor; see [§15.16.6.6.2](classes.md#1516662-primary-constructor) for more information. -### 15.16.4 Implicit record class members +### 15.16.6 Implicit record class members -#### 15.16.4.1 General +#### 15.16.6.1 General Certain members are provided by the implementation unless a member with a matching signature is declared in the *class_body*, or an accessible concrete, non-virtual member with a matching signature is inherited. A matching member prevents the implementation from providing that member only, not any other provided members. Two members are considered matching if they have the same signature or would be considered hiding in an inheritance scenario. The members provided by the implementation are described in the following subclauses. -#### 15.16.4.2 Copy constructors +#### 15.16.6.2 Copy constructors A ***copy constructor*** for a type `T` is a constructor having a single parameter of type `T`. The purpose of a copy constructor is to copy the state from the parameter to the new instance being created. @@ -6416,11 +6557,11 @@ A ***copy constructor*** for a type `T` is a constructor having a single paramet > > the record class is immutable. The provided auto properties `Age` and `Name` are read-init. A copy constructor is provided, as is a primary constructor. *end example* -In certain circumstances ([§15.16.4.4](classes.md#151644-copy-and-clone-members)), a copy constructor may be provided by the compiler, and called by provided code. +In certain circumstances ([§15.16.6.4](classes.md#151664-copy-and-clone-members)), a copy constructor may be provided by the compiler, and called by provided code. A copy constructor on a type that has a required member list ([§15.7.1](classes.md#1571-general)) shall be decorated with SetsRequiredMembersAttribute ([§23.5.12.1](attributes.md#235121-the-setsrequiredmembers-attribute)). -#### 15.16.4.3 Equality members +#### 15.16.6.3 Equality members If a record class is derived directly from `object`, the record class type has a provided property declared as follows: @@ -6587,18 +6728,18 @@ The provided override of `GetHashCode()` returns an `int` result of combining th > > *end example* -#### 15.16.4.4 Copy and clone members +#### 15.16.6.4 Copy and clone members A record class type contains two copying members: -- A copy constructor ([§15.16.4.2](classes.md#151642-copy-constructors)) +- A copy constructor ([§15.16.6.2](classes.md#151662-copy-constructors)) - A provided public, parameter-less, instance clone method having an unspecified reserved name The copy constructor shall not execute any instance field/property initializers present in the record class declaration. If the constructor is not explicitly declared, it shall be provided by the implementation. If the provided record class is sealed, the constructor shall be private; otherwise; it shall be protected. An explicitly declared copy constructor shall be either public or protected, unless the record class is sealed. The first thing the constructor shall do, is to call a copy constructor of the base class, or a parameter-less `object` constructor if the record inherits from `object`. It is an error for a user-defined copy constructor to use an implicit or explicit *constructor_initializer* that doesn’t fulfill this requirement. After a base copy constructor is invoked, a provided copy constructor shall copy values for all instance fields implicitly or explicitly declared within the record class type. The sole presence of a copy constructor, whether explicit or implicit, shall not prevent an automatic addition of a default instance constructor. If a virtual clone method is present in the base record class, the provided clone method shall override it, and the return type of the clone method shall be the current containing type if the covariant-returns feature is supported, and the override return type otherwise. It is an error if the base record class clone method is sealed. If a virtual clone method is not present in the base record class, the return type of the clone method shall be the containing type and the method shall be virtual, unless the record class is sealed or abstract. If the containing record class is abstract, the provided clone method shall also be abstract. If the clone method is not abstract, it shall return the result of a call to a copy constructor. -#### 15.16.4.5 Printing members +#### 15.16.6.5 Printing members If a record class is derived directly from `object`, the class includes a provided method declared as follows: @@ -6768,17 +6909,17 @@ The provided method: > > *end example* -#### 15.16.4.6 Positional record class members +#### 15.16.6.6 Positional record class members -##### 15.16.4.6.1 General +##### 15.16.6.6.1 General As well as providing the members described in the preceding subclauses, positional record classes ([§15.2.1](classes.md#1521-general)) result in the implementation providing additional members with the same conditions as the other provided members, as described in the following subclauses. -##### 15.16.4.6.2 Primary constructor +##### 15.16.6.6.2 Primary constructor -The primary constructor of a record class is like that of a non-record class ([§15.11.6](classes.md#15116-primary-constructors)), with the following difference: Each parameter value is stored in a corresponding private instance field having a corresponding property with set and get accessors. +The primary constructor of a record class is like that of a non-record class (§prim-constructor), with the following difference: Each parameter value is stored in a corresponding private instance field having a corresponding property with set and get accessors. -##### 15.16.4.6.3 Properties +##### 15.16.6.6.3 Properties For each parameter of a *delimited_parameter_list* that has the same name and type as an explicitly declared instance field, the remainder of this subclause does not apply. @@ -6808,7 +6949,7 @@ For a record class: > > *end example* -##### 15.16.4.6.4 Deconstruct +##### 15.16.6.6.4 Deconstruct A positional record class ([§15.2.1](classes.md#1521-general)) with at least one parameter causes to be provided a public `void`-returning instance method called `Deconstruct` with an out parameter declaration for each parameter of the primary constructor declaration. Each parameter of `Deconstruct` has the same type as the corresponding parameter of the primary constructor declaration. The body of the method assigns to each parameter of `Deconstruct` the value from an instance member access to a member of the same name. The method may be declared explicitly. It is an error if the explicit declaration does not match the expected signature or accessibility, or is static. @@ -6838,11 +6979,11 @@ A positional record class ([§15.2.1](classes.md#1521-general)) with at least on > > *end example* -## 15.17 Declaring a collection type +## §declaring-a-collection-type Declaring a collection type -### 15.17.1 General +### §declaring-a-collection-type-general General -There are a number of contexts in which a collection expression ([§12.8.25](expressions.md#12825-collection-expressions)) may be converted to a collection type ([§10.2.22](conversions.md#10222-implicit-collection-expression-conversions)). One of them is for a target class, struct, or interface type to be made a collection type by annotating it with an attribute, as shown below. +There are a number of contexts in which a collection expression (§collection-expressions) may be converted to a collection type (§imp-collection-expression-conv). One of them is for a target class, struct, or interface type to be made a collection type by annotating it with an attribute, as shown below. Here is a simple user-defined collection type and its associated builder type: @@ -6887,7 +7028,7 @@ internal static class MyCollectionBuilder } ``` -The collection type shall be annotated with `CollectionBuilderAttribute` ([§23.5.13](attributes.md#23513-the-collectionbuilder-attribute)) that designates an associated, non-generic builder class or struct type having a collection-creation method (whose name is user-defined; in this case, it is `Create`). +The collection type shall be annotated with `CollectionBuilderAttribute` (§collection-builder-attr) that designates an associated, non-generic builder class or struct type having a collection-creation method (whose name is user-defined; in this case, it is `Create`). The job of a ***collection-creation method*** is to create and initialize an instance of its associated collection type. @@ -6913,9 +7054,9 @@ For a *collection_expression* with a target type `C` where the The span parameter for the collection-creation method may be explicitly marked `scoped` or `[UnscopedRef] ([§9.7.3](variables.md#973-the-scoped-modifier))`. If the parameter is implicitly or explicitly `scoped`, the compiler may allocate the storage for the span on the stack rather than the heap. -The construction of an instance of a collection type is described in [§15.17.2](classes.md#15172-collection-construction). +The construction of an instance of a collection type is described in §collection-construction. -### 15.17.2 Collection construction +### §collection-construction Collection construction The *collection_element*s of a *collection_expression* are evaluated in order, left to right. Each *collection_element* is evaluated exactly once, and any further references to the any elements refer to the results of this initial evaluation. @@ -6925,7 +7066,7 @@ An unhandled exception thrown from any of the methods used during construction s `Length`, `Count`, and `GetEnumerator` are assumed to have no side effects. -If the target type is a struct or class type that implements `System.Collections.IEnumerable`, and the target type does not have a collection-creation method ([§15.17.1](classes.md#15171-general)), the construction of the collection instance steps are, as follows: +If the target type is a struct or class type that implements `System.Collections.IEnumerable`, and the target type does not have a collection-creation method (§declaring-a-collection-type-general), the construction of the collection instance steps are, as follows: - The elements are evaluated in order. Some or all elements may be evaluated during the steps below rather than before. - The compiler may determine the known length of the collection expression by invoking countable properties ([§18.1](ranges.md#181-general)) or equivalent properties from well-known interfaces or types, on each *spread_element*’s *expression*. @@ -6989,7 +7130,7 @@ If the target type is an array, a `Span` or `ReadOnlySpan`, a type with a collec > > *end note* -## 15.18 Record class and non-record class differences +## 15.17 Record class and non-record class differences A record class differs from a non-record class in several important ways: diff --git a/standard/conversions.md b/standard/conversions.md index bbb260f3f..771cfe457 100644 --- a/standard/conversions.md +++ b/standard/conversions.md @@ -460,13 +460,13 @@ Although an implicit conversion to `object` is permitted, a warning shall be iss > > *end example* -### 10.2.22 Implicit collection expression conversions +### §imp-collection-expression-conv Implicit collection expression conversions An implicit collection expression conversion exists from a collection expression to the following types: - A single-dimensional array type `T[]`, in which case, the element type is `T`. - `System.Span` and `System.ReadOnlySpan`, in which cases, the element type is `T`. -- A type with an appropriate collection-creation method ([§15.17.1](classes.md#15171-general)), in which case, the element type is the iteration type ([§13.9.5](statements.md#1395-the-foreach-statement)) determined from a `GetEnumerator` instance method or enumerable interface, not from an extension method. +- A type with an appropriate collection-creation method (§declaring-a-collection-type-general), in which case, the element type is the iteration type ([§13.9.5](statements.md#1395-the-foreach-statement)) determined from a `GetEnumerator` instance method or enumerable interface, not from an extension method. - A struct or class type that implements `System.Collections.IEnumerable` where: - The type has an applicable ([§12.6.4.2](expressions.md#12642-applicable-function-member)) constructor that can be invoked with no arguments, and the constructor is accessible at the location of the collection expression. @@ -504,17 +504,17 @@ The following additional implicit conversions exist from a collection expression - To an interface type `I` where there is a collection-creation method associated with `I` that returns a type `V` and there is an implicit boxing conversion from `V` to `I`. The conversion is a collection expression conversion to `V` followed by an implicit boxing conversion from `V` to `I`. -When a collection expression is converted to a ref struct type, all ref safety requirements ([§9.7.2](variables.md#972-ref-safe-contexts), [§16.8.15](structs.md#16815-safe-context-constraint)) shall be met. +When a collection expression is converted to a ref struct type, all ref safety requirements ([§9.7.2](variables.md#972-ref-safe-contexts), [§16.6.15](structs.md#16615-safe-context-constraint)) shall be met. -### 10.2.23 Implicit inline array conversions +### §ImplicitInlineArrayConversions Implicit inline array conversions -The implicit inline array ([§16.6](structs.md#166-inline-arrays)) conversions are: +The implicit inline array (§InlineArray) conversions are: - From an expression designating a writable inline array with element type `T` to `System.Span` - From an expression designating a writable inline array with element type `T` to `System.ReadonlySpan` - From an expression designating a readonly inline array with element type `T` to `System.ReadonlySpan` -The conversion of an inline array to a `System.Span` or `System.ReadonlySpan` ignores any declared operators in the inline array type that might otherwise appear to be applicable. See [§16.6](structs.md#166-inline-arrays) for more information. +The conversion of an inline array to a `System.Span` or `System.ReadonlySpan` ignores any declared operators in the inline array type that might otherwise appear to be applicable. See §InlineArray for more information. ## 10.3 Explicit conversions @@ -760,7 +760,7 @@ The following implicit conversions are classified as standard implicit conversio - Boxing conversions ([§10.2.9](conversions.md#1029-boxing-conversions)) - Implicit constant expression conversions ([§10.2.11](conversions.md#10211-implicit-constant-expression-conversions)) - Implicit conversions involving type parameters ([§10.2.12](conversions.md#10212-implicit-conversions-involving-type-parameters)) -- Implicit inline array conversions ([§10.2.23](conversions.md#10223-implicit-inline-array-conversions)) +- Implicit inline array conversions (§ImplicitInlineArrayConversions) The standard implicit conversions specifically exclude user-defined implicit conversions. diff --git a/standard/documentation-comments.md b/standard/documentation-comments.md index 755f40454..11239f2f6 100644 --- a/standard/documentation-comments.md +++ b/standard/documentation-comments.md @@ -61,11 +61,11 @@ Although developers are free to create their own set of tags, a recommended set Note carefully that the documentation file does not provide full information about the type and members (for example, it does not contain any type information). To get such information about a type or member, the documentation file must be used in conjunction with reflection on the type or member. -A partial type or a partial method can be declared in multiple parts, each of which can be in one or more compilation units, and each of which can have one or more documentation comments. A partial method typically has a “defining partial declaration” and an “implementing partial declaration.” +A partial type, partial method, partial property, or partial indexer can be declared in multiple parts, each of which can be in one or more compilation units, and each of which can have one or more documentation comments. A partial method, partial property, or partial indexer typically has a “defining partial declaration” and an “implementing partial declaration.” For a partial type, the document comments that apply directly to that type, if any, from each of its parts, are all written to the documentation file in some unspecified order. -For a partial method: +For a partial method, partial property, or partial indexer: - If a defining partial declaration has no corresponding implementing partial declaration, any documentation comments in that defining partial declaration are ignored (as that declaration will be removed). - Otherwise, if the implementing partial declaration has any documentation comments, they are written to the documentation file, and any documentation comments in the defining partial declaration are ignored. diff --git a/standard/expressions.md b/standard/expressions.md index 8799cc6e3..63750adbe 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -1300,7 +1300,7 @@ Even though overload resolution of a dynamically bound operation takes place at - For a delegate invocation ([§12.8.10.4](expressions.md#128104-delegate-invocations)), the list is a single function member with the same parameter list as the *delegate_type* of the invocation - For a method invocation ([§12.8.10.2](expressions.md#128102-method-invocations)) on a type, or on a value whose static type is not dynamic, the set of accessible methods in the method group is known at compile-time. - For an object creation expression ([§12.8.17.2](expressions.md#128172-object-creation-expressions)) the set of accessible constructors in the type is known at compile-time. -- For an indexer access ([§12.8.12.5](expressions.md#128125-indexer-access)) the set of accessible indexers in the receiver is known at compile-time. +- For an indexer access ([§12.8.12.4](expressions.md#128124-indexer-access)) the set of accessible indexers in the receiver is known at compile-time. In these cases a limited compile-time check is performed on each member in the known set of function members, to see if it can be known for certain never to be invoked at run-time. For each function member `F` a modified parameter and argument list are constructed: @@ -1335,7 +1335,7 @@ The run-time processing of a function member invocation consists of the followin - `M` is invoked. - Otherwise, if the type of `E` is a value-type `V`, and `M` is declared or overridden in `V`: - `E` is evaluated. If this evaluation causes an exception, then no further steps are executed. For an instance constructor, this evaluation consists of allocating storage (typically from an execution stack) for the new object. In this case `E` is classified as a variable. - - If `E` is not classified as a variable, or if `V` is not a readonly struct type ([§16.2.2](structs.md#1622-struct-modifiers)) and `M` is not a readonly function member ([§16.8.12](structs.md#16812-methods)), and `E` is one of: + - If `E` is not classified as a variable, or if `V` is not a readonly struct type ([§16.2.2](structs.md#1622-struct-modifiers)) and `M` is not a readonly function member ([§16.6.12](structs.md#16612-methods)), and `E` is one of: - an input parameter ([§15.6.2.3.2](classes.md#156232-input-parameters)), or - a `readonly` field ([§15.5.3](classes.md#1553-readonly-fields)), or - a `readonly` reference variable or return ([§9.7](variables.md#97-reference-variables-and-returns)), @@ -1624,7 +1624,7 @@ fragment Interpolated_Raw_String_Character multi_line_interpolated_raw_string_expression : Interpolated_Raw_String_Start Whitespace* New_Line - (Interpolated_Raw_String_Mid | New_Line)* New_Line + (Interpolated_Raw_String_Mid | New_Line)* New_Line Whitespace* Interpolated_Raw_String_End ; ``` @@ -1953,7 +1953,7 @@ In a member access of the form `E.I`, if `E` is a single identifier, and if the > > *end example* -With respect to primary constructors ([§15.11.6](classes.md#15116-primary-constructors)), the rule above affects whether an identifier within an instance member should be treated as a type reference, or as a primary constructor parameter reference, which, in turn, captures the parameter into the state of the enclosing type. Even though "the member lookup of `E.I` is never ambiguous," when lookup yields a member group, in some cases it is impossible to determine whether a member access refers to a static member or an instance member without fully resolving (binding) the member access. At the same time, capturing a primary constructor parameter changes properties of enclosing type in a way that affects semantic analysis. For example, the type might become unmanaged and fail certain constraints because of that. There are even scenarios for which binding can succeed either way, depending on whether the parameter is considered captured or not. +With respect to primary constructors (§prim-constructor), the rule above affects whether an identifier within an instance member should be treated as a type reference, or as a primary constructor parameter reference, which, in turn, captures the parameter into the state of the enclosing type. Even though "the member lookup of `E.I` is never ambiguous," when lookup yields a member group, in some cases it is impossible to determine whether a member access refers to a static member or an instance member without fully resolving (binding) the member access. At the same time, capturing a primary constructor parameter changes properties of enclosing type in a way that affects semantic analysis. For example, the type might become unmanaged and fail certain constraints because of that. There are even scenarios for which binding can succeed either way, depending on whether the parameter is considered captured or not. An ambiguity error shall result for a member access `E.I` when all the following conditions are met: @@ -2042,7 +2042,7 @@ A *null_conditional_projection_initializer* is a restriction of *null_conditiona #### 12.8.9.1 General A null-forgiving expression’s value, type, classification ([§12.2](expressions.md#122-expression-classifications)) -and safe-context ([§16.8.15](structs.md#16815-safe-context-constraint)) is the value, type, classification and safe-context of its *primary_expression*. +and safe-context ([§16.6.15](structs.md#16615-safe-context-constraint)) is the value, type, classification and safe-context of its *primary_expression*. ```ANTLR null_forgiving_expression @@ -2469,7 +2469,7 @@ The *primary_expression* of an *element_access* shall not be an *array_creation_ An *element_access* is dynamically bound ([§12.3.3](expressions.md#1233-dynamic-binding)) if at least one of the following holds: - The *primary_expression* has compile-time type `dynamic`. -- At least one expression of the *argument_list* has compile-time type `dynamic`, and the *primary_no_array_creation_expression* does not have an inline array type ([§16.6](structs.md#166-inline-arrays)) or there is more than one *argument* in the *argument_list*. +- At least one expression of the *argument_list* has compile-time type `dynamic`, and the *primary_no_array_creation_expression* does not have an inline array type (§InlineArray) or there is more than one *argument* in the *argument_list*. In this case the compile-time type of the *element_access* depends on the compile-time type of its *primary_expression*: if it has an array type then the compile-time type is the element type of that array type; otherwise the compile-time type is `dynamic` and the *element_access* is classified as a value of type `dynamic`. The rules below to determine the meaning of the *element_access* are then applied at run-time, using the run-time type instead of the compile-time type of those of the *primary_expression* and *argument_list* expressions which have the compile-time type `dynamic`. If the *primary_expression* does not have compile-time type `dynamic`, then the element access undergoes a limited compile-time check as described in [§12.6.5](expressions.md#1265-compile-time-checking-of-dynamic-member-invocation). @@ -2485,15 +2485,15 @@ In this case the compile-time type of the *element_access* depends on the compil > > *end example* -If the *primary_expression* of an *element_access* is a value of an *array_type*, the *element_access* is an array access ([§12.8.12.2](expressions.md#128122-array-access)). Otherwise, if the *primary_no_array_creation_expression* of an *element_access* is a variable or value of an inline array type and the *argument_list* consists of a single argument, the *element_access* is an inline array element access ([§12.8.12.3](expressions.md#128123-inline-array-element-access)). Otherwise, the *primary_no_array_creation_expression* shall be a variable or value of a class, struct, or interface type that has one or more indexer members, in which case the *element_access* is an indexer access ([§12.8.12.5](expressions.md#128125-indexer-access)). +If the *primary_expression* of an *element_access* is a value of an *array_type*, the *element_access* is an array access ([§12.8.12.2](expressions.md#128122-array-access)). Otherwise, if the *primary_no_array_creation_expression* of an *element_access* is a variable or value of an inline array type and the *argument_list* consists of a single argument, the *element_access* is an inline array element access (§InlineArrayElementAccess). Otherwise, the *primary_no_array_creation_expression* shall be a variable or value of a class, struct, or interface type that has one or more indexer members, in which case the *element_access* is an indexer access ([§12.8.12.4](expressions.md#128124-indexer-access)). - a value of an array type, the *element_access* is an array access ([§12.8.12.2](expressions.md#128122-array-access)); -- a value of `string` type, the *element_access* is a string access ([§12.8.12.4](expressions.md#128124-string-access)); -- otherwise, the *primary_expression* shall be a variable or value of a class, struct, or interface type that has one or more indexer members, in which case the *element_access* is an indexer access ([§12.8.12.5](expressions.md#128125-indexer-access)). +- a value of `string` type, the *element_access* is a string access ([§12.8.12.3](expressions.md#128123-string-access)); +- otherwise, the *primary_expression* shall be a variable or value of a class, struct, or interface type that has one or more indexer members, in which case the *element_access* is an indexer access ([§12.8.12.4](expressions.md#128124-indexer-access)). #### 12.8.12.2 Array access -For access to elements in an inline array ([§16.6](structs.md#166-inline-arrays)) see [§12.8.12.3](expressions.md#128123-inline-array-element-access). +For access to elements in an inline array (§InlineArray) see §InlineArrayElementAccess. For an array access the *argument_list* shall not contain named arguments or by-reference arguments ([§15.6.2.3](classes.md#15623-by-reference-parameters)). @@ -2521,16 +2521,16 @@ The run-time processing of an array access of the form `P[A]`, where `P` is a *p -> > > *Note:* A range of elements of an array cannot be assigned to using an array access. This differs from indexer accesses ([§12.8.12.5](expressions.md#128125-indexer-access)) which may, but need not, support assignment to a range of indices specified by a `Range` value. *end note* +> > > *Note:* A range of elements of an array cannot be assigned to using an array access. This differs from indexer accesses ([§12.8.12.4](expressions.md#128124-indexer-access)) which may, but need not, support assignment to a range of indices specified by a `Range` value. *end note* - Otherwise: - The result of evaluating the array access is a variable reference ([§9.5](variables.md#95-variable-references)) of the element type of the array. - The value of each expression in the *argument_list* is checked against the actual bounds of each dimension of the array instance referenced by `P`. If one or more values are out of range, a `System.IndexOutOfRangeException` is thrown and no further steps are executed. - The variable reference of the array element given by the index expressions is computed, and this becomes the result of the array access. -#### 12.8.12.3 Inline array element access +#### §InlineArrayElementAccess Inline array element access -For access to an element in an inline array ([§16.6](structs.md#166-inline-arrays)), the *primary_no_array_creation_expression* of the *element_access* shall designate an inline array. Furthermore, the *argument_list* shall contain a single *argument*, which is not a named argument ([§12.6.2.1](expressions.md#12621-general)). That *argument* shall be of type `int`, or be implicitly convertible to type `int`, `System.Index`, or `System.Range`. +For access to an element in an inline array (§InlineArray), the *primary_no_array_creation_expression* of the *element_access* shall designate an inline array. Furthermore, the *argument_list* shall contain a single *argument*, which is not a named argument ([§12.6.2.1](expressions.md#12621-general)). That *argument* shall be of type `int`, or be implicitly convertible to type `int`, `System.Index`, or `System.Range`. It is a compile-time error if *argument* is a constant expression whose value results in an index outside the bounds of the inline array. If at runtime the value of *argument* results in an index outside the bounds of the inline array, a `System.IndexOutOfRangeException` is thrown. @@ -2616,7 +2616,7 @@ The value of *argument* is converted to `int` and the element access is interpre *argument* is converted to `System.Index` and then to an `int`-based index value indicating the element position relative to the start of the inline array. Then, the element access is interpreted as described when *argument*’s type is `int`. -Using an index of `System.Index` to access an element in a non-inline array is described in [§12.8.12.2](expressions.md#128122-array-access). However, note carefully that that process is *not* used when an inline array is indexed using a `System.Index`. Specifically, an inline array element access ignores any declared indexers in the inline array type. See [§16.6](structs.md#166-inline-arrays) for more information. +Using an index of `System.Index` to access an element in a non-inline array is described in [§12.8.12.2](expressions.md#128122-array-access). However, note carefully that that process is *not* used when an inline array is indexed using a `System.Index`. Specifically, an inline array element access ignores any declared indexers in the inline array type. See §InlineArray for more information. **When *argument*’s type is implicitly convertible to `System.Range`** @@ -2644,7 +2644,7 @@ passing the `int` equivalents of the Range’s start and end Indexes, respective static System.ReadOnlySpan GetSlice(in «InlineArrayType» array) ``` -Using an index of `System.Range` to access an element in a non-inline array is described in [§12.8.12.2](expressions.md#128122-array-access). However, note carefully that that process is *not* used when an inline array is indexed using a `System.Range`. Specifically, an inline array element access ignores any declared Slice methods in the inline array type. See [§16.6](structs.md#166-inline-arrays) for more information. +Using an index of `System.Range` to access an element in a non-inline array is described in [§12.8.12.2](expressions.md#128122-array-access). However, note carefully that that process is *not* used when an inline array is indexed using a `System.Range`. Specifically, an inline array element access ignores any declared Slice methods in the inline array type. See §InlineArray for more information. If *primary_no_array_creation_expression* is a value, an error is reported. @@ -2679,7 +2679,7 @@ If *primary_no_array_creation_expression* is a value, an error is reported. > > *end example* -#### 12.8.12.4 String access +#### 12.8.12.3 String access For a string access the *argument_list* of the *element_access* shall contain a single unnamed value argument ([§15.6.2.2](classes.md#15622-value-parameters)) which shall be: @@ -2707,7 +2707,7 @@ The run-time processing of a string access of the form `P[A]`, where `P` is a *p - The value of the converted index expression is checked against the actual bounds of the string instance referenced by `P`. If the value is out of range, a `System.IndexOutOfRangeException` is thrown and no further steps are executed. - The value of character at the offset of the converted index expression with the string `P` becomes the result of the string access. -#### 12.8.12.5 Indexer access +#### 12.8.12.4 Indexer access For an indexer access, the *primary_expression* of the *element_access* shall be a variable or value of a class, struct, or interface type, and this type shall implement one or more indexers that are applicable with respect to the *argument_list* of the *element_access*. The *argument_list* shall not contain `out` or `ref` arguments. @@ -3812,7 +3812,7 @@ When an instance of a struct `S` having a required member list ([§15.7.1](class A stack allocation expression allocates a block of memory from the execution stack. The ***execution stack*** is an area of memory where local variables are stored. The execution stack is not part of the managed heap. The memory used for local variable storage is automatically recovered when the current function returns. -The safe context rules for a stack allocation expression are described in [§16.8.15.10](structs.md#1681510-stackalloc). +The safe context rules for a stack allocation expression are described in [§16.6.15.10](structs.md#1661510-stackalloc). ```ANTLR stackalloc_expression @@ -3982,7 +3982,7 @@ These are the same transformations applied in [§6.4.3](lexical-structure.md#643 An *anonymous_method_expression* is one of two ways of defining an anonymous function. These are further described in [§12.22](expressions.md#1222-anonymous-function-expressions). -### 12.8.25 Collection expressions +### §collection-expressions Collection expressions A ***collection expression*** is a `[]`-delimited, comma-separated set of zero or more *collection_element*s that together represent a collection. @@ -4005,7 +4005,7 @@ spread_element ; ``` -On its own, a *collection_expression* has no type, but, rather, it is target-typed; that is, depending on the context in which it is used, it is converted ([§10.2.22](conversions.md#10222-implicit-collection-expression-conversions)) to the type of the target (presuming such a conversion is permitted). Any type that supports a *collection_initializer* ([§12.8.17.2.3](expressions.md#1281723-collection-initializers)) may be a target type for a *collection_expression*. A type designated with `CollectionBuilderAttribute` may also be a target type ([§15.17.1](classes.md#15171-general)). +On its own, a *collection_expression* has no type, but, rather, it is target-typed; that is, depending on the context in which it is used, it is converted (§imp-collection-expression-conv) to the type of the target (presuming such a conversion is permitted). Any type that supports a *collection_initializer* ([§12.8.17.2.3](expressions.md#1281723-collection-initializers)) may be a target type for a *collection_expression*. A type designated with `CollectionBuilderAttribute` may also be a target type (§declaring-a-collection-type-general). The *expression* of a *collection_element* need not be a constant. A *collection_expression* is not a compile-time constant, even if all its *collection_element*s are. @@ -4345,7 +4345,7 @@ All non-positional properties being changed shall have both set and init accesso This expression is evaluated as follows: -- For a record class type, the receiver’s clone method ([§15.16.4.4](classes.md#151644-copy-and-clone-members)) is invoked, and its result is converted to the receiver’s type. +- For a record class type, the receiver’s clone method ([§15.16.6.4](classes.md#151664-copy-and-clone-members)) is invoked, and its result is converted to the receiver’s type. - For a record struct or non-record struct type, the receiver is copied. - Each `member_initializer` is processed the same way as an assignment to a field or property access of the result of the conversion. Assignments are processed in lexical order. If *member_initializer_list* is omitted, no members are changed. diff --git a/standard/grammar.md b/standard/grammar.md index f7a678bc5..2504fb8e2 100644 --- a/standard/grammar.md +++ b/standard/grammar.md @@ -995,7 +995,6 @@ primary_expression | pointer_member_access // unsafe code support | pointer_element_access // unsafe code support | stackalloc_expression - | collection_expression ; // Source: §12.8.3 Interpolated string expressions @@ -1166,7 +1165,7 @@ fragment Interpolated_Raw_String_Character multi_line_interpolated_raw_string_expression : Interpolated_Raw_String_Start Whitespace* New_Line - (Interpolated_Raw_String_Mid | New_Line)* New_Line + (Interpolated_Raw_String_Mid | New_Line)* New_Line Whitespace* Interpolated_Raw_String_End ; @@ -1453,24 +1452,6 @@ named_entity_target | qualified_alias_member ; -// Source: §12.8.25 Collection expressions -collection_expression - : '[' (collection_element (',' collection_element)*)? ']' - ; - -collection_element - : expression_element - | spread_element - ; - -expression_element - : expression - ; - -spread_element - : '..' expression - ; - // Source: §12.9.1 General unary_expression : primary_expression @@ -1655,7 +1636,22 @@ anonymous_function_signature ; explicit_anonymous_function_signature - : '(' parameter_list? ')' + : '(' explicit_anonymous_function_parameter_list? ')' + ; + +explicit_anonymous_function_parameter_list + : explicit_anonymous_function_parameter + (',' explicit_anonymous_function_parameter)* + ; + +explicit_anonymous_function_parameter + : attributes? 'scoped'? anonymous_function_parameter_modifier? type identifier + ; + +anonymous_function_parameter_modifier + : 'ref' + | 'out' + | 'in' ; implicit_anonymous_function_signature @@ -2273,7 +2269,7 @@ using_directive // Source: §14.6.2 Using alias directives using_alias_directive - : 'using' 'unsafe'? identifier '=' (namespace_name | type) ';' + : 'using' identifier '=' namespace_or_type_name ';' ; // Source: §14.6.3 Using namespace directives @@ -2283,7 +2279,7 @@ using_namespace_directive // Source: §14.6.4 Using static directives using_static_directive - : 'using' 'static' 'unsafe'? type_name ';' + : 'using' 'static' type_name ';' ; // Source: §14.7 Namespace member declarations @@ -2313,20 +2309,9 @@ class_declaration ; non_record_class_declaration - : non_record_class_without_positional_members - | non_record_class_with_positional_members - ; - -non_record_class_without_positional_members - : attributes? class_modifier* 'partial'? 'class' identifier - type_parameter_list? class_base? - type_parameter_constraints_clause* class_body - ; - -non_record_class_with_positional_members : attributes? class_modifier* 'partial'? 'class' identifier - type_parameter_list? delimited_parameter_list class_base? - type_parameter_constraints_clause* class_body + type_parameter_list? class_base? type_parameter_constraints_clause* + class_body ; // Source: §15.2.2.1 General @@ -2359,10 +2344,6 @@ class_base | ':' class_type base_argument_list? ',' interface_type_list ; -base_argument_list - : '(' argument_list? ')' - ; - interface_type_list : interface_type (',' interface_type)* ; @@ -2403,7 +2384,6 @@ constructor_constraint // Source: §15.2.6 Class body class_body : '{' class_member_declaration* '}' ';'? - | ';' ; // Source: §15.3.1 General @@ -2565,7 +2545,7 @@ parameter_modifier ; parameter_mode_modifier - : ref_kind + : 'ref' | 'out' | 'in' ; @@ -2854,10 +2834,21 @@ finalizer_body // Source: §15.16.1 General record_class_declaration : attributes? class_modifier* 'partial'? 'record' 'class'? identifier - type_parameter_list? delimited_parameter_list? class_base? + type_parameter_list? delimited_parameter_list? class_base? type_parameter_constraints_clause* record_class_body ; +// Source: §15.16.2 Class base specification +base_argument_list + : '(' argument_list? ')' + ; + +// Source: §15.16.3 Record class body +record_class_body + : class_body + | ';' + ; + // Source: §16.2.1 General struct_declaration : non_record_struct_declaration @@ -2865,20 +2856,9 @@ struct_declaration ; non_record_struct_declaration - : non_record_struct_without_positional_members - | non_record_struct_with_positional_members - ; - -non_record_struct_without_positional_members : attributes? struct_modifier* 'ref'? 'partial'? 'struct' identifier type_parameter_list? struct_interfaces? - type_parameter_constraints_clause* struct_body - ; - -non_record_struct_with_positional_members - : attributes? struct_modifier* 'ref'? 'partial'? 'struct' - identifier type_parameter_list? delimited_parameter_list struct_interfaces? - type_parameter_constraints_clause* struct_body + type_parameter_constraints_clause* struct_body ';'? ; record_struct_declaration @@ -2911,8 +2891,7 @@ struct_interfaces // Source: §16.2.6 Struct body struct_body - : '{' struct_member_declaration* '}' ';'? - | ';' + : '{' struct_member_declaration* '}' ; // Source: §16.3.1 General @@ -2930,14 +2909,20 @@ struct_member_declaration | fixed_size_buffer_declaration // unsafe code support ; -// Source: §16.5.1 General +// Source: §16.4.1 General record_struct_declaration : attributes? struct_modifier* 'partial'? 'record' 'struct' identifier type_parameter_list? delimited_parameter_list? struct_interfaces? - type_parameter_constraints_clause* struct_body + type_parameter_constraints_clause* record_struct_body + ; + +// Source: §16.4.3 Record struct body +record_struct_body + : struct_body ';'? + | ';' ; -// Source: §16.8.8.2 Ref fields +// Source: §16.6.8.2 Ref fields struct_field_declaration : attributes? field_modifier* ('readonly'? 'ref' 'readonly'?)? type variable_declarators ';' @@ -2962,7 +2947,7 @@ variable_initializer interface_declaration : attributes? interface_modifier* 'partial'? 'interface' identifier variant_type_parameter_list? interface_base? - type_parameter_constraints_clause* interface_body + type_parameter_constraints_clause* interface_body ';'? ; // Source: §19.2.2 Interface modifiers @@ -2997,8 +2982,7 @@ interface_base // Source: §19.3 Interface body interface_body - : '{' interface_member_declaration* '}' ';'? - | ';' + : '{' interface_member_declaration* '}' ; // Source: §19.4.1 General @@ -3016,7 +3000,7 @@ interface_member_declaration // Source: §20.2 Enum declarations enum_declaration - : attributes? enum_modifier* 'enum' identifier enum_base? enum_body + : attributes? enum_modifier* 'enum' identifier enum_base? enum_body ';'? ; enum_base @@ -3029,9 +3013,8 @@ integral_type_name ; enum_body - : '{' enum_member_declarations? '}' ';'? - | '{' enum_member_declarations ',' '}' ';'? - | ';' + : '{' enum_member_declarations? '}' + | '{' enum_member_declarations ',' '}' ; // Source: §20.3 Enum modifiers @@ -3179,7 +3162,7 @@ dataptr_type // Source: §24.3.3 Function pointers funcptr_type - : 'delegate' '*' calling_convention_specifier? + : 'delegate' '*' calling_convention_specifier? '<' funcptr_parameter_list funcptr_return_type '>' ; diff --git a/standard/interfaces.md b/standard/interfaces.md index db1bf8475..78a82fe52 100644 --- a/standard/interfaces.md +++ b/standard/interfaces.md @@ -575,11 +575,11 @@ For a type `T` that is a struct or a class that implements interfaces `I2` and ` ### 19.4.11 Interface member access -Interface members are accessed through member access ([§12.8.7](expressions.md#1287-member-access)) and indexer access ([§12.8.12.5](expressions.md#128125-indexer-access)) expressions of the form `I.M` and `I[A]`, where `I` is an interface type, `M` is a constant, field, method, property, or event of that interface type, and `A` is an indexer argument list. +Interface members are accessed through member access ([§12.8.7](expressions.md#1287-member-access)) and indexer access ([§12.8.12.4](expressions.md#128124-indexer-access)) expressions of the form `I.M` and `I[A]`, where `I` is an interface type, `M` is a constant, field, method, property, or event of that interface type, and `A` is an indexer argument list. In a class `D`, with direct or indirect base class `B`, where `B` directly or indirectly implements interface `I` and `I` defines a method `M()`, the expression `base.M()` is valid only if `base.M()` staticly ([§12.3](expressions.md#123-static-and-dynamic-binding)) binds to an implementation of `M()` in a class type. -For interfaces that are strictly single-inheritance (each interface in the inheritance chain has exactly zero or one direct base interface), the effects of the member lookup ([§12.5](expressions.md#125-member-lookup)), method invocation ([§12.8.10.2](expressions.md#128102-method-invocations)), and indexer access ([§12.8.12.5](expressions.md#128125-indexer-access)) rules are exactly the same as for classes and structs: More derived members hide less derived members with the same name or signature. However, for multiple-inheritance interfaces, ambiguities can occur when two or more unrelated base interfaces declare members with the same name or signature. This subclause shows several examples, some of which lead to ambiguities and others which do not. In all cases, explicit casts can be used to resolve the ambiguities. +For interfaces that are strictly single-inheritance (each interface in the inheritance chain has exactly zero or one direct base interface), the effects of the member lookup ([§12.5](expressions.md#125-member-lookup)), method invocation ([§12.8.10.2](expressions.md#128102-method-invocations)), and indexer access ([§12.8.12.4](expressions.md#128124-indexer-access)) rules are exactly the same as for classes and structs: More derived members hide less derived members with the same name or signature. However, for multiple-inheritance interfaces, ambiguities can occur when two or more unrelated base interfaces declare members with the same name or signature. This subclause shows several examples, some of which lead to ambiguities and others which do not. In all cases, explicit casts can be used to resolve the ambiguities. > *Example*: In the following code > diff --git a/standard/ranges.md b/standard/ranges.md index a243b62a7..ed01e8a66 100644 --- a/standard/ranges.md +++ b/standard/ranges.md @@ -16,7 +16,7 @@ Under the model a type is classified as: > *Note*: The model does not require that a slice of the type can be set, but a type may support it as an extension of the model. *end note* -The model is supported for single-dimensional arrays ([§12.8.12.2](expressions.md#128122-array-access)) and strings ([§12.8.12.4](expressions.md#128124-string-access)). +The model is supported for single-dimensional arrays ([§12.8.12.2](expressions.md#128122-array-access)) and strings ([§12.8.12.3](expressions.md#128123-string-access)). The model can be supported by any class, struct or interface type which provides appropriate indexers ([§15.9](classes.md#159-indexers)) which implement the model semantics. @@ -143,8 +143,8 @@ This method does **not** check that the return value is in the valid range of `0 `Index` values may be directly used in the *argument_list* of an *element_access* expression ([§12.8.12](expressions.md#12812-element-access)) which is: - an array access and the target is a single-dimensional array ([§12.8.12.2](expressions.md#128122-array-access)); -- a string access ([§12.8.12.4](expressions.md#128124-string-access)) -- an indexer access and the target type has an indexer with corresponding parameters of either `Index` type ([§12.8.12.5](expressions.md#128125-indexer-access)) or of a type to which `Index` values are implicitly convertible; or +- a string access ([§12.8.12.3](expressions.md#128123-string-access)) +- an indexer access and the target type has an indexer with corresponding parameters of either `Index` type ([§12.8.12.4](expressions.md#128124-indexer-access)) or of a type to which `Index` values are implicitly convertible; or - an indexer access and the target type conforms to a sequence pattern for which implicit `Index` support is specified ([§18.4.2](ranges.md#1842-implicit-index-support)). ## 18.3 The Range type @@ -259,9 +259,9 @@ A concrete range value is *empty* if `N` is zero. An empty concrete range may ha `Range` values can be directly used in the *argument_list* of an *element_access* expression ([§12.8.12](expressions.md#12812-element-access)) which is: - an array access and the target is a single-dimensional array ([§12.8.12.2](expressions.md#128122-array-access)); -- a string access ([§12.8.12.4](expressions.md#128124-string-access)); -- an indexer access and the target type has an indexer with corresponding parameters of either `Range` type ([§12.8.12.5](expressions.md#128125-indexer-access)) or of a type to which `Range` values are implicitly convertible; or -- an indexer access ([§12.8.12.5](expressions.md#128125-indexer-access)) and the target type conforms to a sequence pattern for which implicit `Range` support is specified ([§18.4.3](ranges.md#1843-implicit-range-support)). +- a string access ([§12.8.12.3](expressions.md#128123-string-access)); +- an indexer access and the target type has an indexer with corresponding parameters of either `Range` type ([§12.8.12.4](expressions.md#128124-indexer-access)) or of a type to which `Range` values are implicitly convertible; or +- an indexer access ([§12.8.12.4](expressions.md#128124-indexer-access)) and the target type conforms to a sequence pattern for which implicit `Range` support is specified ([§18.4.3](ranges.md#1843-implicit-range-support)). ## 18.4 Pattern-based implicit support for Index and Range @@ -270,8 +270,8 @@ A concrete range value is *empty* if `N` is zero. An empty concrete range may ha If an *element_access* expression ([§12.8.12](expressions.md#12812-element-access)) of the form `E[A]`; where `E` has type `T` and `A` is a single expression implicitly convertible to `Index` or `Range`; fails to be identified as: - an array access ([§12.8.12.2](expressions.md#128122-array-access)), -- a string access ([§12.8.12.4](expressions.md#128124-string-access)), or -- an indexer access ([§12.8.12.5](expressions.md#128125-indexer-access)) as `T` provides no suitable accessible indexer +- a string access ([§12.8.12.3](expressions.md#128123-string-access)), or +- an indexer access ([§12.8.12.4](expressions.md#128124-indexer-access)) as `T` provides no suitable accessible indexer then implicit support for the expression is provided if `T` conforms to a particular pattern. If `T` does not conform to this pattern then a compile-time error occurs. diff --git a/standard/structs.md b/standard/structs.md index fe4864a62..6afc30857 100644 --- a/standard/structs.md +++ b/standard/structs.md @@ -49,13 +49,13 @@ record_struct_body ; ``` -There are two kinds of struct: ***non-record struct***, as declared by *non_record_struct_declaration*, and ***record struct***, as declared by *record_struct_declaration*. A non-record struct is the kind of struct that C# has supported since the language’s inception. Record structs were added much later and are discussed in [§16.5](structs.md#165-record-structs). The differences between the two kinds are discussed in [§16.7](structs.md#167-record-struct-and-non-record-struct-differences). +There are two kinds of struct: ***non-record struct***, as declared by *non_record_struct_declaration*, and ***record struct***, as declared by *record_struct_declaration*. A non-record struct is the kind of struct that C# has supported since the language’s inception. Record structs were added much later and are discussed in [§16.4](structs.md#164-record-structs). The differences between the two kinds are discussed in [§16.5](structs.md#165-record-struct-and-non-record-struct-differences). A *non_record_struct_declaration* can have one of two almost identical forms: *non_record_struct_without_positional_members* and *non_record_struct_with_positional_members*. A *non_record_struct_without_positional_members* consists of an optional set of *attributes* ([§23](attributes.md#23-attributes)), followed by an optional set of *struct_modifier*s ([§16.2.2](structs.md#1622-struct-modifiers)), followed by an optional `ref` modifier ([§16.2.3](structs.md#1623-ref-modifier)), followed by an optional partial modifier ([§15.2.7](classes.md#1527-partial-type-declarations)), followed by the keyword `struct` and an *identifier* that names the struct, followed by an optional *type_parameter_list* specification ([§15.2.3](classes.md#1523-type-parameters)), followed by an optional *struct_interfaces* specification ([§16.2.5](structs.md#1625-struct-interfaces)), followed by an optional *type_parameter_constraints-clauses* specification ([§15.2.5](classes.md#1525-type-parameter-constraints)), followed by a *struct_body* ([§16.2.6](structs.md#1626-struct-body)), optionally followed by a semicolon. -A *non_record_struct_with_positional_members* has the same syntax but requires a *delimited_parameter_list*, as shown above in that grammar rule. For a discussion of *delimited_parameter_list*, see [§15.11.6](classes.md#15116-primary-constructors). +A *non_record_struct_with_positional_members* has the same syntax but requires a *delimited_parameter_list*, as shown above in that grammar rule. For a discussion of *delimited_parameter_list*, see §prim-constructor. A struct having a required member ([§15.7.1](classes.md#1571-general)) directly (that is, not through inheritance) shall be treated as if it were decorated with the attribute `System.Runtime.CompilerServices.RequiredMemberAttribute` ([§23.5.12.2](attributes.md#235122-the-requiredmember-attribute)). A *struct_declaration* shall not supply *type_parameter_constraints_clause*s unless it also supplies a *type_parameter_list*. @@ -100,7 +100,7 @@ When an instance of a readonly struct is passed to a method, its `this` is treat ### 16.2.3 Ref modifier -The `ref` modifier indicates that the *non_record_struct_declaration* declares a type whose instances are allocated on the execution stack. These types are called ***ref struct*** types. The `ref` modifier declares that instances may contain ref-like fields, and shall not be copied out of its safe-context ([§16.8.15](structs.md#16815-safe-context-constraint)). The rules for determining the safe context of a ref struct are described in [§16.8.15](structs.md#16815-safe-context-constraint). +The `ref` modifier indicates that the *non_record_struct_declaration* declares a type whose instances are allocated on the execution stack. These types are called ***ref struct*** types. The `ref` modifier declares that instances may contain ref-like fields, and shall not be copied out of its safe-context ([§16.6.15](structs.md#16615-safe-context-constraint)). The rules for determining the safe context of a ref struct are described in [§16.6.15](structs.md#16615-safe-context-constraint). It is a compile-time error if a ref struct type is used in any of the following contexts: @@ -158,7 +158,7 @@ The *struct_body*s `{}`, `{};`, and `;` are equivalent, and the *struct_body*s ` ### 16.3.1 General -The members of a struct consist of the members introduced by its *struct_member_declaration*s, the members inherited from the type `System.ValueType``, and any members implicitly provided by the implementation ([§16.5.3](structs.md#1653-implicit-record-struct-members)). +The members of a struct consist of the members introduced by its *struct_member_declaration*s, the members inherited from the type `System.ValueType``, and any members implicitly provided by the implementation ([§16.4.4](structs.md#1644-implicit-record-struct-members)). ```ANTLR struct_member_declaration @@ -178,11 +178,11 @@ struct_member_declaration *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)). -> *Note*: A *struct_member_declaration* includes all *class_member_declaration* alternatives except *finalizer_declaration*, and adds *struct_field_declaration* which supports ref fields ([§16.8.8.2](structs.md#16882-ref-fields)). *end note* +> *Note*: A *struct_member_declaration* includes all *class_member_declaration* alternatives except *finalizer_declaration*, and adds *struct_field_declaration* which supports ref fields ([§16.6.8.2](structs.md#16682-ref-fields)). *end note* -Fields in structs support capabilities not supported in classes. See [§16.8.8.2](structs.md#16882-ref-fields) for details. +Fields in structs support capabilities not supported in classes. See [§16.6.8.2](structs.md#16682-ref-fields) for details. -Except for the differences noted in [§16.8](structs.md#168-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. +Except for the differences noted in [§16.6](structs.md#166-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. ### 16.3.2 Readonly members @@ -224,17 +224,17 @@ An instance member definition or accessor of an instance property, indexer, or e > > The `readonly` method `AddMessage` can change the state of a message list. The `InitializeMessages` member can clear and re-initialize the list of messages. In the case of `AddMessage`, the `readonly` modifier is valid. In the case of `InitializeMessages`, adding the `readonly` modifier is invalid. *end example* -## 16.4 Primary constructors +## §struct-prim-constructors Primary constructors -As with a non-record class, a non-record struct with a *delimited_parameter_list* has a primary constructor ([§15.11.6](classes.md#15116-primary-constructors)) provided by the implementation. The semantics of the non-record class version apply here as well and are augmented by the text in this subclause. +As with a non-record class, a non-record struct with a *delimited_parameter_list* has a primary constructor (§prim-constructor) provided by the implementation. The semantics of the non-record class version apply here as well and are augmented by the text in this subclause. In the case of a non-record class, the implementation shall provide a private, init-only field for each parameter. However, for a non-record struct, the storage is read-write and provided in some unspecified manner. Instance field declarations for a non-record struct are permitted to include variable initializers. If there is no primary constructor, the instance initializers execute as part of the parameterless constructor. Otherwise, at runtime the primary constructor executes the instance initializers appearing in the *struct_body*. -## 16.5 Record structs +## 16.4 Record structs -### 16.5.1 General +### 16.4.1 General A record struct is a specialized value type that is optimized for storing data rather than behavior. It provides built-in functionality that would normally require significant “boilerplate” code in a non-record struct, such as value-based equality and easy immutability. @@ -254,29 +254,29 @@ At most only one *record_struct_declaration* containing `partial` may provide a The parameters in *delimited_parameter_list* shall not have `ref`, `out` or `this` modifiers; however, `in` and `params` modifiers are permitted. -### 16.5.2 Struct members +### 16.4.2 Struct members It is an error for a member of a record struct to be named `Clone`. It is an error for an instance field of a record struct to have an unsafe type. -### 16.5.3 Implicit record struct members +### 16.4.4 Implicit record struct members -#### 16.5.3.1 General +#### 16.4.4.1 General In the case of a record struct, members are provided by the implementation unless a member with a “matching” signature is declared in the *struct_body* or an accessible concrete non-virtual member with a “matching” signature is inherited. A matching member prevents the implementation from providing that member only, not any other provided members. Two members are considered matching if they have the same signature or would be considered “hiding” in an inheritance scenario. (See Signatures and overloading [§7.5](basic-concepts.md#75-signatures-and-overloading).) The members provided by the implementation are described in the following subclauses. -#### 16.5.3.2 Primary constructors +#### 16.4.4.2 Primary constructors -The primary constructor of a record struct is like that of a non-record struct ([§16.4](structs.md#164-primary-constructors)), with the following difference: Each parameter value is stored in a corresponding private instance field having a corresponding property with set and get accessors. +The primary constructor of a record struct is like that of a non-record struct (§struct-prim-constructors), with the following difference: Each parameter value is stored in a corresponding private instance field having a corresponding property with set and get accessors. Instance field declarations for a non-record struct are permitted to include variable initializers. If there is no primary constructor, the instance initializers execute as part of the parameterless constructor. Otherwise, at runtime the primary constructor executes the instance initializers appearing in the *struct_body*. -#### 16.5.3.3 Equality members +#### 16.4.4.3 Equality members -The provided equality members are similar to those for a record class ([§15.16.4.3](classes.md#151643-equality-members)), except for the lack of method `EqualityContract`, null checks, or inheritance. +The provided equality members are similar to those for a record class ([§15.16.6.3](classes.md#151663-equality-members)), except for the lack of method `EqualityContract`, null checks, or inheritance. A record struct `R` implements `System.IEquatable` and includes a synthesized strongly-typed overload of `Equals(R other)`, which is public, as follows: @@ -354,7 +354,7 @@ The provided override of `GetHashCode()` shall return an `int` result of combini > > *end example* -#### 16.5.3.4 Printing members +#### 16.4.4.4 Printing members A record struct includes a provided method, declared as follows: @@ -441,23 +441,23 @@ This method performs the following tasks: > > *end example* -#### 16.5.3.5 Positional record struct members +#### 16.4.4.5 Positional record struct members -##### 16.5.3.5.1 General +##### 16.4.4.5.1 General As well as providing the members described in the preceding subclauses, positional record structs ([§16.2.1](structs.md#1621-general)) result in the implementation providing additional members with the same conditions as the other provided members, as described in the following subclauses. -##### 16.5.3.5.2 Primary constructor +##### 16.4.4.5.2 Primary constructor -As with a record class, a record struct with a *delimited_parameter_list* has a primary constructor ([§15.16.4.6.2](classes.md#1516462-primary-constructor)) provided by the implementation. The semantics of the record class version apply here as well and are augmented by the text in this subclause. +As with a record class, a record struct with a *delimited_parameter_list* has a primary constructor ([§15.16.6.6.2](classes.md#1516662-primary-constructor)) provided by the implementation. The semantics of the record class version apply here as well and are augmented by the text in this subclause. In the case of a record class, the implementation shall provide a private, init-only field for each parameter. However, for a record struct, the storage is read-write and provided in some unspecified manner. Instance field declarations for a record struct are permitted to include variable initializers. If there is no primary constructor, the instance initializers execute as part of the parameterless constructor. Otherwise, at runtime the primary constructor executes the instance initializers appearing in the *record_struct_body*. -The definite assignment rules for struct instance constructors ([§16.8.9](structs.md#1689-constructors), [§12.8.14](expressions.md#12814-this-access)) apply to the primary constructor of record structs. As for any other struct instance constructor without a `this()` initializer, any instance field that is not definitely assigned by the primary constructor is implicitly initialized to its default value in the initialization phase that runs before the body of the primary constructor. +The definite assignment rules for struct instance constructors ([§16.6.9](structs.md#1669-constructors), [§12.8.14](expressions.md#12814-this-access)) apply to the primary constructor of record structs. As for any other struct instance constructor without a `this()` initializer, any instance field that is not definitely assigned by the primary constructor is implicitly initialized to its default value in the initialization phase that runs before the body of the primary constructor. -##### 16.5.3.5.3 Properties +##### 16.4.4.5.3 Properties For each parameter of a *delimited_parameter_list* that has the same name and type as an explicitly declared instance field, the remainder of this subclause does not apply. @@ -479,16 +479,16 @@ For a record struct: - Attributes may be applied to the provided auto-property and its backing field by using `property:` or `field:` targets, respectively, for attributes syntactically applied to the corresponding record struct parameter. -##### 16.5.3.5.4 Deconstruct +##### 16.4.4.5.4 Deconstruct A positional record struct with at least one parameter provides a public `void`-returning instance method called `Deconstruct` with an out parameter declaration for each parameter of the primary constructor declaration. Each parameter of `Deconstruct` has the same type as the corresponding parameter of the primary constructor declaration. The body of the method assigns each parameter of the Deconstruct method to the value from an instance member access to a member of the same name. If the instance members accessed in the body do not include a property with a non-`readonly` `get` accessor, then the synthesized `Deconstruct` method is `readonly`. The method can be declared explicitly. It is an error if the explicit declaration does not match the expected signature or accessibility, or is static. -## 16.6 Inline arrays +## §InlineArray Inline arrays -A struct type decorated with the attribute `System.Runtime.CompilerServices.InlineArrayAttribute` ([§23.5.14](attributes.md#23514-the-inlinearray-attribute)) is an ***inline array type***, which is a managed type. An instance of that type is an ***inline array***, a structure that contains a contiguous block of a given number of elements of the same type, and nothing else. It’s the safe-code equivalent of unsafe-code’s fixed-size buffer ([§24.8](unsafe-code.md#248-fixed-size-buffers)). +A struct type decorated with the attribute `System.Runtime.CompilerServices.InlineArrayAttribute` (§InlineArrayAttribute) is an ***inline array type***, which is a managed type. An instance of that type is an ***inline array***, a structure that contains a contiguous block of a given number of elements of the same type, and nothing else. It’s the safe-code equivalent of unsafe-code’s fixed-size buffer ([§24.8](unsafe-code.md#248-fixed-size-buffers)). With some limitations (see later below), an inline array can be used like an array ([§17](arrays.md#17-arrays)). @@ -545,7 +545,7 @@ There are a number of restrictions on the instance field’s declaration: An inline array is a collection; as such, it can be iterated over by a `foreach` statement, as shown. -The elements of the inline array can be accessed for read or write via subscripting ([§12.8.12.3](expressions.md#128123-inline-array-element-access)). +The elements of the inline array can be accessed for read or write via subscripting (§InlineArrayElementAccess). A list pattern ([§11.2.11](patterns.md#11211-list-pattern)) shall not be used in the context of an inline array. @@ -555,7 +555,7 @@ Any indexers or `Slice` methods declared for an inline array type that have sign > *Example*: Consider the following: > > -> ```csharp +```csharp > var buffer = new Buffer(); > int x = buffer[2]; // element access > @@ -575,7 +575,7 @@ Any indexers or `Slice` methods declared for an inline array type that have sign > > Even though the struct declares an indexer taking an `int` argument, that indexer is not used by element access `buffer[2]`. *end example* -## 16.7 Record struct and non-record struct differences +## 16.5 Record struct and non-record struct differences A record struct differs from a non-record struct in several important ways: @@ -586,22 +586,22 @@ A record struct differs from a non-record struct in several important ways: - It shall not have a member called `Clone`. - It shall not have an instance field with an unsafe type. -## 16.8 Class and struct differences +## 16.6 Class and struct differences -### 16.8.1 General +### 16.6.1 General Structs differ from classes in several important ways: -- Structs are value types ([§16.8.2](structs.md#1682-value-semantics)). -- All struct types implicitly inherit from the class `System.ValueType` ([§16.8.3](structs.md#1683-inheritance)). -- Assignment to a variable of a struct type creates a *copy* of the value being assigned ([§16.8.4](structs.md#1684-assignment)). -- The default value of a struct is the value produced by setting all fields to their default value ([§16.8.5](structs.md#1685-default-values)). -- Boxing and unboxing operations are used to convert between a struct type and certain reference types ([§16.8.6](structs.md#1686-boxing-and-unboxing)). -- The meaning of `this` is different within struct members ([§16.8.7](structs.md#1687-meaning-of-this)). +- Structs are value types ([§16.6.2](structs.md#1662-value-semantics)). +- All struct types implicitly inherit from the class `System.ValueType` ([§16.6.3](structs.md#1663-inheritance)). +- Assignment to a variable of a struct type creates a *copy* of the value being assigned ([§16.6.4](structs.md#1664-assignment)). +- The default value of a struct is the value produced by setting all fields to their default value ([§16.6.5](structs.md#1665-default-values)). +- Boxing and unboxing operations are used to convert between a struct type and certain reference types ([§16.6.6](structs.md#1666-boxing-and-unboxing)). +- The meaning of `this` is different within struct members ([§16.6.7](structs.md#1667-meaning-of-this)). - 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.8.2 Value semantics +### 16.6.2 Value semantics Structs are value types ([§8.3](types.md#83-value-types)) and are said to have value semantics. Classes, on the other hand, are reference types ([§8.2](types.md#82-reference-types)) and are said to have reference semantics. @@ -668,7 +668,7 @@ With classes, it is possible for two variables to reference the same object, and > > *end example* -### 16.8.3 Inheritance +### 16.6.3 Inheritance All struct types implicitly inherit from the class `System.ValueType`, which, in turn, inherits from class `object`. A struct declaration may specify a list of implemented interfaces, but it is not possible for a struct declaration to specify a base class. @@ -678,7 +678,7 @@ Since inheritance is not supported for structs, the declared accessibility of a Function members in a struct cannot be abstract or virtual, and the `override` modifier is allowed only to override methods inherited from `System.ValueType`. -### 16.8.4 Assignment +### 16.6.4 Assignment Assignment to a variable of a struct type creates a *copy* of the value being assigned. This differs from assignment to a variable of a class type, which copies the reference but not the object identified by the reference. @@ -686,7 +686,7 @@ Similar to an assignment, when a struct is passed as a value parameter or return When a property or indexer of a struct is the target of an assignment, the instance expression associated with the property or indexer access shall be classified as a variable. If the instance expression is classified as a value, a compile-time error occurs. This is described in further detail in [§12.24.2](expressions.md#12242-simple-assignment). -### 16.8.5 Default values +### 16.6.5 Default values As described in [§9.3](variables.md#93-default-values), several kinds of variables are automatically initialized to their default value when they are created. For variables of class types and other reference types, as well as reference variable fields, this default value is `null`. However, since structs are value types that cannot be `null`, the default value of a struct is the value produced by setting all value type fields to their default value and all reference variable fields and reference type fields to `null`. @@ -701,7 +701,7 @@ As described in [§9.3](variables.md#93-default-values), several kinds of variab > > *end example* -The default value of a struct corresponds to the value returned by the default constructor of the struct ([§8.3.3](types.md#833-default-constructors)). When a struct does not declare an explicit parameterless instance constructor, the default constructor is synthesized and always returns the value that results from setting all fields to their default values. The `default` expression always produces the zero-initialized default value, even when a struct declares an explicit parameterless instance constructor ([§16.8.9](structs.md#1689-constructors)). +The default value of a struct corresponds to the value returned by the default constructor of the struct ([§8.3.3](types.md#833-default-constructors)). When a struct does not declare an explicit parameterless instance constructor, the default constructor is synthesized and always returns the value that results from setting all fields to their default values. The `default` expression always produces the zero-initialized default value, even when a struct declares an explicit parameterless instance constructor ([§16.6.9](structs.md#1669-constructors)). > *Note*: Structs should be designed to consider the default initialization state a valid state. In the example > @@ -729,7 +729,7 @@ The default value of a struct corresponds to the value returned by the default c > > *end note* -### 16.8.6 Boxing and unboxing +### 16.6.6 Boxing and unboxing A value of a class type can be converted to type `object` or to an interface type that is implemented by the class simply by treating the reference as another type at compile-time. Likewise, a value of type `object` or a value of an interface type can be converted back to a class type without changing the reference (but, of course, a run-time type check is required in this case). @@ -739,7 +739,7 @@ Since structs are not reference types, these operations are implemented differen For further details on boxing and unboxing, see [§10.2.9](conversions.md#1029-boxing-conversions) and [§10.3.7](conversions.md#1037-unboxing-conversions). -### 16.8.7 Meaning of this +### 16.6.7 Meaning of this The meaning of `this` in a struct differs from the meaning of `this` in a class, as described in [§12.8.14](expressions.md#12814-this-access). When a struct type overrides a virtual method inherited from `System.ValueType` (such as `Equals`, `GetHashCode`, or `ToString`), invocation of the virtual method through an instance of the struct type does not cause boxing to occur. This is true even when the struct is used as a type parameter and the invocation occurs through an instance of the type parameter type. @@ -829,11 +829,11 @@ Similarly, boxing never implicitly occurs when accessing a member on a constrain > > *end example* -### 16.8.8 Fields +### 16.6.8 Fields -#### 16.8.8.1 Field initializers +#### 16.6.8.1 Field initializers -As described in [§16.8.5](structs.md#1685-default-values), the default value of a struct consists of the value that results from setting all value type and reference variable fields to their default value and all reference type fields to `null`. Static and instance fields of a struct are permitted to include variable initializers; however, in the case of an instance field initializer, at least one instance constructor shall also be declared, or for a record struct, a *delimited_parameter_list* shall be present. +As described in [§16.6.5](structs.md#1665-default-values), the default value of a struct consists of the value that results from setting all value type and reference variable fields to their default value and all reference type fields to `null`. Static and instance fields of a struct are permitted to include variable initializers; however, in the case of an instance field initializer, at least one instance constructor shall also be declared, or for a record struct, a *delimited_parameter_list* shall be present. > *Example*: > @@ -867,7 +867,7 @@ When a struct instance constructor has a `this()` constructor initializer that r A *field_declaration* declared directly inside a *struct_declaration* having the *struct_modifier* `readonly` shall have the *field_modifier* `readonly`. -#### 16.8.8.2 Ref fields +#### 16.6.8.2 Ref fields ```ANTLR struct_field_declaration @@ -925,7 +925,7 @@ readonly ref struct RoS `roRefToRwData` is a read-only reference variable, whose referent is seen as a writable `int`. `roRefToRoData` is a read-only reference variable, whose referent is seen as a read-only `int`. The read/write field `rwField` can be written directly, and via the reference variable `roRefToRwData`. -### 16.8.9 Constructors +### 16.6.9 Constructors 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. @@ -1027,16 +1027,16 @@ For a struct instance constructor that does not have a `this()` initializer, any > > *end example*] -### 16.8.10 Static constructors +### 16.6.10 Static constructors Static constructors for structs follow most of the same rules as for classes. The execution of a static constructor for a struct type is triggered by the first of the following events to occur within an application domain: - A static member of the struct type is referenced. - An explicitly declared constructor of the struct type is called. -> *Note*: The creation of default values ([§16.8.5](structs.md#1685-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* +> *Note*: The creation of default values ([§16.6.5](structs.md#1665-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.8.11 Properties +### 16.6.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. @@ -1063,7 +1063,7 @@ Automatically implemented properties ([§15.7.4](classes.md#1574-automatically-i > *Note*: Because the backing field of an auto-property of a struct type is implicitly initialized to its default value in the initialization phase of an instance constructor that does not assign it ([§12.8.14](expressions.md#12814-this-access)), an explicit constructor initializer is not required in order to satisfy the definite-assignment rules for that backing field. *end note* -### 16.8.12 Methods +### 16.6.12 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. @@ -1075,7 +1075,7 @@ A readonly method may call a sibling property or indexer set accessor that is re All *method_declaration*s of a partial method shall have a `readonly` modifier, or none of them shall have it. -### 16.8.13 Indexers +### 16.6.13 Indexers An *indexer_declaration* ([§15.9](classes.md#159-indexers)) for an instance indexer in a *struct_declaration* may contain the *indexer_modifier* `readonly`. @@ -1087,13 +1087,13 @@ It is a compile-time error for an indexer to have a readonly modifier on all of > *Note*: To correct the error, move the modifier from the accessors to the indexer itself. *end note* -### 16.8.14 Events +### 16.6.14 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.8.15 Safe context constraint +### 16.6.15 Safe context constraint -#### 16.8.15.1 General +#### 16.6.15.1 General At compile-time, each expression is associated with a context where that instance and all its fields can be safely accessed, its ***safe-context***. The safe-context is a context, enclosing an expression, which it is safe for the value to escape to. @@ -1113,7 +1113,7 @@ There are four different safe-context values, the same as the ref-safe-context v - For an assignment `e1 = e2` the safe-context of `e2` shall be at least as wide a context as the safe-context of `e1`. - For an assignment to an `out` parameter, the safe-context of the right-hand side shall be at least return-only. -#### 16.8.15.2 Parameter safe context +#### 16.6.15.2 Parameter safe context A parameter of a ref struct type, including the `this` parameter of an instance method, has a safe-context of caller-context. @@ -1121,7 +1121,7 @@ An `out` parameter of a ref struct type has a safe-context of return-only. A `this` parameter in a struct constructor has a safe-context of return-only. -#### 16.8.15.3 Local variable safe context +#### 16.6.15.3 Local variable safe context A local variable of a ref struct type has a safe-context as follows: @@ -1131,19 +1131,19 @@ A local variable of a ref struct type has a safe-context as follows: See [§9.7.2.1](variables.md#9721-general) and [§9.7.2.2](variables.md#9722-local-variable-ref-safe-context). -#### 16.8.15.4 Field safe context +#### 16.6.15.4 Field safe context A reference to a field `e.F`, where the type of `F` is a ref struct type, has a safe-context that is the same as the safe-context of `e`. -#### 16.8.15.5 Operators +#### 16.6.15.5 Operators -The application of a user-defined operator is treated as a method invocation ([§16.8.15.6](structs.md#168156-method-and-property-invocation)). +The application of a user-defined operator is treated as a method invocation ([§16.6.15.6](structs.md#166156-method-and-property-invocation)). For an operator that yields a value, such as `e1 + e2` or `c ? e1 : e2`, the safe-context of the result is the narrowest context among the safe-contexts of the operands of the operator. As a consequence, for a unary operator that yields a value, such as `+e`, the safe-context of the result is the safe-context of the operand. > *Note*: The first operand of a conditional operator is a `bool`, so its safe-context is caller-context. It follows that the resulting safe-context is the narrowest safe-context of the second and third operand. *end note* -#### 16.8.15.6 Method and property invocation +#### 16.6.15.6 Method and property invocation A value resulting from a method invocation `e1.M(e2, ...)` or property invocation `e.P`, where `M()` does not return ref-to-ref-struct, has safe-context of the smallest of the following contexts: @@ -1192,7 +1192,7 @@ A property invocation (either `get` or `set`) is treated as a method invocation > > *end example* -#### 16.8.15.7 Method arguments must match +#### 16.6.15.7 Method arguments must match For any method invocation `e.M(a1, a2, ... aN)`: @@ -1237,7 +1237,7 @@ The presence of `scoped` allows developers to reduce the friction this rule crea > > *end example* -#### 16.8.15.8 Infer safe-context of declaration expressions +#### 16.6.15.8 Infer safe-context of declaration expressions The safe-context of a declaration variable from an `out` argument (`M(x, out var y)`) or deconstruction (`(var x, var y) = M()`) is the narrowest of the following: @@ -1277,7 +1277,7 @@ The safe-context of a declaration variable from an `out` argument (`M(x, out var > > *end example* -#### 16.8.15.9 Object initializer safe context +#### 16.6.15.9 Object initializer safe context The safe-context of an object initializer expression is the narrowest of: @@ -1320,12 +1320,12 @@ The safe-context of an object initializer expression is the narrowest of: > > *end example* -#### 16.8.15.10 stackalloc +#### 16.6.15.10 stackalloc The result of a stackalloc expression has safe-context of function-member. -#### 16.8.15.11 Constructor invocations +#### 16.6.15.11 Constructor invocations A `new` expression that invokes a constructor obeys the same rules as a method invocation that is considered to return the type being constructed. -In addition the safe-context is the smallest of the safe-contexts of all arguments and operands of all object initializer expressions, recursively, if any initializer is present. See [§16.8.15.9](structs.md#168159-object-initializer-safe-context) for details. +In addition the safe-context is the smallest of the safe-contexts of all arguments and operands of all object initializer expressions, recursively, if any initializer is present. See [§16.6.15.9](structs.md#166159-object-initializer-safe-context) for details. diff --git a/standard/types.md b/standard/types.md index 631824230..db2c89099 100644 --- a/standard/types.md +++ b/standard/types.md @@ -272,7 +272,7 @@ Like any other instance constructor, the default constructor of a value type is > > *end example* -A struct type is permitted to declare instance constructors, including a parameterless instance constructor. An explicitly declared parameterless instance constructor shall have public accessibility ([§16.8.9](structs.md#1689-constructors)). +A struct type is permitted to declare instance constructors, including a parameterless instance constructor. An explicitly declared parameterless instance constructor shall have public accessibility ([§16.6.9](structs.md#1669-constructors)). ### 8.3.4 Struct types diff --git a/standard/unsafe-code.md b/standard/unsafe-code.md index c4a7a960a..6021cb3d4 100644 --- a/standard/unsafe-code.md +++ b/standard/unsafe-code.md @@ -276,7 +276,7 @@ A ***function pointer*** is a pointer capable of containing the address of a sta ```ANTLR funcptr_type - : 'delegate' '*' calling_convention_specifier? + : 'delegate' '*' calling_convention_specifier? '<' funcptr_parameter_list funcptr_return_type '>' ; @@ -1139,7 +1139,7 @@ fixed_size_buffer_declarator ; ``` -A fixed-size buffer declaration may include a set of attributes ([§23](attributes.md#23-attributes)), a `new` modifier ([§15.3.5](classes.md#1535-the-new-modifier)), accessibility modifiers corresponding to any of the declared accessibilities permitted for struct members ([§16.8.3](structs.md#1683-inheritance)) and an `unsafe` modifier ([§24.2](unsafe-code.md#242-unsafe-contexts)). The attributes and modifiers apply to all of the members declared by the fixed-size buffer declaration. It is an error for the same modifier to appear multiple times in a fixed-size buffer declaration. +A fixed-size buffer declaration may include a set of attributes ([§23](attributes.md#23-attributes)), a `new` modifier ([§15.3.5](classes.md#1535-the-new-modifier)), accessibility modifiers corresponding to any of the declared accessibilities permitted for struct members ([§16.6.3](structs.md#1663-inheritance)) and an `unsafe` modifier ([§24.2](unsafe-code.md#242-unsafe-contexts)). The attributes and modifiers apply to all of the members declared by the fixed-size buffer declaration. It is an error for the same modifier to appear multiple times in a fixed-size buffer declaration. A fixed-size buffer declaration is not permitted to include the `static` modifier. diff --git a/standard/variables.md b/standard/variables.md index 6cece3267..ef6ac2ff9 100644 --- a/standard/variables.md +++ b/standard/variables.md @@ -1237,7 +1237,7 @@ A ***reference return*** is the *variable_reference* returned from a returns-by- All reference variables obey safety rules that ensure the ref-safe-context of the reference variable is not greater than the ref-safe-context of its referent. -> *Note*: The related notion of a *safe-context* is defined in ([§16.8.15](structs.md#16815-safe-context-constraint)), along with associated constraints. *end note* +> *Note*: The related notion of a *safe-context* is defined in ([§16.6.15](structs.md#16615-safe-context-constraint)), along with associated constraints. *end note* For any variable, the ***ref-safe-context*** of that variable is the context where a *variable_reference* ([§9.5](variables.md#95-variable-references)) to that variable is valid. The referent of a reference variable shall have a ref-safe-context that is at least as wide as the ref-safe-context of the reference variable itself. @@ -1429,7 +1429,7 @@ The conditional operator ([§12.21](expressions.md#1221-conditional-operator)), For a variable `c` resulting from a ref-returning function invocation, `ref e1.M(e2, ...)`, where `M()` does not return ref-to-ref-struct, its ref-safe-context is the narrowest of the following contexts: - The caller-context. -- The safe-context ([§16.8.15](structs.md#16815-safe-context-constraint)) contributed by all argument expressions (including the receiver), excluding arguments corresponding to `scoped` parameters and excluding `out` arguments. +- The safe-context ([§16.6.15](structs.md#16615-safe-context-constraint)) contributed by all argument expressions (including the receiver), excluding arguments corresponding to `scoped` parameters and excluding `out` arguments. - The ref-safe-context contributed by all `ref` and `ref readonly` arguments, excluding those corresponding to `scoped ref` parameters and excluding `out` arguments. If `M()` does return ref-to-ref-struct, the ref-safe-context is the narrowest ref-safe-context contributed by all arguments which are ref-to-ref-struct. @@ -1483,7 +1483,7 @@ A `new` expression that invokes a constructor obeys the same rules as a method i ### 9.7.3 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.8.15](structs.md#16815-safe-context-constraint)) of a variable. The presence of this modifier requires 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.6.15](structs.md#16615-safe-context-constraint)) of a variable. The presence of this modifier requires that related code doesn’t extend the lifetime of the variable. `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.