Skip to content

Commit 580d30b

Browse files
committed
Tweaks to the match types proposal.
1 parent 3c6b360 commit 580d30b

File tree

1 file changed

+18
-7
lines changed

1 file changed

+18
-7
lines changed

content/match-types-spec.md

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ The proposed specification defines a subset of current match types that are cons
2727
Legal match types use the new, specified reduction rules.
2828
Illegal match types are rejected, which is a breaking change, and can be recovered under `-source:3.3`.
2929

30+
In addition, the proposal gives a specification for `provablyDisjoint` and for the reduction algorithm.
31+
3032
## Motivation
3133

3234
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
5759
Reduction depends on two decision produces:
5860

5961
* *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`.
6163

6264
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.
6365

6466
If matching is delegated to the `TypeComparer` black box, then it is impossible in practice to guarantee the first compatibility property.
6567

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.
6777
It defines a subset of match type cases that are considered legal.
6878
Legal cases get a specification for when and how they should reduce for any scrutinee.
6979
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
290300
Therefore, this proposal now also includes a proposed specification for "provably disjoint".
291301
To the best of our knowledge, it is strictly stronger than what is currently implemented, with one exception.
292302

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 }`.
294304
However, it is not able to prove disjointness between any of the following:
295305

296306
* `{ 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.
301311

302312
On to the specification.
303313

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.
305315

306316
We note `X ⋔ Y` to say that `X` and `Y` are provably disjoint.
307317
Intuitively, that notion is based on the following properties of the Scala language:
@@ -343,7 +353,7 @@ It is defined as follows:
343353
* `⌈{ α => X } = ⌈X⌉⌉`
344354
* `⌈X₁ & X₂⌉ = ⌈X₁⌉ & ⌈X₂⌉`
345355
* `⌈X₁ | X₂⌉ = ⌈X₁⌉ | ⌈X₂⌉`
346-
* `⌈[...ai] =>> X₁⌉ = [...ai] =>> ⌈X₁]`
356+
* `⌈[...ai] =>> X₁⌉ = [...ai] =>> ⌈X₁⌉`
347357

348358
The following properties hold about `⌈X⌉` (we have paper proofs for those):
349359

@@ -388,9 +398,9 @@ Most rules go by pair, which makes the whole relation symmetric:
388398
* Two type lambdas with the same number of type parameters are disjoint if their result types are disjoint:
389399
* `[a1, ..., an] =>> S1 ⋔ [b1, ..., bn] =>> T1` if `S1 ⋔ T1`
390400
* 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`
392402
* 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`
394404
* An `enum` value case is always disjoint from a literal type:
395405
* `c ⋔ q.D.y`
396406
* `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
560570
Notable prior work related to this proposal includes:
561571

562572
- [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)
563574
- ["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)
564575
- [PR with the proposed implementation](https://github.com/lampepfl/dotty/pull/18262)
565576

0 commit comments

Comments
 (0)