-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Create spec for const expressions for is patterns #7589
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
Open
Rekkonnect
wants to merge
11
commits into
dotnet:main
Choose a base branch
from
Rekkonnect:pattern-const-expressions
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 2 commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
ffb40d0
Create pattern-const-expressions.md
Rekkonnect d5e4d8b
Add design meeting from 2023-10-09
Rekkonnect 2767290
Update spec
Rekkonnect 438900c
Remove new error question
Rekkonnect d66f305
Update pattern-const-expressions.md
Rekkonnect 1890653
Remove `literal` word
Rekkonnect 259d137
Further clarifications on diagnostics
Rekkonnect 9234d41
Clarify constant context
Rekkonnect b065e8a
Include switch expressions + rewording
Rekkonnect 9eee89d
Adjust missing default arm diagnostics + fixes
Rekkonnect f8d2b7a
Update constant contexts + default arm warnings
Rekkonnect File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| # Constant `is` pattern expressions | ||
|
|
||
| * [x] Proposed | ||
| * [ ] Prototype: None | ||
| * [ ] Implementation: None | ||
| * [ ] Specification: Started, below | ||
|
|
||
| ## Summary | ||
| [summary]: #summary | ||
|
|
||
| Consider `is` pattern expressions as constant if the LHS is constant. | ||
|
|
||
| ## Motivation | ||
| [motivation]: #motivation | ||
|
|
||
| When the pattern expressions are converted into simpler boolean expressions using equality and comparison operators, they are considered constant expressions if all parts of the expression are considered constant and can be evaluated during compilation. Also, the expressions returned from the ternary operator can also be considered constant if all sides are constant (condition, consequence and alternative). | ||
|
|
||
| ## Detailed design | ||
| [design]: #detailed-design | ||
|
|
||
| ### Spec | ||
| The [section](https://github.com/dotnet/csharpstandard/blob/draft-v7/standard/expressions.md#1223-constant-expressions) in the spec needs to be updated accordingly, in the following segments: | ||
|
|
||
| > Only the following constructs are permitted in constant expressions: | ||
| > - Literals (including the null literal). | ||
| > - References to const members of class and struct types. | ||
| > - References to members of enumeration types. | ||
| > - References to local constants. | ||
| > - Parenthesized subexpressions, which are themselves constant expressions. | ||
| > - Cast expressions. | ||
| > - checked and unchecked expressions. | ||
| > - nameof expressions. | ||
| > - The predefined +, –, !, and ~ unary operators. | ||
| > - The predefined +, –, *, /, %, <<, >>, &, |, ^, &&, ||, ==, !=, <, >, <=, and >= binary operators. | ||
| > - The ?: conditional operator. | ||
| > - **Pattern expressions.** | ||
333fred marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| > - sizeof expressions, provided the unmanaged-type is one of the types specified in §23.6.9 for which sizeof returns a constant value. | ||
| > - Default value expressions, provided the type is one of the types listed above. | ||
|
|
||
| ### Grammar | ||
| The grammar remains untouched, as nothing changes syntactically for this change. | ||
|
|
||
| ### Semantics | ||
| A pattern expression with a constant LHS may be evaluated at compile time currently, but it cannot be assigned to a constant symbol. With this change, constant fields and locals of type `bool` may be assigned pattern expressions, as already evaluated during compilation. | ||
|
|
||
| ### Examples | ||
| The below example shows a pattern expression being assigned to a constant field. | ||
| ```csharp | ||
| public const int A = 4; | ||
| public const bool B = A is 4; | ||
| public const bool C = A is not 3 and < 1 or 5; | ||
| ``` | ||
|
|
||
| Since `A` is constant, and pattern expressions require that the operands on the right are constant, all operands are constant, and the expression is thus evaluated during compilation. This result will then be assigned to the constant field. | ||
|
|
||
| Another example, using type and `null` value checks: | ||
| ```csharp | ||
| const int a = 4; | ||
| const bool b = false; | ||
| const long c = 4; | ||
| const string d = "hello"; | ||
|
|
||
| const bool x = a is int; // always true | ||
| const bool y = a is long; // always false | ||
| const bool z = d is not null; // always true | ||
| const bool p = b is null; // always false | ||
| ``` | ||
|
|
||
| All the above are currently valid pattern matching expressions, that also emit warnings about their constant evaluation results, about them being always true or false. | ||
333fred marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| When assigning those expressions to a constant symbol, it would be preferrable to not report these warnings about the constant result of the expression. | ||
|
|
||
| Expressions accessing properties and comparing their values are illegal, as property evaluation occurs at runtime: | ||
|
|
||
| ```csharp | ||
| const bool q = d is string { Length: 5 }; // Error: not a constant expression | ||
333fred marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ``` | ||
|
|
||
| ## Drawbacks | ||
| [drawbacks]: #drawbacks | ||
|
|
||
| None. | ||
|
|
||
| ## Alternatives | ||
| [alternatives]: #alternatives | ||
|
|
||
| Currently, equality and comparison operators can be used to compare against other literals, including nullability of the objects (e.g. `x != null`, or `y == 4 || y < 3`). However, type checking cannot be currently peformed at compile time and assigned to a constant. | ||
|
|
||
| ## Unresolved questions | ||
| [unresolved]: #unresolved-questions | ||
|
|
||
| - [ ] Requires LDM review | ||
|
|
||
| ## Design meetings | ||
| [meetings]: #design-meetings | ||
|
|
||
| - Approval for Any Time milestone: [Here](https://github.com/dotnet/csharplang/blob/main/meetings/2023/LDM-2023-10-09.md#is-expression-evaluating-const-expression-should-be-considered-constant) | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.