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
This commit implements one of the missing aspects of Match Types: an
algorithm to determine when it is sound to reduce match types (see
discussion in #5300).
To understand the problem that is being solved, we can look at the
motivational example from the [Haskell Role
paper](https://www.seas.upenn.edu/~sweirich/papers/popl163af-weirich.pdf)
(adapted to Scala).
Given this class:
```scala
class Foo {
type Age
type Type[X] = X match {
case Age => Char
case Int => Boolean
}
def method[X](x: X): Type[X] = ...
}
```
What is the type of `method(1)`?
On master, the compiler answers with "it depends", it could be either
`Char` or `Boolean`, which is obviously unsound:
```scala
val foo = new Foo { type Age = Int }
foo.method(1): Char
(foo: Foo).method(1): Boolean
```
The current algorithm to reduce match types is as follows:
```
foreach pattern
if (scrutinee <:< pattern)
return pattern's result type
else
continue
```
The unsoundness comes from the fact that the answer of `scrutinee <:<
pattern` can change depending on the context, which can result in
equivalent expressions being typed differently.
The proposed solution is to extend the algorithm above with an
additional intersection check:
```
foreach pattern
if (scrutinee <:< pattern)
return pattern's result type
if (!intersecting(scrutinee, pattern))
continue
else
abort
```
Where `intersecting` returns `false` if there is a proof that both of
its arguments are not intersecting. In the absence of such proof, the
reduction is aborted. This algorithm solves the `type Age` example by
preventing the reduction of `Type[X]` (with `X != Age`) when `Age is
abstract. I believe this is enough to have sound type functions without
the need for adding roles to the type system.
0 commit comments