diff --git a/standard/patterns.md b/standard/patterns.md index c21159c64..6bfa3f744 100644 --- a/standard/patterns.md +++ b/standard/patterns.md @@ -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: -> -> -> ```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*: -> -> -> ```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.