-
Notifications
You must be signed in to change notification settings - Fork 95
Review and update pattern subsumption and exhaustion #1691
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
BillWagner
wants to merge
4
commits into
dotnet:draft-v8
Choose a base branch
from
BillWagner:subsumption-exhaustion
base: draft-v8
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 all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
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 |
|---|---|---|
|
|
@@ -448,60 +448,9 @@ If, after applying the preceding rule, the token `_` is still a *discard_pattern | |
| ## 11.3 Pattern subsumption | ||
|
|
||
| In a switch statement ([§13.8.3](statements.md#1383-the-switch-statement)), it is an error if a case’s pattern is *subsumed* by the preceding set of *unguarded* ([§13.8.3](statements.md#1383-the-switch-statement)) cases. In a switch expression ([§12.11](expressions.md#1211-switch-expression)), it is an error if a *switch_expression_arm*’s pattern is *subsumed* by the preceding set of *unguarded* *switch_expression_arm*s’ patterns. | ||
| > *Note*: This means that any input value would have been matched by one of the previous cases or arms. *end note* | ||
| The following rules define when a set of patterns subsumes a given pattern: | ||
|
|
||
| A pattern `P` *would match* a constant `K` if the specification for that pattern’s runtime behavior is that `P` matches `K`. | ||
|
|
||
| A set of patterns `Q` *subsumes* a pattern `P` if any of the following conditions hold: | ||
|
|
||
| - `P` is a constant pattern and any of the patterns in the set `Q` would match `P`’s *converted value* | ||
| - `P` is a var pattern and the set of patterns `Q` is *exhaustive* ([§11.4](patterns.md#114-pattern-exhaustiveness)) for the type of the pattern input value ([§11.1](patterns.md#111-general)), and either the pattern input value is not of a nullable type or some pattern in `Q` would match `null`. | ||
| - `P` is a declaration pattern with type `T` and the set of patterns `Q` is *exhaustive* for the type `T` ([§11.4](patterns.md#114-pattern-exhaustiveness)). | ||
|
|
||
| > *Example*: In the following switch expression, no arm is subsumed even though arms 1, 2, and 3 share the same pattern: | ||
| > | ||
| > <!-- Example: {template:"code-in-main", name:"SwitchExprUnguardedSubsumption"} --> | ||
| > ```csharp | ||
| > object x = 10; | ||
| > bool b = false; | ||
| > int y = x switch | ||
| > { | ||
| > int i when !b => 0, | ||
| > int i when b => 1, | ||
| > int i => 2, | ||
| > _ => 3 | ||
| > }; | ||
| > ``` | ||
| > | ||
| > Arms 1 and 2 have non-constant guards and so are not *unguarded*; only arm 3 is *unguarded* with pattern `int i`, which does not subsume the final `_` arm because it does not match a non-`int` value such as `null`. *end example* | ||
| > *Note*: This means that any input value would have been matched by one of the previous cases or arms. *end note* | ||
|
|
||
| ## 11.4 Pattern exhaustiveness | ||
|
|
||
| Informally, a set of patterns is exhaustive for a type if, for every possible value of that type other than null, some pattern in the set is applicable. | ||
| The following rules define when a set of patterns is *exhaustive* for a type: | ||
|
|
||
| A set of patterns `Q` is *exhaustive* for a type `T` if any of the following conditions hold: | ||
|
|
||
| 1. `T` is an integral or enum type, or a nullable version of one of those, and for every possible value of `T`’s non-nullable underlying type, some pattern in `Q` would match that value; or | ||
| 2. Some pattern in `Q` is a *var pattern*; or | ||
| 3. Some pattern in `Q` is a *declaration pattern* for type `D`, and there is an identity conversion, an implicit reference conversion, or a boxing conversion from `T` to `D`. | ||
|
|
||
| > *Example*: | ||
| > | ||
| > <!-- Example: {template:"standalone-console-without-using", name:"PatternExhaustiveness1", replaceEllipsis:true, customEllipsisReplacements: [""], ignoredWarnings:["CS8321"]} --> | ||
| > ```csharp | ||
| > static void M(byte b) | ||
| > { | ||
| > switch (b) { | ||
| > case 0: case 1: case 2: ... // handle every specific value of byte | ||
| > break; | ||
| > // error: the pattern 'byte other' is subsumed by the (exhaustive) | ||
| > // previous cases | ||
| > case byte other: | ||
| > break; | ||
| > } | ||
| > } | ||
| > ``` | ||
| > | ||
| > *end example* | ||
| A set of patterns is exhaustive if, for every possible input value, some pattern in the set is applicable. When an implementation detects that a set of patterns is not exhaustive, it shall issue a warning. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is now an incredibly short section, and we're not planning on adding more detail. 11.3 is really short now too. Is there a reasonable way of combining them, or do we want to avoid confusing the two terms? |
||
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the detail removed this line should no longer be a note. Line 450 introduces the use of set, so maybe something along the lines of:
This maybe should become before 450 – i.e. short definition of subsumed followed by the error cases?
Can a pattern only be subsumed if it is itself unguarded? I.e. should it be “An unguarded pattern
Pis…”?