Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions standard/classes.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -4941,6 +4941,9 @@ operator_modifier
: 'public'
| 'static'
| 'extern'
| 'abstract'
| 'virtual'
| 'sealed'
| unsafe_modifier // unsafe code support
;

Expand Down Expand Up @@ -4992,7 +4995,7 @@ There are three categories of overloadable operators: Unary operators ([§15.10.

The *operator_body* is either a semicolon, a block body ([§15.6.1](classes.md#1561-general)) or an expression body ([§15.6.1](classes.md#1561-general)). A block body consists of a *block*, which specifies the statements to execute when the operator is invoked. The *block* shall conform to the rules for value-returning methods described in [§15.6.11](classes.md#15611-method-body). An expression body consists of `=>` followed by an expression and a semicolon, and denotes a single expression to perform when the operator is invoked.

For `extern` operators, the *operator_body* consists simply of a semicolon. For all other operators, the *operator_body* is either a block body or an expression body.
For `extern` operators, the *operator_body* consists simply of a semicolon. For an abstract operator declaration in an interface ([§19.4.7](interfaces.md#1947-interface-operators)), the *operator_body* is a semicolon. For all other operators, the *operator_body* is either a block body or an expression body.

The following rules apply to all operator declarations:

Expand Down
21 changes: 16 additions & 5 deletions standard/conversions.md
Original file line number Diff line number Diff line change
Expand Up @@ -761,9 +761,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 does not 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, `D₁`, from which user-defined conversion operators will be considered. This set consists of `S₀` (if `S₀` is a class or struct), the base classes of `S₀` (if `S₀` is a class), and `T₀` (if `T₀` is a class or struct).
- 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 `S` to a type encompassed by `T`.
- If `U₁` is not empty, then `U` is `U₁`. Otherwise,
- Find the set of types, `D₂`, 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, `U₂`. This set consists of the user-defined and lifted implicit conversion operators declared by the interfaces in `D₂` that convert from a type encompassing `S` to a type encompassed by `T`.
- If `U₂` is not empty, then `U` is `U₂`.
- 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.
Expand All @@ -789,8 +794,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 does not 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, `D₁`, from which user-defined conversion operators will be considered. This set consists of `S₀` (if `S₀` is a class or struct), the base classes of `S₀` (if `S₀` is a class), `T₀` (if `T₀` is a class or struct), and the base classes of `T₀` (if `T₀` is a class).
- 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 or encompassed by `S` to a type encompassing or encompassed by `T`.
- If `U₁` is not empty, then `U` is `U₁`. Otherwise,
- Find the set of types, `D₂`, 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, `U₂`. This set consists of the user-defined and lifted implicit or explicit conversion operators declared by the interfaces in `D₂` that convert from a type encompassing or encompassed by `S` to a type encompassing or encompassed by `T`.
- If `U₂` is not empty, then `U` is `U₂`.
- 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.
Expand Down
Loading
Loading