You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/docs/reference/match-types.md
+28-13
Original file line number
Diff line number
Diff line change
@@ -129,41 +129,56 @@ Within a match type `Match(S, Cs) <: B`, all occurrences of type variables count
129
129
130
130
## Typing Rules for Match Expressions
131
131
132
-
Typing rules for match expressions have to account for the difference between sequential match on the term level and parallel match on the type level. As a running example consider:
132
+
Typing rules for match expressions are tricky. First, they need some new form of GADT matching for value parameters.
133
+
Second, they have to account for the difference between sequential match on the term level and parallel match on the type level. As a running example consider:
133
134
```scala
134
-
typeM[X] =Xmatch {
135
+
typeM[+X] =Xmatch {
135
136
caseA=>1
136
137
caseB=>2
137
138
}
139
+
```
140
+
We'd like to be able to typecheck
141
+
```scala
138
142
defm[X](x: X):M[X] = x match {
143
+
case_: A=>1// type error
144
+
case_: B=>2// type error
145
+
}
146
+
```
147
+
Unfortunately, this goes nowhere. Let's try the first case. We have: `x.type <: A` and `x.type <: X`. This tells
148
+
us nothing about `X`, so we cannot reduce `M` in order to show that the right hand side of the case is valid.
149
+
150
+
The following variant is more promising:
151
+
```scala
152
+
defm(x: Any):M[x.type] = x match {
139
153
case_: A=>1
140
154
case_: B=>2
141
155
}
142
156
```
143
-
As a first approximation, the typing rules for match expressions are as usual. E.g. to typecheck the first case `case _: A => 1` of the definition of `m` above, GADT matching will produce the constraint `X <: A`. Therefore, `M[X]` reduces to the singleton type `1`.
144
-
The right hand side `1` of the case conforms to this type, so the case typechecks. Typechecking the second case proceeds similarly.
157
+
To make this work, we'd need a new form of GADT checking: If the scrutinee is a term variable `s`, we can make use of
158
+
the fact that `s.type` must conform to the pattern's type and derive a GADT constraint from that. For the first case above,
159
+
this would be the constraint `x.type <: A`. The new aspect here is that we need GADT constraints over singleton types where
160
+
before we just had constraints over type parameters.
161
+
162
+
Assuming this extension, we can then try to typecheck as usual. E.g. to typecheck the first case `case _: A => 1` of the definition of `m` above, GADT matching will produce the constraint `x.type <: A`. Therefore, `M[x.type]` reduces to the singleton type `1`. The right hand side `1` of the case conforms to this type, so the case typechecks. Typechecking the second case proceeds similarly.
145
163
146
-
However, it turns out that these rules are not enough for type soundness. To see this, assume that `A` and `B` are traits that are both extended by a common class `C`. In this case, `M[C]` reduces to `1 & 2`, but `m(new C)` reduces to `1`. So the type of the application `m(new C)` does not match the reduced result type of `m`, which means soundness is violated.
164
+
However, it turns out that these rules are not enough for type soundness. To see this, assume that `A` and `B` are traits that are both extended by a common class `C`. In this case, and assuming `c: C`, `M[c.type]` reduces to `1 & 2`, but `m(c)` reduces to `1`. So the type of the application `m(c)` does not match the reduced result type of `m`, which means soundness is violated.
147
165
148
-
To plug the soundness hole, we have to tighten the typing rules for match expressions. In the example above we need to also consider the case where the scrutinee type `X` is a subtype of `A` and `B`. In this case, the match expression still returns `1` but the match type `M[X]` reduces to `1 & 2`, which means there should be a type error. However, this second check can be omitted if `A` and `B` are types that don't overlap. We can omit the check because in that case there is no scrutinee value `x` that could reduce to `1`, so no discrepancy can arise at runtime.
166
+
To plug the soundness hole, we have to tighten the typing rules for match expressions. In the example above we need to also consider the case where the scrutinee `x` conforms to `A` and `B`. In this case, the match expression still returns `1` but the match type `M[x.type]` reduces to `1 & 2`, which means there should be a type error. However, this second check can be omitted if `A` and `B` are types that don't overlap. We can omit the check because in that case there is no scrutinee value `x` that could reduce to `1`, so no discrepancy can arise at runtime.
149
167
150
168
More generally, we proceeed as follows:
151
169
152
170
When typechecking the `i`th case of a match expression
153
171
```
154
-
t match { case P_1 => t_1 ... case P_n => t_n
172
+
x match { case P_1 => t_1 ... case P_n => t_n
155
173
```
156
-
where `t` has type `T` and `t_i` has type `T_i`
157
-
against an expected match type `R`:
174
+
where `t_i` has type `T_i` against an expected match type `R`:
158
175
159
176
1. Determine all maximal sequences of
160
177
patterns `P_j_1, ..., P_j_m` that follow `P_i` in the match expression and that do overlap with `P_i`. That is, `P_i, P_j_1, ..., P_j_m` all match at least one common value.
161
178
162
-
2. For each such sequence, verify that `T_i <: R` under the GADT constraint arising from matching the scrutinee type `T` against all of the patterns `P_i, P_j_1, ..., P_j_m`.
179
+
2. For each such sequence, verify that `T_i <: R` under the GADT constraint arising from matching the scrutinee `x` against all of the patterns `P_i, P_j_1, ..., P_j_m`.
163
180
164
-
In the example above, `A` and `B` would be overlapping because they have the common subclass `C`. Hence, we have to check that the right-hand side `1` is a subtype of `M[X]`
165
-
under the assumptions that `X <: A` and `X <: B`. Under these assumptions `M[X]` reduces
166
-
to `1 & 2`, which gives a type error.
181
+
In the example above, `A` and `B` would be overlapping because they have the common subclass `C`. Hence, we have to check that the right-hand side `1` is a subtype of `M[x.type]` under the assumptions that `x.type <: A` and `x.type <: B`. Under these assumptions `M[x.type]` reduces to `1 & 2`, which gives a type error.
167
182
168
183
For simplicity, we have disregarded the `null` value in this discussion. `null` does not cause a fundamental problem but complicates things somewhat because some forms of patterns do not match `null`.
0 commit comments