diff --git a/standard/classes.md b/standard/classes.md index 594d56fb5..2c29f60e1 100644 --- a/standard/classes.md +++ b/standard/classes.md @@ -2184,9 +2184,9 @@ 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)). Additionally a *method_declaration* that is contained directly by a *struct_declaration* may include the `readonly` modifier ([§16.5.12](structs.md#16512-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.5.12](structs.md#16512-methods)). -A declaration has a valid combination of modifiers if all of the following are true: +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).): - The declaration includes a valid combination of access modifiers ([§15.3.6](classes.md#1536-access-modifiers)). - The declaration does not include the same modifier multiple times. diff --git a/standard/conversions.md b/standard/conversions.md index 39acaacc0..be8683bfd 100644 --- a/standard/conversions.md +++ b/standard/conversions.md @@ -741,9 +741,14 @@ A user-defined implicit conversion from an expression `E` to a type `T` is pro - If `E` has a type, let `S` be that type. - If `S` or `T` are nullable value types, let `Sᵢ` and `Tᵢ` be their underlying types, otherwise let `Sᵢ` and `Tᵢ` be `S` and `T`, respectively. - If `Sᵢ` or `Tᵢ` are type parameters, let `S₀` and `T₀` be their effective base classes, otherwise let `S₀` and `T₀` be `Sᵢ` and `Tᵢ`, respectively. -- Find the set of types, `D`, from which user-defined conversion operators will be considered. This set consists of `S₀` (if `S₀` exists and is a class or struct), the base classes of `S₀` (if `S₀` exists and is a class), and `T₀` (if `T₀` is a class or struct). A type is added to the set `D` only if an identity conversion to another type already included in the set doesn’t exist. - -- Find the set of applicable user-defined and lifted conversion operators, `U`. This set consists of the user-defined and lifted implicit conversion operators declared by the classes or structs in `D` that convert from a type encompassing `E` to a type encompassed by `T`. If `U` is empty, the conversion is undefined and a compile-time error occurs. +- Find the set of applicable user-defined and lifted conversion operators, `U`. + - Find the set of types, `D1`, from which user-defined conversion operators will be considered. This set consists of `S0` (if `S0` is a class or struct), the base classes of `S0` (if `S0` is a class), and `T0` (if `T0` is a class or struct). + - Find the set of applicable user-defined and lifted conversion operators, `U1`. This set consists of the user-defined and lifted implicit conversion operators declared by the classes or structs in `D1` that convert from a type encompassing `S` to a type encompassed by `T`. + - If `U1` is not empty, then `U` is `U1`. Otherwise, + - Find the set of types, `D2`, from which user-defined conversion operators will be considered. This set consists of `Sᵢ` *effective interface set* and their base interfaces (if `Sᵢ` is a type parameter), and `Tᵢ` *effective interface set* (if `Tᵢ` is a type parameter). + - Find the set of applicable user-defined and lifted conversion operators, `U2`. This set consists of the user-defined and lifted implicit conversion operators declared by the interfaces in `D2` that convert from a type encompassing `S` to a type encompassed by `T`. + - If `U2` is not empty, then `U` is `U2`. +- If `U` is empty, the conversion is undefined and a compile-time error occurs. - Find the most-specific source type, `Sₓ`, of the operators in `U`: - If `S` exists and any of the operators in `U` convert from `S`, then `Sₓ` is `S`. - Otherwise, `Sₓ` is the most-encompassed type in the combined set of source types of the operators in `U`. If exactly one most-encompassed type cannot be found, then the conversion is ambiguous and a compile-time error occurs. @@ -769,8 +774,14 @@ A user-defined explicit conversion from an expression `E` to a type `T` is pro - If `E` has a type, let `S` be that type. - If `S` or `T` are nullable value types, let `Sᵢ` and `Tᵢ` be their underlying types, otherwise let `Sᵢ` and `Tᵢ` be `S` and `T`, respectively. - If `Sᵢ` or `Tᵢ` are type parameters, let `S₀` and `T₀` be their effective base classes, otherwise let `S₀` and `T₀` be `Sᵢ` and `Tᵢ`, respectively. -- Find the set of types, `D`, from which user-defined conversion operators will be considered. This set consists of `S₀` (if `S₀` exists and is a class or struct), the base classes of `S₀` (if `S₀` exists and is a class), `T₀` (if `T₀` is a class or struct), and the base classes of `T₀` (if `T₀` is a class). A type is added to the set `D` only if an identity conversion to another type already included in the set doesn’t exist. -- Find the set of applicable user-defined and lifted conversion operators, `U`. This set consists of the user-defined and lifted implicit or explicit conversion operators declared by the classes or structs in `D` that convert from a type encompassing `E` or encompassed by `S` (if it exists) to a type encompassing or encompassed by `T`. If `U` is empty, the conversion is undefined and a compile-time error occurs. +- Find the set of applicable user-defined and lifted conversion operators, `U`. + - Find the set of types, `D1`, from which user-defined conversion operators will be considered. This set consists of `S0` (if `S0` is a class or struct), the base classes of `S0` (if `S0` is a class), `T0` (if `T0` is a class or struct), and the base classes of `T0` (if `T0` is a class). + - Find the set of applicable user-defined and lifted conversion operators, `U1`. This set consists of the user-defined and lifted implicit or explicit conversion operators declared by the classes or structs in `D1` that convert from a type encompassing or encompassed by `S` to a type encompassing or encompassed by `T`. + - If `U1` is not empty, then `U` is `U1`. Otherwise, + - Find the set of types, `D2`, from which user-defined conversion operators will be considered. This set consists of `Sᵢ` *effective interface set* and their base interfaces (if `Sᵢ` is a type parameter), and `Tᵢ` *effective interface set* and their base interfaces (if `Tᵢ` is a type parameter). + - Find the set of applicable user-defined and lifted conversion operators, `U2`. This set consists of the user-defined and lifted implicit or explicit conversion operators declared by the interfaces in `D2` that convert from a type encompassing or encompassed by `S` to a type encompassing or encompassed by `T`. + - If `U2` is not empty, then `U` is `U2`. +- If `U` is empty, the conversion is undefined and a compile-time error occurs. - Find the most-specific source type, `Sₓ`, of the operators in `U`: - If `S` exists and any of the operators in `U` convert from `S`, then `Sₓ` is `S`. - Otherwise, if any of the operators in `U` convert from types that encompass `E`, then `Sₓ` is the most-encompassed type in the combined set of source types of those operators. If no most-encompassed type can be found, then the conversion is ambiguous and a compile-time error occurs. diff --git a/standard/interfaces.md b/standard/interfaces.md index 666042de0..0e1166b96 100644 --- a/standard/interfaces.md +++ b/standard/interfaces.md @@ -94,7 +94,7 @@ If a generic interface is declared in multiple parts ([§15.2.3](classes.md#1523 #### 19.2.3.2 Variance safety -The occurrence of variance annotations in the type parameter list of a type restricts the places where types can occur within the type declaration. However, these restrictions do not apply to occurrences of types within a declaration of a static member. +The occurrence of variance annotations in the type parameter list of a type restricts the places where types can occur within the type declaration. However, these restrictions do not apply to occurrences of types within a declaration of a non-virtual, non-abstract static member. A type `T` is ***output-unsafe*** if one of the following holds: @@ -233,15 +233,15 @@ interface_member_declaration ; ``` -This clause augments the description of members in classes ([§15.3](classes.md#153-class-members)) with the differences and restrictions for interfaces: +This subclause augments the description of members in classes ([§15.3](classes.md#153-class-members)) with the differences and restrictions for interfaces: - A *finalizer_declaration* is not allowed. - Instance constructors, *constructor_declaration*s, are not allowed. - All interface members implicitly have public access; however, an explicit access modifier ([§7.5.2](basic-concepts.md#752-declared-accessibility)) is permitted except on static constructors ([§15.12](classes.md#1512-static-constructors)). -- The `abstract` modifier is implied for interface function members ([§12.6](expressions.md#126-function-members)) without bodies; that modifier may be given explicitly. -- An interface instance function member whose declaration includes a body is an implicitly `virtual` member unless the `sealed` or `private` modifier is used. The `virtual` modifier may be given explicitly. +- The `abstract` modifier is implied for interface instance function members ([§12.6](expressions.md#126-function-members)) without bodies; that modifier may be given explicitly. For interface static function members without bodies the `abstract` modifier shall be present. +- An interface instance function member whose declaration includes a body is an implicitly `virtual` member unless the `sealed` or `private` modifier is used. The `virtual` modifier may be given explicitly. An interface static member whose declaration includes a body may have a `virtual` modifier. - A `private` or `sealed` function member of an interface shall have a body. -- A `private` function member shall not have the modifier `sealed`. +- A `private` instance function member shall not have the modifier `sealed`. - A derived interface may override an abstract or virtual member declared in a base interface. - An explicitly implemented function member shall not have the modifier `sealed`. @@ -429,7 +429,7 @@ A virtual method with implementation declared in an interface may be overridden ### 19.4.4 Interface properties -This clause augments the description of properties in classes [§15.7](classes.md#157-properties) for properties declared in interfaces. +This subclause augments the description of properties in classes [§15.7](classes.md#157-properties) for properties declared in interfaces. Interface properties are declared using *property_declaration*s ([§15.7.1](classes.md#1571-general)) with the following additional rules: @@ -440,25 +440,27 @@ Interface properties are declared using *property_declaration*s ([§15.7.1](clas > *Note*: As an interface cannot contain instance fields, an interface property cannot be an instance auto-property, as that would require the declaration of implicit hidden instance fields. *end note* - The type of an interface property shall be output-safe if there is a get accessor, and shall be input-safe if there is a set or init accessor. -- An interface method declaration that has a block body or expression body as a *method_body* is `virtual`; the `virtual` modifier is not required, but is allowed. -- An instance *property_declaration* that has no implementation is `abstract`; the `abstract` modifier is not required, but is allowed. It is *never* considered to be an automatically implemented property ([§15.7.4](classes.md#1574-automatically-implemented-properties)). +- An interface instance method declaration that has a block body or expression body as a *method_body* is `virtual`; the `virtual` modifier is not required, but is allowed. For a static method the `virtual` modifier is permitted. +- An instance *property_declaration* that has no implementation is `abstract`; the `abstract` modifier is not required, but is allowed. It is *never* considered to be an automatically implemented property ([§15.7.4](classes.md#1574-automatically-implemented-properties)). However, the `abstract` modifier shall be present if a static property is to be abstract. +- A *property_declaration* may contain the `sealed` modifier. ### 19.4.5 Interface events -This clause augments the description of events in classes [§15.8](classes.md#158-events) for events declared in interfaces. +This subclause augments the description of events in classes [§15.8](classes.md#158-events) for events declared in interfaces. Interface events are declared using *event_declaration*s ([§15.8.1](classes.md#1581-general)), with the following additional rules: - *event_modifier* shall not include `override`. - A derived interface may implement an abstract interface event declared in a base interface ([§15.8.5](classes.md#1585-virtual-sealed-override-and-abstract-accessors)). - It is a compile-time error for *variable_declarators* in an instance *event_declaration* to contain any *variable_initializer*s. -- An instance event with the `virtual` or `sealed` modifiers must declare accessors. It is *never* considered to be an automatically implemented field-like event ([§15.8.2](classes.md#1582-field-like-events)). -- An instance event with the `abstract` modifier must not declare accessors. +- An instance event with the `virtual` or `sealed` modifiers shall declare accessors. It is *never* considered to be an automatically implemented field-like event ([§15.8.2](classes.md#1582-field-like-events)). +- An instance event with the `abstract` modifier shall not declare accessors. +- A static event may have `abstract`, `virtual`, and `sealed` modifiers. - The type of an interface event shall be input-safe. ### 19.4.6 Interface indexers -This clause augments the description of indexers in classes [§15.9](classes.md#159-indexers) for indexers declared in interfaces. +This sub clause augments the description of indexers in classes [§15.9](classes.md#159-indexers) for indexers declared in interfaces. Interface indexers are declared using *indexer_declaration*s ([§15.9](classes.md#159-indexers)), with the following additional rules: @@ -474,15 +476,20 @@ Interface indexers are declared using *indexer_declaration*s ([§15.9](classes.m ### 19.4.7 Interface operators -This clause augments the description of *operator_declaration* members in classes [§15.10](classes.md#1510-operators) for operators declared in interfaces. +This subclause augments the description of *operator_declaration* members in classes [§15.10](classes.md#1510-operators) for operators declared in interfaces. For an *operator_declaration* in an interface the *operator_body* shall only be a block body ([§15.6.1](classes.md#1561-general)) or an expression body ([§15.6.1](classes.md#1561-general)). -It is a compile-time error for an interface to declare a conversion, equality, or inequality operator. +A static *operator_declaration* may have `abstract`, `virtual`, and `sealed` modifiers. + +In the context of a class or struct, at least one of the *fixed_parameter*s in a *unary_operator_declarator* and *binary_operator_declarator* is required to have type `T` or `T?`, where `T` is the instance type of the enclosing type. This requirement is relaxed in the context of an interface in that a restricted operand is allowed to be of a type parameter that counts as “the instance type of the enclosing type.” In order for a type parameter `T` to count as that it shall meet the following requirements: + +- `T` is a direct type parameter on the interface in which the operator declaration occurs, and +- `T` is directly constrained by the instance type; i.e., the surrounding interface with its own type parameters used as type arguments. ### 19.4.8 Interface static constructors -This clause augments the description of static constructors in classes [§15.12](classes.md#1512-static-constructors) for static constructors declared in interfaces. +This subclause augments the description of static constructors in classes [§15.12](classes.md#1512-static-constructors) for static constructors declared in interfaces. The static constructor for a closed ([§8.4.3](types.md#843-open-and-closed-types)) interface executes at most once in a given application domain. The execution of a static constructor is triggered by the first of the following actions to occur within an application domain: @@ -498,7 +505,7 @@ To initialize a new closed interface type, first a new set of static fields for ### 19.4.9 Interface nested types -This clause augments the description of nested types in classes [§15.3.9](classes.md#1539-nested-types) for nested types declared in interfaces. +This subclause augments the description of nested types in classes [§15.3.9](classes.md#1539-nested-types) for nested types declared in interfaces. It is an error to declare a class type, struct type, or enum type within the scope of a type parameter that was declared with a *variance_annotation* ([§19.2.3.1](interfaces.md#19231-general)). @@ -949,6 +956,8 @@ The qualified interface member name of an explicit interface member implementati > > *end example* +An explicit interface member implementation that implements a static member shall itself be static. + ### 19.6.3 Uniqueness of implemented interfaces The interfaces implemented by a generic type declaration shall remain unique for all possible constructed types. Without this rule, it would be impossible to determine the correct method to call for certain constructed types. diff --git a/standard/patterns.md b/standard/patterns.md index 301adb22c..294c5da9a 100644 --- a/standard/patterns.md +++ b/standard/patterns.md @@ -447,9 +447,9 @@ relational_pattern Relational patterns support the relational operators `<`, `<=`, `>`, and `>=` on all of the built-in types that support such binary relational operators with both operands having the same type: `sbyte`, `byte`, `short`, `ushort`, `int`, `uint`, `long`, `ulong`, `char`, `float`, `double`, `decimal`, `nint`, `nuint`, and enums. -It is a compile-time error if `constant_expression`is `double.NaN`, `float.NaN`, or `null_literal`. +It is a compile-time error if *constant_expression*is `double.NaN`, `float.NaN`, or `null_literal`. -When the input value has a type for which a suitable built-in binary relational operator is defined, the evaluation of that operator is taken as the meaning of the relational pattern. Otherwise, the input value is converted to the type of `constant_expression` using an explicit nullable or unboxing conversion. It is a compile-time error if no such conversion exists. The pattern is considered to not match if the conversion fails. If the conversion succeeds, the result of the pattern-matching operation is the result of evaluating the expression `e «op» v` where `e` is the converted input, «op» is the relational operator, and `v` is the `constant_expression`. +When the input value has a type for which a suitable built-in binary relational operator is defined, the evaluation of that operator is taken as the meaning of the relational pattern. Otherwise, the input value is converted to the type of *constant_expression* using an explicit nullable or unboxing conversion. It is a compile-time error if no such conversion exists. It is a compile-time error if the input type is a type parameter constrained to, or a type inheriting, from `System.Numerics.INumberBase` and the input type has no suitable built-in binary relational operator defined. The pattern is considered to not match if the conversion fails. If the conversion succeeds, the result of the pattern-matching operation is the result of evaluating the expression `e «op» v` where `e` is the converted input, «op» is the relational operator, and `v` is the *constant_expression*. > *Example*: >