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: content/match-types-spec.md
+18-7Lines changed: 18 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -27,6 +27,8 @@ The proposed specification defines a subset of current match types that are cons
27
27
Legal match types use the new, specified reduction rules.
28
28
Illegal match types are rejected, which is a breaking change, and can be recovered under `-source:3.3`.
29
29
30
+
In addition, the proposal gives a specification for `provablyDisjoint` and for the reduction algorithm.
31
+
30
32
## Motivation
31
33
32
34
Currently, match type reduction is implementation-defined.
@@ -57,13 +59,21 @@ In order to guarantee compatibility, we must ensure that, for any given match ty
57
59
Reduction depends on two decision produces:
58
60
59
61
**matching* a scrutinee `X` against a pattern `P` (which we mentioned above), and
60
-
* deciding that a scrutinee `X` is *provably disjoint* from a pattern `P` (disjointness is not affected by this SIP; see below).
62
+
* deciding whether a scrutinee `X` is *provably disjoint* from a pattern `P`.
61
63
62
64
When a scrutinee does not match a given pattern and cannot be proven disjoint from it either, the match type is "stuck" and does not reduce.
63
65
64
66
If matching is delegated to the `TypeComparer` black box, then it is impossible in practice to guarantee the first compatibility property.
65
67
66
-
In order to solve this problem, this SIP provides a specification for match type reduction that is independent of the `TypeComparer` black box.
68
+
In addition to the compatibility properties above, there is also a soundness property that we need to uphold:
69
+
70
+
* if `X match { ... }` reduces to `R` and `Y <: X`, then `Y match { ... }` also reduces to `R`.
71
+
72
+
This requires both that *matching* with a tighter scrutinee gives the same result, and that `provablyDisjoint(X, P)` implies `provablyDisjoint(Y, P)`.
73
+
(Those properties must be relaxed when `Y <: Nothing`, in order not to create more problems; see Olivier Blanvillain's thesis section 4.4.2 for details.)
74
+
With the existing implementation for `provablyDisjoint`, there are reasonable, non-contrived examples that violate this property.
75
+
76
+
In order to solve these problems, this SIP provides a specification for match type reduction that is independent of the `TypeComparer` black box.
67
77
It defines a subset of match type cases that are considered legal.
68
78
Legal cases get a specification for when and how they should reduce for any scrutinee.
69
79
Illegal cases are rejected as being outside of the language.
@@ -290,7 +300,7 @@ Additional study revealed that, while *specifiable*, the current algorithm is ve
290
300
Therefore, this proposal now also includes a proposed specification for "provably disjoint".
291
301
To the best of our knowledge, it is strictly stronger than what is currently implemented, with one exception.
292
302
293
-
The current implementation can prove that `{ type A = Int }` is provably disjoint from `{ type A = Boolean }`.
303
+
The current implementation considers that `{ type A = Int }` is provably disjoint from `{ type A = Boolean }`.
294
304
However, it is not able to prove disjointness between any of the following:
295
305
296
306
*`{ type A = Int }` and `{ type A = Boolean; type B = String }` (adding another type member)
@@ -301,7 +311,7 @@ Therefore, we drop the very ad hoc case of one-to-one type member refinements.
301
311
302
312
On to the specification.
303
313
304
-
A scrutinee `X` is *provably disjoint* from a pattern `P` iff it is probably disjoint from the type `P'` obtained by replacing every type capture in `P` by a wildcard type argument with the same bounds.
314
+
A scrutinee `X` is *provably disjoint* from a pattern `P` iff it is provably disjoint from the type `P'` obtained by replacing every type capture in `P` by a wildcard type argument with the same bounds.
305
315
306
316
We note `X ⋔ Y` to say that `X` and `Y` are provably disjoint.
307
317
Intuitively, that notion is based on the following properties of the Scala language:
@@ -343,7 +353,7 @@ It is defined as follows:
343
353
*`⌈{ α => X } = ⌈X⌉⌉`
344
354
*`⌈X₁ & X₂⌉ = ⌈X₁⌉ & ⌈X₂⌉`
345
355
*`⌈X₁ | X₂⌉ = ⌈X₁⌉ | ⌈X₂⌉`
346
-
*`⌈[...ai] =>> X₁⌉ = [...ai] =>> ⌈X₁]⌉`
356
+
*`⌈[...ai] =>> X₁⌉ = [...ai] =>> ⌈X₁⌉`
347
357
348
358
The following properties hold about `⌈X⌉` (we have paper proofs for those):
349
359
@@ -388,9 +398,9 @@ Most rules go by pair, which makes the whole relation symmetric:
388
398
* Two type lambdas with the same number of type parameters are disjoint if their result types are disjoint:
* An `enum` value case is disjoint from any other `enum` value case (identified by either not being in the same `enum` class, or having a different name):
391
-
*`p.C.x ⋔ q.D.y` if `C != D` or `x != y` (recall: these are enum value cases)
401
+
*`p.C.x ⋔ q.D.y` if `C != D` or `x != y`
392
402
* Two literal types are disjoint if they are different:
393
-
*`c ⋔ d` if `c != d` (where they are literal types)
403
+
*`c ⋔ d` if `c != d`
394
404
* An `enum` value case is always disjoint from a literal type:
395
405
*`c ⋔ q.D.y`
396
406
*`p.C.x ⋔ d`
@@ -560,6 +570,7 @@ As far as we know, those use cases have no workaround if we make type member ext
560
570
Notable prior work related to this proposal includes:
561
571
562
572
-[Current reference page for Scala 3 match types](https://dotty.epfl.ch/docs/reference/new-types/match-types.html)
573
+
-[Abstractions for Type-Level Programming](https://infoscience.epfl.ch/record/294024), Olivier Blanvillain, Chapter 4 (Match Types)
563
574
-["Pre-Sip" discussion in the Contributors forum](https://contributors.scala-lang.org/t/pre-sip-proper-specification-for-match-types/6265) (submitted at the same time as this SIP document)
564
575
-[PR with the proposed implementation](https://github.com/lampepfl/dotty/pull/18262)
0 commit comments