From 88ec7974222aa0255482fda146fdc8f7bd31f11b Mon Sep 17 00:00:00 2001 From: Lucas Date: Wed, 8 Mar 2023 15:13:45 +0100 Subject: [PATCH 1/4] Add code tabs to contextual abstractions page --- .../scala3-migration/incompat-type-checker.md | 78 +++++++++++++------ 1 file changed, 56 insertions(+), 22 deletions(-) diff --git a/_overviews/scala3-migration/incompat-type-checker.md b/_overviews/scala3-migration/incompat-type-checker.md index 8c111a199f..5d0f6025e4 100644 --- a/_overviews/scala3-migration/incompat-type-checker.md +++ b/_overviews/scala3-migration/incompat-type-checker.md @@ -18,7 +18,9 @@ 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-3-unsound_vc_1 %} +{% tab 'Scala 3 Only' %} +~~~ scala class Foo[-A](x: List[A]) { def f[B](y: List[B] = x): Unit = ??? } @@ -26,9 +28,9 @@ class Foo[-A](x: List[A]) { class Outer[+A](x: A) { class Inner(y: A) } -``` +~~~ -{% highlight text %} +~~~ text -- Error: src/main/scala/variance.scala:2:8 2 | def f[B](y: List[B] = x): Unit = y | ^^^^^^^^^^^^^^^^^ @@ -37,7 +39,9 @@ class Outer[+A](x: A) { 6 | class Inner(y: A) | ^^^^ |covariant type A occurs in contravariant position in type A of parameter y -{% endhighlight %} +~~~ +{% endtab %} +{% endtabs %} Each problem of this kind needs a specific care. You can try the following options on a case-by-case basis: @@ -47,27 +51,50 @@ You can try the following options on a case-by-case basis: In our example, we can opt for these two solutions: -{% highlight diff %} +{% tabs unsound_vc_2 class=tabs-scala-version %} +{% tab 'Scala 2' for=unsound_vc_2 %} +~~~ scala class Foo[-A](x: List[A]) { -- def f[B](y: List[B] = x): Unit = ??? -+ def f[B](y: List[B]): Unit = ??? -+ def f(): Unit = f(x) + def f[B](y: List[B] = x): Unit = ??? } class Outer[+A](x: A) { -- class Inner(y: A) -+ class Inner[B >: A](y: B) + class Inner(y: A) +} +~~~ +{% endtab %} +{% tab 'Scala 3' for=unsound_vc_2 %} +~~~ scala +class Foo[-A](x: List[A]) { + def f[B](y: List[B]): Unit = ??? + def f(): Unit = f(x) } -{% endhighlight %} + +class Outer[+A](x: A) { + class Inner[B >: A](y: B) +} +~~~ +{% endtab %} +{% endtabs %} Or, as a temporary solution, you can also use the `uncheckedVariance` annotation: -{% highlight diff %} +{% tabs unsound_vc_3 class=tabs-scala-version %} +{% tab 'Scala 2' for=unsound_vc_3 %} +~~~ scala class Outer[+A](x: A) { -- class Inner(y: A) -+ class Inner(y: A @uncheckedVariance) + class Inner(y: A) } -{% endhighlight %} +~~~ +{% endtab %} +{% tab 'Scala 3' for=unsound_vc_3 %} +~~~ scala +class Outer[+A](x: A) { + class Inner(y: A @uncheckedVariance) +} +~~~ +{% endtab %} +{% endtabs %} ## Unsoundness Fixes in Pattern Matching @@ -75,7 +102,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-3-unsound_pm_1 %} +{% tab 'Scala 3 Only' %} +~~~ scala trait Request case class Fetch[A](ids: Set[A]) extends Request @@ -88,17 +117,19 @@ object Request { } } } -``` +~~~ The error message is: -{% highlight text %} +~~~ text -- [E007] Type Mismatch Error: src/main/scala/pattern-match.scala:9:59 9 | case (x @ Fetch(_), y @ Fetch(_)) => combineFetch(x, y) | ^ | Found: (y : Fetch[A$2]) | Required: Fetch[A$1] -{% endhighlight %} +~~~ +{% endtab %} +{% endtabs %} Which is right, there is no proof that `x` and `y` have the same type parameter `A`. @@ -108,9 +139,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 %} From 5189032effb5b77dae766019ca762dcb1b94083e Mon Sep 17 00:00:00 2001 From: Lucas Date: Thu, 9 Mar 2023 11:16:45 +0100 Subject: [PATCH 2/4] Corrections --- .../scala3-migration/incompat-type-checker.md | 73 +++++++------------ 1 file changed, 26 insertions(+), 47 deletions(-) diff --git a/_overviews/scala3-migration/incompat-type-checker.md b/_overviews/scala3-migration/incompat-type-checker.md index 5d0f6025e4..25b932fe0a 100644 --- a/_overviews/scala3-migration/incompat-type-checker.md +++ b/_overviews/scala3-migration/incompat-type-checker.md @@ -18,8 +18,8 @@ It is unsound and might cause runtime failures, as demonstrated by this [test](h The Scala 3 compiler does not permit this anymore. -{% tabs scala-3-unsound_vc_1 %} -{% tab 'Scala 3 Only' %} +{% 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 = ??? @@ -29,8 +29,11 @@ class Outer[+A](x: A) { class Inner(y: A) } ~~~ +{% endtab %} +{% endtabs %} -~~~ text +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 | ^^^^^^^^^^^^^^^^^ @@ -39,9 +42,7 @@ class Outer[+A](x: A) { 6 | class Inner(y: A) | ^^^^ |covariant type A occurs in contravariant position in type A of parameter y -~~~ -{% endtab %} -{% endtabs %} +{% endhighlight %} Each problem of this kind needs a specific care. You can try the following options on a case-by-case basis: @@ -51,50 +52,27 @@ You can try the following options on a case-by-case basis: In our example, we can opt for these two solutions: -{% tabs unsound_vc_2 class=tabs-scala-version %} -{% tab 'Scala 2' for=unsound_vc_2 %} -~~~ scala +{% highlight diff %} class Foo[-A](x: List[A]) { - def f[B](y: List[B] = x): Unit = ??? +- def f[B](y: List[B] = x): Unit = ??? ++ def f[B](y: List[B]): Unit = ??? ++ def f(): Unit = f(x) } class Outer[+A](x: A) { - class Inner(y: A) -} -~~~ -{% endtab %} -{% tab 'Scala 3' for=unsound_vc_2 %} -~~~ scala -class Foo[-A](x: List[A]) { - def f[B](y: List[B]): Unit = ??? - def f(): Unit = f(x) +- class Inner(y: A) ++ class Inner[B >: A](y: B) } - -class Outer[+A](x: A) { - class Inner[B >: A](y: B) -} -~~~ -{% endtab %} -{% endtabs %} +{% endhighlight %} Or, as a temporary solution, you can also use the `uncheckedVariance` annotation: -{% tabs unsound_vc_3 class=tabs-scala-version %} -{% tab 'Scala 2' for=unsound_vc_3 %} -~~~ scala +{% highlight diff %} class Outer[+A](x: A) { - class Inner(y: A) +- class Inner(y: A) ++ class Inner(y: A @uncheckedVariance) } -~~~ -{% endtab %} -{% tab 'Scala 3' for=unsound_vc_3 %} -~~~ scala -class Outer[+A](x: A) { - class Inner(y: A @uncheckedVariance) -} -~~~ -{% endtab %} -{% endtabs %} +{% endhighlight %} ## Unsoundness Fixes in Pattern Matching @@ -102,8 +80,8 @@ 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. -{% tabs scala-3-unsound_pm_1 %} -{% tab 'Scala 3 Only' %} +{% tabs scala-2-unsound_pm_1 %} +{% tab 'Scala 2 Only' %} ~~~ scala trait Request case class Fetch[A](ids: Set[A]) extends Request @@ -118,18 +96,19 @@ object Request { } } ~~~ +{% endtab %} +{% endtabs %} -The error message is: +In Scala 3, the error message is: -~~~ text +{% highlight text %} -- [E007] Type Mismatch Error: src/main/scala/pattern-match.scala:9:59 9 | case (x @ Fetch(_), y @ Fetch(_)) => combineFetch(x, y) | ^ | Found: (y : Fetch[A$2]) | Required: Fetch[A$1] -~~~ -{% endtab %} -{% endtabs %} +{% endhighlight %} + Which is right, there is no proof that `x` and `y` have the same type parameter `A`. From 85dea576f9a72ebe4becfd5cd93a9e718eae0d59 Mon Sep 17 00:00:00 2001 From: Lucas Date: Fri, 10 Mar 2023 10:16:41 +0100 Subject: [PATCH 3/4] Correction of minor issues - Change the spelling of the sentence line 35 - Change the tab line 122 to Scala 2 and 3 - Put the sentence line 129 outside the tab --- Gemfile.lock | 3 +++ _overviews/scala3-migration/incompat-type-checker.md | 11 ++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 9a1627c8b8..cb30f39c76 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -219,6 +219,8 @@ GEM jekyll-feed (~> 0.9) jekyll-seo-tag (~> 2.1) minitest (5.17.0) + nokogiri (1.14.2-x86_64-darwin) + racc (~> 1.4) nokogiri (1.14.2-x86_64-linux) racc (~> 1.4) octokit (4.25.1) @@ -263,6 +265,7 @@ GEM zeitwerk (2.6.7) PLATFORMS + x86_64-darwin-22 x86_64-linux DEPENDENCIES diff --git a/_overviews/scala3-migration/incompat-type-checker.md b/_overviews/scala3-migration/incompat-type-checker.md index 25b932fe0a..6c6728d4fa 100644 --- a/_overviews/scala3-migration/incompat-type-checker.md +++ b/_overviews/scala3-migration/incompat-type-checker.md @@ -32,7 +32,7 @@ class Outer[+A](x: A) { {% endtab %} {% endtabs %} -So if you compile in Scala 3, you should get this kind of error. +So if you compile in Scala 3, you will get the following error. {% highlight text %} -- Error: src/main/scala/variance.scala:2:8 2 | def f[B](y: List[B] = x): Unit = y @@ -118,12 +118,13 @@ 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. -{% tabs scala-3-unsound_pm_2 %} -{% tab 'Scala 3 Only' %} +{% tabs shared-unsound_pm_2 %} +{% tab 'Scala 2 and 3' %} ~~~ 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 %} + +Alternatively, a general but unsafe solution is to cast. + From bb537c2678c12e094b6ad82cbaa4ff157e894a0c Mon Sep 17 00:00:00 2001 From: Lucas Date: Fri, 10 Mar 2023 10:20:48 +0100 Subject: [PATCH 4/4] Delete darwin dependencies --- Gemfile.lock | 3 --- 1 file changed, 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index cb30f39c76..9a1627c8b8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -219,8 +219,6 @@ GEM jekyll-feed (~> 0.9) jekyll-seo-tag (~> 2.1) minitest (5.17.0) - nokogiri (1.14.2-x86_64-darwin) - racc (~> 1.4) nokogiri (1.14.2-x86_64-linux) racc (~> 1.4) octokit (4.25.1) @@ -265,7 +263,6 @@ GEM zeitwerk (2.6.7) PLATFORMS - x86_64-darwin-22 x86_64-linux DEPENDENCIES