已开启
docs(match): describe sealed match exhaustiveness #577
docs(match): describe sealed match exhaustiveness #577
已开启
Cangjie-Sundaiyue创建于 8月12日
共 2 个文件变更+52-0
@@ -37,6 +37,32 @@ x = 0
37 37 
38The `match` expression requires that all matches must be exhaustive, meaning all possible values of the expression to be matched should be considered. When the `match` expression is not exhaustive, or the compiler cannot determine whether it is exhaustive, a compilation error will occur. In other words, the union of the value ranges covered by all `case` branches (including pattern guards) should include all possible values of the expression to be matched. A common way to ensure the exhaustiveness of the `match` expression is to use the wildcard pattern `_` in the last `case` branch, as `_` can match any value.38The `match` expression requires that all matches must be exhaustive, meaning all possible values of the expression to be matched should be considered. When the `match` expression is not exhaustive, or the compiler cannot determine whether it is exhaustive, a compilation error will occur. In other words, the union of the value ranges covered by all `case` branches (including pattern guards) should include all possible values of the expression to be matched. A common way to ensure the exhaustiveness of the `match` expression is to use the wildcard pattern `_` in the last `case` branch, as `_` can match any value.
39 39 
40+### Exhaustive Matching of Sealed Types
41+ 
42+For a `sealed abstract class` or `sealed interface` whose definition and `match` expression are in the current package, the final wildcard pattern `_` can be omitted when the type patterns in the `case` branches list every possible subtype. For example:
43+ 
44+<!-- compile -->
45+ 
46+```cangjie
47+sealed interface Color {}
48+ 
49+class Red <: Color {}
50+class Green <: Color {}
51+class Blue <: Color {}
52+ 
53+func describe(color: Color): String {
54+ match (color) {
55+ case _: Red => "red"
56+ case _: Green => "green"
57+ case _: Blue => "blue"
58+ }
59+}
60+```
61+ 
62+Here, `Color` and its subtypes are in the current package, and none of the three subtypes can be inherited further, so the type patterns cover every possible `Color` value. A trailing `_` is unnecessary; if it is added, the compiler reports an `unreachable pattern` warning.
63+ 
64+Keep `_` when the compiler cannot determine that the set of subtypes is closed. For example, this is the case when the `sealed` type is imported from another package, a subtype is declared `private` in another source file and cannot be named at the matching location, or a subtype can be inherited further, such as an `open`, `abstract`, or `sealed` subtype or a child interface. The same rule applies to nested type patterns in tuples and in arguments of enum constructors.
65+ 
40The exhaustiveness of the `match` expression ensures that there must be a `case` branch that matches the value to be matched. The following example will result in a compilation error because not all possible values of `x` are covered by the `case` branches:66The exhaustiveness of the `match` expression ensures that there must be a `case` branch that matches the value to be matched. The following example will result in a compilation error because not all possible values of `x` are covered by the `case` branches:
41 67 
42<!-- compile.error -->68<!-- compile.error -->
@@ -37,6 +37,32 @@ x = 0
37 37 
38`match` 表达式要求所有匹配必须是穷尽(exhaustive)的,意味着待匹配表达式的所有可能取值都应该被考虑到。当 `match` 表达式非穷尽,或者编译器判断不出是否穷尽时,均会编译报错,换言之,所有 `case` 分支(包含 pattern guard)所覆盖的取值范围的并集,应该包含待匹配表达式的所有可能取值。常用的确保 `match` 表达式穷尽的方式是在最后一个 `case` 分支中使用通配符模式 `_`,因为 `_` 可以匹配任何值。38`match` 表达式要求所有匹配必须是穷尽(exhaustive)的,意味着待匹配表达式的所有可能取值都应该被考虑到。当 `match` 表达式非穷尽,或者编译器判断不出是否穷尽时,均会编译报错,换言之,所有 `case` 分支(包含 pattern guard)所覆盖的取值范围的并集,应该包含待匹配表达式的所有可能取值。常用的确保 `match` 表达式穷尽的方式是在最后一个 `case` 分支中使用通配符模式 `_`,因为 `_` 可以匹配任何值。
39 39 
40+### sealed 类型的穷尽匹配
41+ 
42+对于定义和匹配都位于当前包中的 `sealed abstract class` 或 `sealed interface`,如果 `case` 中的类型模式已经列出了所有可能的子类型,则可以省略最后的通配符模式 `_`。例如:
43+ 
44+<!-- compile -->
45+ 
46+```cangjie
47+sealed interface Color {}
48+ 
49+class Red <: Color {}
50+class Green <: Color {}
51+class Blue <: Color {}
52+ 
53+func describe(color: Color): String {
54+ match (color) {
55+ case _: Red => "red"
56+ case _: Green => "green"
57+ case _: Blue => "blue"
58+ }
59+}
60+```
61+ 
62+这里的 `Color` 及其子类型均在当前包中,且三个子类型都不能继续被继承,因此这些类型模式已经覆盖 `Color` 的所有可能取值。末尾不需要再添加 `_`;若添加该分支,编译器会提示该模式不可达。
63+ 
64+当编译器无法确定子类型集合是否封闭时,仍需保留 `_`。例如,`sealed` 类型从其他包导入、子类型在其他源文件中以 `private` 声明而无法在当前匹配位置命名,或者某个子类型仍可继续被继承(如 `open`、`abstract`、`sealed` 子类型或子接口)时,均应使用 `_` 作为兜底。该规则同样适用于元组中以及有参 `enum` 构造器参数中的嵌套类型模式。
65+ 
40`match` 表达式的穷尽性保证了一定存在和待匹配值相匹配的 `case` 分支。下面的例子将编译报错,因为所有的 `case` 并没有覆盖 `x` 的所有可能取值:66`match` 表达式的穷尽性保证了一定存在和待匹配值相匹配的 `case` 分支。下面的例子将编译报错,因为所有的 `case` 并没有覆盖 `x` 的所有可能取值:
41 67 
42<!-- compile.error -->68<!-- compile.error -->