Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Null-forgiving operator #1195

Open
wants to merge 7 commits into
base: draft-v8
Choose a base branch
from
Open
Changes from 2 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
23 changes: 17 additions & 6 deletions standard/expressions.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ The precedence of an operator is established by the definition of its associated
>
> | **Subclause** | **Category** | **Operators** |
> | ----------------- | ------------------------------- | -------------------------------------------------------|
> | [§12.8](expressions.md#128-primary-expressions) | Primary | `x.y` `x?.y` `f(x)` `a[x]` `a?[x]` `x++` `x--` `new` `typeof` `default` `checked` `unchecked` `delegate` `stackalloc` |
> | [§12.8](expressions.md#128-primary-expressions) | Primary | `x.y` `x?.y` `f(x)` `a[x]` `a?[x]` `x++` `x--` `x!` `new` `typeof` `default` `checked` `unchecked` `delegate` `stackalloc` |
> | [§12.9](expressions.md#129-unary-operators) | Unary | `+` `-` `!` `~` `++x` `--x` `(T)x` `await x` |
> | [§12.10](expressions.md#1210-arithmetic-operators) | Multiplicative | `*` `/` `%` |
> | [§12.10](expressions.md#1210-arithmetic-operators) | Additive | `+` `-` |
Expand Down Expand Up @@ -1273,7 +1273,6 @@ Primary expressions include the simplest forms of expressions.
primary_expression
: primary_no_array_creation_expression
| array_creation_expression
| null_forgiving_expression
;

primary_no_array_creation_expression
Expand All @@ -1291,6 +1290,7 @@ primary_no_array_creation_expression
| base_access
| post_increment_expression
| post_decrement_expression
| null_forgiving_expression
| object_creation_expression
| delegate_creation_expression
| anonymous_object_creation_expression
Expand All @@ -1307,7 +1307,7 @@ primary_no_array_creation_expression
;
```

> *Note*: These grammar rules are not ANTLR-ready as they are part of a set of mutually left-recursive rules (`primary_expression`, `primary_no_array_creation_expression`, `member_access`, `invocation_expression`, `element_access`, `post_increment_expression`, `post_decrement_expression`, `pointer_member_access` and `pointer_element_access`) which ANTLR does not handle. Standard techniques can be used to transform the grammar to remove the mutual left-recursion. This has not been done as not all parsing strategies require it (e.g. an LALR parser would not) and doing so would obfuscate the structure and description. *end note*
> *Note*: These grammar rules are not ANTLR-ready as they are part of a set of mutually left-recursive rules (`primary_expression`, `primary_no_array_creation_expression`, `member_access`, `invocation_expression`, `element_access`, `post_increment_expression`, `post_decrement_expression`, `null_forgiving_expression`, `pointer_member_access` and `pointer_element_access`) which ANTLR does not handle. Standard techniques can be used to transform the grammar to remove the mutual left-recursion. This has not been done as not all parsing strategies require it (e.g. an LALR parser would not) and doing so would obfuscate the structure and description. *end note*

*pointer_member_access* ([§23.6.3](unsafe-code.md#2363-pointer-member-access)) and *pointer_element_access* ([§23.6.4](unsafe-code.md#2364-pointer-element-access)) are only available in unsafe code ([§23](unsafe-code.md#23-unsafe-code)).

Expand Down Expand Up @@ -1824,18 +1824,29 @@ A *null_conditional_projection_initializer* is a restriction of *null_conditiona

### 12.8.9 Null-forgiving expressions

This operator sets the null state ([§8.9.5](types.md#895-nullabilities-and-null-states)) of the operand to “not null”.
The null-forgiving operator sets the null state ([§8.9.5](types.md#895-nullabilities-and-null-states)) of the operand to “not null”.

```ANTLR
null_forgiving_expression
: primary_no_array_creation_expression suppression
: primary_expression null_forgiving_operator
;

suppression
null_forgiving_operator
: '!'
;
```

The *primary_expression* must not be known to have a value type.
Nigel-Ecma marked this conversation as resolved.
Show resolved Hide resolved

It is an error to apply the null-forgiving operator more than once to the same expression, intervening parenetheses notwithstanding.
Nigel-Ecma marked this conversation as resolved.
Show resolved Hide resolved

> *Example*: the following are all invalid:
>
> ```csharp
> var p = q!!; // error: cannot apply the null_forgiving_operator more than once
> var s = ( ( m(t) ! ) )! // error: null_forgiving_operator applied twice to m(t)
> ```

This operator has no runtime effect; it evaluates to the result of its operand, and that result retains that operand’s classification.

The null-forgiving operator is used to declare that an expression not known to be a value type is not null.
Expand Down
Loading