Skip to content
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 21 additions & 8 deletions _overviews/scala3-migration/incompat-type-checker.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,21 @@ It is unsound and might cause runtime failures, as demonstrated by this [test](h

The Scala 3 compiler does not permit this anymore.

```scala
{% tabs scala-2-unsound_vc_1 %}
{% tab 'Scala 2 Only' %}
~~~ scala
class Foo[-A](x: List[A]) {
def f[B](y: List[B] = x): Unit = ???
}

class Outer[+A](x: A) {
class Inner(y: A)
}
```
~~~
{% endtab %}
{% endtabs %}

So if you compile in Scala 3, you should get this kind of error.
{% highlight text %}
-- Error: src/main/scala/variance.scala:2:8
2 | def f[B](y: List[B] = x): Unit = y
Expand Down Expand Up @@ -75,7 +80,9 @@ Scala 3 fixes some unsoundness bugs in pattern matching, preventing some semanti

For instance, the match expression in `combineReq` can be compiled with Scala 2.13 but not with Scala 3.

```scala
{% tabs scala-2-unsound_pm_1 %}
{% tab 'Scala 2 Only' %}
~~~ scala
trait Request
case class Fetch[A](ids: Set[A]) extends Request

Expand All @@ -88,9 +95,11 @@ object Request {
}
}
}
```
~~~
{% endtab %}
{% endtabs %}

The error message is:
In Scala 3, the error message is:

{% highlight text %}
-- [E007] Type Mismatch Error: src/main/scala/pattern-match.scala:9:59
Expand All @@ -100,6 +109,7 @@ The error message is:
| Required: Fetch[A$1]
{% endhighlight %}


Which is right, there is no proof that `x` and `y` have the same type parameter `A`.

Coming from Scala 2, this is clearly an improvement to help us locate mistakes in our code.
Expand All @@ -108,9 +118,12 @@ It is not always easy and sometimes it is even not possible, in which case the c

In this example, we can relax the constraint on `x` and `y` by stating that `A` is a common ancestor of both type arguments.
This makes the compiler type-check the code successfully.

```scala
{% tabs scala-3-unsound_pm_2 %}
{% tab 'Scala 3 Only' %}
~~~ scala
def combineFetch[A](x: Fetch[_ <: A], y: Fetch[_ <: A]): Fetch[A] = Fetch(x.ids ++ y.ids)
```
~~~

Alternatively, a general but unsafe solution is to cast.
{% endtab %}
{% endtabs %}