From 7ce9585c3104b2dc33f738bb02b5f09430dabb22 Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Thu, 10 Dec 2020 14:33:57 -0500 Subject: [PATCH 01/15] Update expressions.md --- standard/expressions.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/standard/expressions.md b/standard/expressions.md index e0823b247..e79de3ecf 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -2851,6 +2851,36 @@ named_entity_target ; ``` +### §throw-expression-operator-new-clause The throw expression operator + +```antlr +throw_expression + : 'throw' null_coalescing_expression + ; +``` + +A *throw_expression* throws the value produced by evaluating the *null_coalescing_expression*, which shall denote a value of the class type `System.Exception`, a value of a class type that derives from `System.Exception` or a value of a type parameter type that has `System.Exception` (or a subclass thereof) as its effective base class. If evaluation of the expression produces `null`, a `System.NullReferenceException` shall be thrown instead. + +The behavior at runtime of the evaluation of a *throw expression* is the same as specified for a *throw statement* ([§13.10.6](expressions.md#13106-the-throw-statement)). + +The type rules are as follows: + +- A *throw_expression* has no type. +- A *throw_expression* is convertible to every type by an implicit conversion. + +The flow-analysis rules are as follows: + +- For every variable *v*, *v* is definitely assigned before the *null_coalescing_expression* of a *throw_expression* iff it is definitely assigned before the *throw_expression*. +- For every variable *v*, *v* is definitely assigned after *throw_expression*. + +A *throw expression* shall only occur in the following syntactic contexts: + +- As the second or third operand of a ternary conditional operator (`?:`), but not both. +- As the second operand of a null coalescing operator (`??`). +- As the body of an expression-bodied lambda or method. + +## 12.8 Unary operators + Because `nameof` is not a keyword, a *nameof_expression* is always syntactically ambiguous with an invocation of the simple name `nameof`. For compatibility reasons, if a name lookup ([§11.7.4](expressions.md#1174-simple-names)) of the name `nameof` succeeds, the expression is treated as an *invocation_expression* — regardless of whether the invocation is valid. Otherwise it is a *nameof_expression*. Simple name and member access lookups are performed on the *named_entity* at compile time, following the rules described in [§11.7.4](expressions.md#1174-simple-names) and [§11.7.6](expressions.md#1176-member-access). However, where the lookup described in [§11.7.4](expressions.md#1174-simple-names) and [§11.7.6](expressions.md#1176-member-access) results in an error because an instance member was found in a static context, a *nameof_expression* produces no such error. @@ -4218,6 +4248,7 @@ The `??` operator is called the null coalescing operator. null_coalescing_expression : conditional_or_expression | conditional_or_expression '??' null_coalescing_expression + | throw_expression ; ``` From bc4e68b34c554e6407cb8496013fe5b95cd5ffad Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Sat, 2 Apr 2022 14:39:53 -0400 Subject: [PATCH 02/15] build fixes --- standard/expressions.md | 58 ++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/standard/expressions.md b/standard/expressions.md index e79de3ecf..fa69076d9 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -2851,36 +2851,6 @@ named_entity_target ; ``` -### §throw-expression-operator-new-clause The throw expression operator - -```antlr -throw_expression - : 'throw' null_coalescing_expression - ; -``` - -A *throw_expression* throws the value produced by evaluating the *null_coalescing_expression*, which shall denote a value of the class type `System.Exception`, a value of a class type that derives from `System.Exception` or a value of a type parameter type that has `System.Exception` (or a subclass thereof) as its effective base class. If evaluation of the expression produces `null`, a `System.NullReferenceException` shall be thrown instead. - -The behavior at runtime of the evaluation of a *throw expression* is the same as specified for a *throw statement* ([§13.10.6](expressions.md#13106-the-throw-statement)). - -The type rules are as follows: - -- A *throw_expression* has no type. -- A *throw_expression* is convertible to every type by an implicit conversion. - -The flow-analysis rules are as follows: - -- For every variable *v*, *v* is definitely assigned before the *null_coalescing_expression* of a *throw_expression* iff it is definitely assigned before the *throw_expression*. -- For every variable *v*, *v* is definitely assigned after *throw_expression*. - -A *throw expression* shall only occur in the following syntactic contexts: - -- As the second or third operand of a ternary conditional operator (`?:`), but not both. -- As the second operand of a null coalescing operator (`??`). -- As the body of an expression-bodied lambda or method. - -## 12.8 Unary operators - Because `nameof` is not a keyword, a *nameof_expression* is always syntactically ambiguous with an invocation of the simple name `nameof`. For compatibility reasons, if a name lookup ([§11.7.4](expressions.md#1174-simple-names)) of the name `nameof` succeeds, the expression is treated as an *invocation_expression* — regardless of whether the invocation is valid. Otherwise it is a *nameof_expression*. Simple name and member access lookups are performed on the *named_entity* at compile time, following the rules described in [§11.7.4](expressions.md#1174-simple-names) and [§11.7.6](expressions.md#1176-member-access). However, where the lookup described in [§11.7.4](expressions.md#1174-simple-names) and [§11.7.6](expressions.md#1176-member-access) results in an error because an instance member was found in a static context, a *nameof_expression* produces no such error. @@ -2949,6 +2919,34 @@ 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 [§11.16](expressions.md#1116-anonymous-function-expressions). +### §throw-expression-operator-new-clause The throw expression operator + +```ANTLR +throw_expression + : 'throw' null_coalescing_expression + ; +``` + +A *throw_expression* throws the value produced by evaluating the *null_coalescing_expression*, which shall denote a value of the class type `System.Exception`, a value of a class type that derives from `System.Exception` or a value of a type parameter type that has `System.Exception` (or a subclass thereof) as its effective base class. If evaluation of the expression produces `null`, a `System.NullReferenceException` shall be thrown instead. + +The behavior at runtime of the evaluation of a *throw expression* is the same as specified for a *throw statement* ([§12.10.6](statements.md#12106-the-throw-statement)). + +The type rules are as follows: + +- A *throw_expression* has no type. +- A *throw_expression* is convertible to every type by an implicit conversion. + +The flow-analysis rules are as follows: + +- For every variable *v*, *v* is definitely assigned before the *null_coalescing_expression* of a *throw_expression* iff it is definitely assigned before the *throw_expression*. +- For every variable *v*, *v* is definitely assigned after *throw_expression*. + +A *throw expression* shall only occur in the following syntactic contexts: + +- As the second or third operand of a ternary conditional operator (`?:`), but not both. +- As the second operand of a null coalescing operator (`??`). +- As the body of an expression-bodied lambda or method. + ## 11.8 Unary operators ### 11.8.1 General From dfd3fe08c184117664cec9fb178e0427bd846ccf Mon Sep 17 00:00:00 2001 From: Neal Gafter Date: Wed, 13 Jul 2022 17:09:03 -0700 Subject: [PATCH 03/15] Minor changes to bring this in line with the spec style and organization. --- standard/conversions.md | 5 +++++ standard/expressions.md | 14 ++------------ standard/variables.md | 9 +++++++++ 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/standard/conversions.md b/standard/conversions.md index b701ad097..6c8193b91 100644 --- a/standard/conversions.md +++ b/standard/conversions.md @@ -59,6 +59,7 @@ The following conversions are classified as implicit conversions: - Null literal conversions - Implicit nullable conversions - Lifted user-defined implicit conversions +- Implicit throw conversion Implicit conversions can occur in a variety of situations, including function member invocations ([§11.6.6](expressions.md#1166-function-member-invocation)), cast expressions ([§11.8.7](expressions.md#1187-cast-expressions)), and assignments ([§11.18](expressions.md#1118-assignment-operators)). @@ -301,6 +302,10 @@ A user-defined implicit conversion consists of an optional standard implicit con Anonymous functions and method groups do not have types in and of themselves, but they may be implicitly converted to delegate types. Additionally, some lambda expressions may be implicitly converted to expression tree types. Anonymous function conversions are described in more detail in [§10.7](conversions.md#107-anonymous-function-conversions) and method group conversions in [§10.8](conversions.md#108-method-group-conversions). +### 10.2.14 Implicit throw conversions + +While throw expressions do not have a type, they may be implicitly convertied to any type. + ## 10.3 Explicit conversions ### 10.3.1 General diff --git a/standard/expressions.md b/standard/expressions.md index fa69076d9..df11f54a9 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -2927,19 +2927,9 @@ throw_expression ; ``` -A *throw_expression* throws the value produced by evaluating the *null_coalescing_expression*, which shall denote a value of the class type `System.Exception`, a value of a class type that derives from `System.Exception` or a value of a type parameter type that has `System.Exception` (or a subclass thereof) as its effective base class. If evaluation of the expression produces `null`, a `System.NullReferenceException` shall be thrown instead. +A *throw_expression* throws the value produced by evaluating the *null_coalescing_expression*. The expression shall be implicitly convertible to `System.Exception`, and the result of evaluating the expression is converted to `System.Exception` before being thrown. The behavior at runtime of the evaluation of a *throw expression* is the same as specified for a *throw statement* ([§12.10.6](statements.md#12106-the-throw-statement)). -The behavior at runtime of the evaluation of a *throw expression* is the same as specified for a *throw statement* ([§12.10.6](statements.md#12106-the-throw-statement)). - -The type rules are as follows: - -- A *throw_expression* has no type. -- A *throw_expression* is convertible to every type by an implicit conversion. - -The flow-analysis rules are as follows: - -- For every variable *v*, *v* is definitely assigned before the *null_coalescing_expression* of a *throw_expression* iff it is definitely assigned before the *throw_expression*. -- For every variable *v*, *v* is definitely assigned after *throw_expression*. +A *throw_expression* has no type. A *throw_expression* is convertible to every type by an *implicit throw conversion*. A *throw expression* shall only occur in the following syntactic contexts: diff --git a/standard/variables.md b/standard/variables.md index 658d681b8..4d94df663 100644 --- a/standard/variables.md +++ b/standard/variables.md @@ -802,6 +802,15 @@ For a *lambda_expression* or *anonymous_method_expression* *expr* with a body (e > > *end example* +#### 9.4.4.32 Throw expressions + +For an expression *expr* of the form: + +`throw` *thrown_expr* + +- The definite assignment state of *v* before *thrown_expr* is the same as the state of *v* before *expr*. +- The definite assignment state of *v* after *expr* is "definitely assigned". + ## 9.5 Variable references A *variable_reference* is an *expression* that is classified as a variable. A *variable_reference* denotes a storage location that can be accessed both to fetch the current value and to store a new value. From dbdeecb32993afdee8805d3fc818353975773dae Mon Sep 17 00:00:00 2001 From: Neal Gafter Date: Wed, 13 Jul 2022 17:20:29 -0700 Subject: [PATCH 04/15] Expression bodied member can be a throw expression. --- standard/expressions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/standard/expressions.md b/standard/expressions.md index df11f54a9..90af7dd5b 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -2933,9 +2933,9 @@ A *throw_expression* has no type. A *throw_expression* is convertible to every t A *throw expression* shall only occur in the following syntactic contexts: -- As the second or third operand of a ternary conditional operator (`?:`), but not both. +- As the second or third operand of a ternary conditional operator (`?:`). - As the second operand of a null coalescing operator (`??`). -- As the body of an expression-bodied lambda or method. +- As the body of an expression-bodied lambda or member. ## 11.8 Unary operators From e3a545afc42c5247324990b25e819e4aac8c570d Mon Sep 17 00:00:00 2001 From: Neal Gafter Date: Wed, 13 Jul 2022 17:38:09 -0700 Subject: [PATCH 05/15] Add throw expression as a category into which an expression may be classified. --- standard/expressions.md | 1 + 1 file changed, 1 insertion(+) diff --git a/standard/expressions.md b/standard/expressions.md index 90af7dd5b..20b2c3397 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -24,6 +24,7 @@ For expressions which occur as subexpressions of larger expressions, with the no - A type. An expression with this classification can only appear as the left-hand side of a *member_access* ([§11.7.6](expressions.md#1176-member-access)). In any other context, an expression classified as a type causes a compile-time error. - A method group, which is a set of overloaded methods resulting from a member lookup ([§11.5](expressions.md#115-member-lookup)). A method group may have an associated instance expression and an associated type argument list. When an instance method is invoked, the result of evaluating the instance expression becomes the instance represented by `this` ([§11.7.12](expressions.md#11712-this-access)). A method group is permitted in an *invocation_expression* ([§11.7.8](expressions.md#1178-invocation-expressions)) or a *delegate_creation_expression* ([§11.7.15.6](expressions.md#117156-delegate-creation-expressions)), and can be implicitly converted to a compatible delegate type ([§10.8](conversions.md#108-method-group-conversions)). In any other context, an expression classified as a method group causes a compile-time error. - An event access. Every event access has an associated type, namely the type of the event. Furthermore, an event access may have an associated instance expression. An event access may appear as the left-hand operand of the `+=` and `-=` operators ([§11.18.4](expressions.md#11184-event-assignment)). In any other context, an expression classified as an event access causes a compile-time error. When an accessor of an instance event access is invoked, the result of evaluating the instance expression becomes the instance represented by `this` ([§11.7.12](expressions.md#11712-this-access)). +- A throw expression, which may be used is several contexts to throw an exception in an expression. A throw expression may be converted by an implicit conversion to any type. A property access or indexer access is always reclassified as a value by performing an invocation of the *get_accessor* or the *set_accessor*. The particular accessor is determined by the context of the property or indexer access: If the access is the target of an assignment, the *set_accessor* is invoked to assign a new value ([§11.18.2](expressions.md#11182-simple-assignment)). Otherwise, the *get_accessor* is invoked to obtain the current value ([§11.2.2](expressions.md#1122-values-of-expressions)). From 63133d5940c57b35f5d272b2e5b32ff04bce075d Mon Sep 17 00:00:00 2001 From: Neal Gafter Date: Wed, 13 Jul 2022 17:44:50 -0700 Subject: [PATCH 06/15] Fix section number. --- standard/conversions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/conversions.md b/standard/conversions.md index 6c8193b91..c0715362e 100644 --- a/standard/conversions.md +++ b/standard/conversions.md @@ -302,7 +302,7 @@ A user-defined implicit conversion consists of an optional standard implicit con Anonymous functions and method groups do not have types in and of themselves, but they may be implicitly converted to delegate types. Additionally, some lambda expressions may be implicitly converted to expression tree types. Anonymous function conversions are described in more detail in [§10.7](conversions.md#107-anonymous-function-conversions) and method group conversions in [§10.8](conversions.md#108-method-group-conversions). -### 10.2.14 Implicit throw conversions +### 10.2.15 Implicit throw conversions While throw expressions do not have a type, they may be implicitly convertied to any type. From 928915a0ca38ddd2b9a0e238ff41759b13fdb4b2 Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Sun, 2 Oct 2022 16:43:03 -0400 Subject: [PATCH 07/15] fix merge error. --- standard/expressions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/expressions.md b/standard/expressions.md index 20b2c3397..0993f63e3 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -154,7 +154,7 @@ The precedence of an operator is established by the definition of its associated > | [§11.12](expressions.md#1112-logical-operators) | Logical OR | `|` > | [§11.13](expressions.md#1113-conditional-logical-operators) | Conditional AND | `&&` > | [§11.13](expressions.md#1113-conditional-logical-operators) | Conditional OR | `||` -> | [§11.14](expressions.md#1114-the-null-coalescing-operator) | Null coalescing | `??` +> | [§11.14](expressions.md#1114-the-null-coalescing-operator) | Null coalescing | `??` `throw x` > | [§11.15](expressions.md#1115-conditional-operator) | Conditional | `?:` > | [§11.18](expressions.md#1118-assignment-operators) and [§11.16](expressions.md#1116-anonymous-function-expressions) | Assignment and lambda expression | `=` `*=` `/=` `%=` `+=` `-=` `<<=` `>>=` `&=` `^=` `\|=` `=>` > From d0c85426589afdee78dadfc27e8d2300609084d3 Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Sun, 2 Oct 2022 16:47:17 -0400 Subject: [PATCH 08/15] add column end marker --- standard/expressions.md | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/standard/expressions.md b/standard/expressions.md index 0993f63e3..9fa90fa31 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -140,23 +140,23 @@ The precedence of an operator is established by the definition of its associated > *Note*: The following table summarizes all operators in order of precedence from highest to lowest: > -> | **Subclause** | **Category** | **Operators** -> | ----------------- | ------------------------------- | ------------------------------------------------------- -> | [§11.7](expressions.md#117-primary-expressions) | Primary | `x.y` `x?.y` `f(x)` `a[x]` `a?[x]` `x++` `x--` `new` `typeof` `default` `checked` `unchecked` `delegate` -> | [§11.8](expressions.md#118-unary-operators) | Unary | `+` `-` `!` `~` `++x` `--x` `(T)x` `await x` -> | [§11.9](expressions.md#119-arithmetic-operators) | Multiplicative | `*` `/` `%` -> | [§11.9](expressions.md#119-arithmetic-operators) | Additive | `+` `-` -> | [§11.10](expressions.md#1110-shift-operators) | Shift | `<<` `>>` -> | [§11.11](expressions.md#1111-relational-and-type-testing-operators) | Relational and type-testing | `<` `>` `<=` `>=` `is` `as` -> | [§11.11](expressions.md#1111-relational-and-type-testing-operators) | Equality | `==` `!=` -> | [§11.12](expressions.md#1112-logical-operators) | Logical AND | `&` -> | [§11.12](expressions.md#1112-logical-operators) | Logical XOR | `^` -> | [§11.12](expressions.md#1112-logical-operators) | Logical OR | `|` -> | [§11.13](expressions.md#1113-conditional-logical-operators) | Conditional AND | `&&` -> | [§11.13](expressions.md#1113-conditional-logical-operators) | Conditional OR | `||` -> | [§11.14](expressions.md#1114-the-null-coalescing-operator) | Null coalescing | `??` `throw x` -> | [§11.15](expressions.md#1115-conditional-operator) | Conditional | `?:` -> | [§11.18](expressions.md#1118-assignment-operators) and [§11.16](expressions.md#1116-anonymous-function-expressions) | Assignment and lambda expression | `=` `*=` `/=` `%=` `+=` `-=` `<<=` `>>=` `&=` `^=` `\|=` `=>` +> | **Subclause** | **Category** | **Operators** | +> | ----------------- | ------------------------------- | -------------------------------------------------------| +> | [§11.7](expressions.md#117-primary-expressions) | Primary | `x.y` `x?.y` `f(x)` `a[x]` `a?[x]` `x++` `x--` `new` `typeof` `default` `checked` `unchecked` `delegate` | +> | [§11.8](expressions.md#118-unary-operators) | Unary | `+` `-` `!` `~` `++x` `--x` `(T)x` `await x` | +> | [§11.9](expressions.md#119-arithmetic-operators) | Multiplicative | `*` `/` `%` | +> | [§11.9](expressions.md#119-arithmetic-operators) | Additive | `+` `-` | +> | [§11.10](expressions.md#1110-shift-operators) | Shift | `<<` `>>` | +> | [§11.11](expressions.md#1111-relational-and-type-testing-operators) | Relational and type-testing | `<` `>` `<=` `>=` `is` `as` | +> | [§11.11](expressions.md#1111-relational-and-type-testing-operators) | Equality | `==` `!=` | +> | [§11.12](expressions.md#1112-logical-operators) | Logical AND | `&` | +> | [§11.12](expressions.md#1112-logical-operators) | Logical XOR | `^` | +> | [§11.12](expressions.md#1112-logical-operators) | Logical OR | `|` | +> | [§11.13](expressions.md#1113-conditional-logical-operators) | Conditional AND | `&&` | +> | [§11.13](expressions.md#1113-conditional-logical-operators) | Conditional OR | `||` | +> | [§11.14](expressions.md#1114-the-null-coalescing-operator) | Null coalescing | `??` `throw x` | +> | [§11.15](expressions.md#1115-conditional-operator) | Conditional | `?:` | +> | [§11.18](expressions.md#1118-assignment-operators) and [§11.16](expressions.md#1116-anonymous-function-expressions) | Assignment and lambda expression | `=` `*=` `/=` `%=` `+=` `-=` `<<=` `>>=` `&=` `^=` `|=` `=>` | > > *end note* From 4cc66a98c985b49b402cf03939cb15079c172176 Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Sun, 2 Oct 2022 16:51:04 -0400 Subject: [PATCH 09/15] still rendering --- standard/expressions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/standard/expressions.md b/standard/expressions.md index 9fa90fa31..ba953ee74 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -151,9 +151,9 @@ The precedence of an operator is established by the definition of its associated > | [§11.11](expressions.md#1111-relational-and-type-testing-operators) | Equality | `==` `!=` | > | [§11.12](expressions.md#1112-logical-operators) | Logical AND | `&` | > | [§11.12](expressions.md#1112-logical-operators) | Logical XOR | `^` | -> | [§11.12](expressions.md#1112-logical-operators) | Logical OR | `|` | +> | [§11.12](expressions.md#1112-logical-operators) | Logical OR | `\|` | > | [§11.13](expressions.md#1113-conditional-logical-operators) | Conditional AND | `&&` | -> | [§11.13](expressions.md#1113-conditional-logical-operators) | Conditional OR | `||` | +> | [§11.13](expressions.md#1113-conditional-logical-operators) | Conditional OR | `\|\|` | > | [§11.14](expressions.md#1114-the-null-coalescing-operator) | Null coalescing | `??` `throw x` | > | [§11.15](expressions.md#1115-conditional-operator) | Conditional | `?:` | > | [§11.18](expressions.md#1118-assignment-operators) and [§11.16](expressions.md#1116-anonymous-function-expressions) | Assignment and lambda expression | `=` `*=` `/=` `%=` `+=` `-=` `<<=` `>>=` `&=` `^=` `|=` `=>` | From baaf5386826555db3c5db576b39048be3aeddba6 Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Sun, 2 Oct 2022 16:53:04 -0400 Subject: [PATCH 10/15] add one more escape it appears that once any vertical bar is escaped in a table, they all must be. --- standard/expressions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/expressions.md b/standard/expressions.md index ba953ee74..bace3a4e1 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -156,7 +156,7 @@ The precedence of an operator is established by the definition of its associated > | [§11.13](expressions.md#1113-conditional-logical-operators) | Conditional OR | `\|\|` | > | [§11.14](expressions.md#1114-the-null-coalescing-operator) | Null coalescing | `??` `throw x` | > | [§11.15](expressions.md#1115-conditional-operator) | Conditional | `?:` | -> | [§11.18](expressions.md#1118-assignment-operators) and [§11.16](expressions.md#1116-anonymous-function-expressions) | Assignment and lambda expression | `=` `*=` `/=` `%=` `+=` `-=` `<<=` `>>=` `&=` `^=` `|=` `=>` | +> | [§11.18](expressions.md#1118-assignment-operators) and [§11.16](expressions.md#1116-anonymous-function-expressions) | Assignment and lambda expression | `=` `*=` `/=` `%=` `+=` `-=` `<<=` `>>=` `&=` `^=` `\|=` `=>` | > > *end note* From 64386a72f7c981d3745c6bb2861f7fda96b0dec0 Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Fri, 7 Oct 2022 11:18:18 +0100 Subject: [PATCH 11/15] Add throw expressions to precedence table --- standard/expressions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/expressions.md b/standard/expressions.md index bace3a4e1..98842664f 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -154,7 +154,7 @@ The precedence of an operator is established by the definition of its associated > | [§11.12](expressions.md#1112-logical-operators) | Logical OR | `\|` | > | [§11.13](expressions.md#1113-conditional-logical-operators) | Conditional AND | `&&` | > | [§11.13](expressions.md#1113-conditional-logical-operators) | Conditional OR | `\|\|` | -> | [§11.14](expressions.md#1114-the-null-coalescing-operator) | Null coalescing | `??` `throw x` | +> | [§11.14](expressions.md#1114-the-null-coalescing-operator) and [§11.xy](expressions.md#xy-the-throw-expression-operator) | Null coalescing and throw expression | `??` `throw x` | > | [§11.15](expressions.md#1115-conditional-operator) | Conditional | `?:` | > | [§11.18](expressions.md#1118-assignment-operators) and [§11.16](expressions.md#1116-anonymous-function-expressions) | Assignment and lambda expression | `=` `*=` `/=` `%=` `+=` `-=` `<<=` `>>=` `&=` `^=` `\|=` `=>` | > From 01029fe8cb813013995cded6a5de65ddc235cb3c Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Tue, 11 Oct 2022 15:25:21 +0100 Subject: [PATCH 12/15] Move throw expression to a new top-level section after null coalescing operator --- standard/expressions.md | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/standard/expressions.md b/standard/expressions.md index 98842664f..417ea9cb3 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -154,7 +154,7 @@ The precedence of an operator is established by the definition of its associated > | [§11.12](expressions.md#1112-logical-operators) | Logical OR | `\|` | > | [§11.13](expressions.md#1113-conditional-logical-operators) | Conditional AND | `&&` | > | [§11.13](expressions.md#1113-conditional-logical-operators) | Conditional OR | `\|\|` | -> | [§11.14](expressions.md#1114-the-null-coalescing-operator) and [§11.xy](expressions.md#xy-the-throw-expression-operator) | Null coalescing and throw expression | `??` `throw x` | +> | [§11.14](expressions.md#1114-the-null-coalescing-operator) and [§11.xy](expressions.md#throw-expression-operator-new-clause) | Null coalescing and throw expression | `??` `throw x` | > | [§11.15](expressions.md#1115-conditional-operator) | Conditional | `?:` | > | [§11.18](expressions.md#1118-assignment-operators) and [§11.16](expressions.md#1116-anonymous-function-expressions) | Assignment and lambda expression | `=` `*=` `/=` `%=` `+=` `-=` `<<=` `>>=` `&=` `^=` `\|=` `=>` | > @@ -2920,24 +2920,6 @@ 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 [§11.16](expressions.md#1116-anonymous-function-expressions). -### §throw-expression-operator-new-clause The throw expression operator - -```ANTLR -throw_expression - : 'throw' null_coalescing_expression - ; -``` - -A *throw_expression* throws the value produced by evaluating the *null_coalescing_expression*. The expression shall be implicitly convertible to `System.Exception`, and the result of evaluating the expression is converted to `System.Exception` before being thrown. The behavior at runtime of the evaluation of a *throw expression* is the same as specified for a *throw statement* ([§12.10.6](statements.md#12106-the-throw-statement)). - -A *throw_expression* has no type. A *throw_expression* is convertible to every type by an *implicit throw conversion*. - -A *throw expression* shall only occur in the following syntactic contexts: - -- As the second or third operand of a ternary conditional operator (`?:`). -- As the second operand of a null coalescing operator (`??`). -- As the body of an expression-bodied lambda or member. - ## 11.8 Unary operators ### 11.8.1 General @@ -4258,6 +4240,24 @@ The type of the expression `a ?? b` depends on which implicit conversions are Otherwise, `a` and `b` are incompatible, and `a` compile-time error occurs. +## §throw-expression-operator-new-clause The throw expression operator + +```ANTLR +throw_expression + : 'throw' null_coalescing_expression + ; +``` + +A *throw_expression* throws the value produced by evaluating the *null_coalescing_expression*. The expression shall be implicitly convertible to `System.Exception`, and the result of evaluating the expression is converted to `System.Exception` before being thrown. The behavior at runtime of the evaluation of a *throw expression* is the same as specified for a *throw statement* ([§12.10.6](statements.md#12106-the-throw-statement)). + +A *throw_expression* has no type. A *throw_expression* is convertible to every type by an *implicit throw conversion*. + +A *throw expression* shall only occur in the following syntactic contexts: + +- As the second or third operand of a ternary conditional operator (`?:`). +- As the second operand of a null coalescing operator (`??`). +- As the body of an expression-bodied lambda or member. + ## 11.15 Conditional operator The `?:` operator is called the conditional operator. It is at times also called the ternary operator. From adf4c96b5ab85ad610cbf868454812faa80ede9a Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Wed, 12 Oct 2022 08:24:55 +0100 Subject: [PATCH 13/15] Fix typo --- standard/conversions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/conversions.md b/standard/conversions.md index c0715362e..de8a66af6 100644 --- a/standard/conversions.md +++ b/standard/conversions.md @@ -304,7 +304,7 @@ Anonymous functions and method groups do not have types in and of themselves, bu ### 10.2.15 Implicit throw conversions -While throw expressions do not have a type, they may be implicitly convertied to any type. +While throw expressions do not have a type, they may be implicitly converted to any type. ## 10.3 Explicit conversions From 12f4e5ce3a0692b35af05dadb68254cfa168eafc Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Wed, 12 Oct 2022 08:25:49 +0100 Subject: [PATCH 14/15] Update reference --- standard/expressions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/expressions.md b/standard/expressions.md index 417ea9cb3..eef7223ac 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -154,7 +154,7 @@ The precedence of an operator is established by the definition of its associated > | [§11.12](expressions.md#1112-logical-operators) | Logical OR | `\|` | > | [§11.13](expressions.md#1113-conditional-logical-operators) | Conditional AND | `&&` | > | [§11.13](expressions.md#1113-conditional-logical-operators) | Conditional OR | `\|\|` | -> | [§11.14](expressions.md#1114-the-null-coalescing-operator) and [§11.xy](expressions.md#throw-expression-operator-new-clause) | Null coalescing and throw expression | `??` `throw x` | +> | [§11.14](expressions.md#1114-the-null-coalescing-operator) and [§throw-expression-operator-new-clause](expressions.md#throw-expression-operator-new-clause) | Null coalescing and throw expression | `??` `throw x` | > | [§11.15](expressions.md#1115-conditional-operator) | Conditional | `?:` | > | [§11.18](expressions.md#1118-assignment-operators) and [§11.16](expressions.md#1116-anonymous-function-expressions) | Assignment and lambda expression | `=` `*=` `/=` `%=` `+=` `-=` `<<=` `>>=` `&=` `^=` `\|=` `=>` | > From 9bbbd7a5d7d9937ec1a5d96455a915a8a1853721 Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Wed, 12 Oct 2022 15:20:31 +0100 Subject: [PATCH 15/15] Update link to new section Co-authored-by: Bill Wagner --- standard/expressions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/expressions.md b/standard/expressions.md index eef7223ac..fd36167d1 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -154,7 +154,7 @@ The precedence of an operator is established by the definition of its associated > | [§11.12](expressions.md#1112-logical-operators) | Logical OR | `\|` | > | [§11.13](expressions.md#1113-conditional-logical-operators) | Conditional AND | `&&` | > | [§11.13](expressions.md#1113-conditional-logical-operators) | Conditional OR | `\|\|` | -> | [§11.14](expressions.md#1114-the-null-coalescing-operator) and [§throw-expression-operator-new-clause](expressions.md#throw-expression-operator-new-clause) | Null coalescing and throw expression | `??` `throw x` | +> | [§11.14](expressions.md#1114-the-null-coalescing-operator) and §throw-expression-operator-new-clause | Null coalescing and throw expression | `??` `throw x` | > | [§11.15](expressions.md#1115-conditional-operator) | Conditional | `?:` | > | [§11.18](expressions.md#1118-assignment-operators) and [§11.16](expressions.md#1116-anonymous-function-expressions) | Assignment and lambda expression | `=` `*=` `/=` `%=` `+=` `-=` `<<=` `>>=` `&=` `^=` `\|=` `=>` | >