From babff4eea07952159ef714f02136a5ab9042f9ba Mon Sep 17 00:00:00 2001 From: Lucas Date: Wed, 8 Mar 2023 12:27:52 +0100 Subject: [PATCH 1/4] Add code tabs to the Scala 3 Dropped Features --- .../incompat-dropped-features.md | 134 ++++++++++-------- 1 file changed, 77 insertions(+), 57 deletions(-) diff --git a/_overviews/scala3-migration/incompat-dropped-features.md b/_overviews/scala3-migration/incompat-dropped-features.md index 26e4d84ced..4ab9f6854e 100644 --- a/_overviews/scala3-migration/incompat-dropped-features.md +++ b/_overviews/scala3-migration/incompat-dropped-features.md @@ -25,22 +25,24 @@ Most of these changes can be handled automatically during the [Scala 3 migration The Symbol literal syntax is deprecated in Scala 2.13 and dropped in Scala 3. But the `scala.Symbol` class still exists so that each string literal can be safely replaced by an application of `Symbol`. -This piece of code cannot be compiled with Scala 3: +{% tabs scala-3-literals_1 %} +{% tab 'Scala 3 Only' %} -```scala +This piece of code cannot be compiled with Scala 3: +~~~scala val values: Map[Symbol, Int] = Map('abc -> 1) val abc = values('abc) // Migration Warning: symbol literal 'abc is no longer supported -``` +~~~ The [Scala 3 migration compilation](tooling-migration-mode.html) rewrites the code into: - -{% highlight diff %} +~~~ scala val values: Map[Symbol, Int] = Map(Symbol("abc") -> 1) --val abc = values('abc) -+val abc = values(Symbol("abc")) -{% endhighlight %} +val abc = values(Symbol("abc")) +~~~ +{% endtab %} +{% endtabs %} Although the `Symbol` class is useful during the transition, beware that it is deprecated and will be removed from the `scala-library` in a future version. You are recommended, as a second step, to replace every use of `Symbol` with a plain string literals `"abc"` or a custom dedicated class. @@ -52,47 +54,52 @@ The `do` keyword has acquired a different meaning in the [New Control Syntax]({{ To avoid confusion, the traditional `do while ()` construct is dropped. It is recommended to use the equivalent `while ({ ; }) ()` that can be cross-compiled, or the new Scala 3 syntax `while { ; } do ()`. -The following piece of code cannot be compiled with Scala 3. +{% tabs scala-3-do_while_1 %} +{% tab 'Scala 3 Only' %} -```scala +The following piece of code cannot be compiled with Scala 3. +~~~ scala do { // Migration Warning: `do while ` is no longer supported i += 1 } while (f(i) == 0) -``` +~~~ The [Scala 3 migration compilation](tooling-migration-mode.html) rewrites it into. - -```scala +~~~ scala while ({ { i += 1 } ; f(i) == 0}) () -``` +~~~ +{% endtab %} +{% endtabs %} ## Auto-application Auto-application is the syntax of calling an empty-paren method such as `def toInt(): Int` without passing an empty argument list. It is deprecated in Scala 2.13 and dropped in Scala 3. -The following code is invalid in Scala 3: +{% tabs scala-3-auto_application_1 %} +{% tab 'Scala 3 Only' %} -```scala +The following code is invalid in Scala 3: +~~~ scala object Hello { def message(): String = "Hello" } println(Hello.message) // Migration Warning: method message must be called with () argument -``` +~~~ The [Scala 3 migration compilation](tooling-migration-mode.html) rewrites it into: - -{% highlight diff %} +~~~ scala object Hello { def message(): String = "Hello" } --println(Hello.message) -+println(Hello.message()) -{% endhighlight %} +println(Hello.message()) +~~~ +{% endtab %} +{% endtabs %} Auto-application is covered in detail in [this page]({{ site.scala3ref }}/dropped-features/auto-apply.html) of the Scala 3 reference documentation. @@ -101,48 +108,55 @@ Auto-application is covered in detail in [this page]({{ site.scala3ref }}/droppe Scala 3 introduces [Automatic Eta-Expansion]({{ site.scala3ref }}/changed-features/eta-expansion-spec.html) which will deprecate the method to value syntax `m _`. Furthermore Scala 3 does not allow eta-expansion of values to nullary functions anymore. -Thus, this piece of code is invalid in Scala 3: +{% tabs scala-3-eta_expansion_1 %} +{% tab 'Scala 3 Only' %} -```scala +Thus, this piece of code is invalid in Scala 3: +~~~ scala val x = 1 val f: () => Int = x _ // Migration Warning: The syntax ` _` is no longer supported; -``` +~~~ The [Scala 3 migration compilation](tooling-migration-mode.html) rewrites it into: - -{% highlight diff %} +~~~ scala val x = 1 --val f: () => Int = x _ -+val f: () => Int = (() => x) -{% endhighlight %} +val f: () => Int = (() => x) +~~~ +{% endtab %} +{% endtabs %} ## `any2stringadd` conversion The implicit `Predef.any2stringadd` conversion is deprecated in Scala 2.13 and dropped in Scala 3. -This piece of code does not compile anymore. +{% tabs scala-3-any2stringadd_1 %} +{% tab 'Scala 3 Only' %} -```scala +This piece of code does not compile anymore. +~~~ scala val str = new AnyRef + "foo" // Error: value + is not a member of Object -``` +~~~ The conversion to `String` must be applied explicitly, for instance with `String.valueOf`. - -{% highlight diff %} --val str = new AnyRef + "foo" -+val str = String.valueOf(new AnyRef) + "foo" -{% endhighlight %} +~~~ scala +val str = String.valueOf(new AnyRef) + "foo" +~~~ This rewrite can be applied by the `fix.scala213.Any2StringAdd` Scalafix rule in [`scala/scala-rewrites`](https://index.scala-lang.org/scala/scala-rewrites/scala-rewrites/0.1.2?target=_2.13). +{% endtab %} +{% endtabs %} ## Early Initializer Early initializers are deprecated in Scala 2.13 and dropped in Scala 3. They were rarely used, and mostly to compensate for the lack of [Trait parameters]({{ site.scala3ref }}/other-new-features/trait-parameters.html) which are now supported in Scala 3. +{% tabs scala-3-initializer_1 %} +{% tab 'Scala 3 Only' %} + That is why the following piece of code does not compile anymore. -```scala +~~~ scala trait Bar { val name: String val size: Int = name.size @@ -151,71 +165,77 @@ trait Bar { object Foo extends { val name = "Foo" } with Bar -``` +~~~ The Scala 3 compiler produces two error messages: -{% highlight text %} +~~~ scala -- Error: src/main/scala/early-initializer.scala:6:19 6 |object Foo extends { | ^ | `extends` must be followed by at least one parent -{% endhighlight %} - -{% highlight text %} -- [E009] Syntax Error: src/main/scala/early-initializer.scala:8:2 8 |} with Bar | ^^^^ | Early definitions are not supported; use trait parameters instead -{% endhighlight %} +~~~ It suggests to use trait parameters which would give us: - -```scala +~~~ scala trait Bar(name: String) { val size: Int = name.size } object Foo extends Bar("Foo") -``` +~~~ +{% endtab %} +{% endtabs %} Since trait parameters are not available in Scala 2.13, it does not cross-compile. If you need a cross-compiling solution you can use an intermediate class that carries the early initialized `val`s and `var`s as constructor parameters. -```scala +{% tabs scala-3-initializer_4 %} +{% tab 'Scala 3 Only' %} +~~~ scala abstract class BarEarlyInit(val name: String) extends Bar object Foo extends BarEarlyInit("Foo") -``` +~~~ In the case of a class, it is also possible to use a secondary constructor with a fixed value, as shown by: - -```scala +~~~ scala class Fizz private (val name: String) extends Bar { def this() = this("Fizz") } -``` +~~~ +{% endtab %} +{% endtabs %} ## Existential Type Existential type is a [dropped feature]({{ site.scala3ref }}/dropped-features/existential-types.html), which makes the following code invalid. + +{% tabs scala-3-existential_1 %} +{% tab 'Scala 3 Only' %} -```scala +~~~ scala def foo: List[Class[T]] forSome { type T } // Error: Existential types are no longer supported -``` +~~~ > Existential type is an experimental feature in Scala 2.13 that must be enabled explicitly either by importing `import scala.language.existentials` or by setting the `-language:existentials` compiler flag. The proposed solution is to introduce an enclosing type that carries the dependent type: -```scala +~~~ scala trait Bar { type T val value: List[Class[T]] } def foo: Bar -``` +~~~ +{% endtab %} +{% endtabs %} Note that using a wildcard argument, `_` or `?`, is often simpler but is not always possible. For instance you could replace `List[T] forSome { type T }` by `List[?]`. From 1166c55bfc8f3a08cab101b527292b1fb27508c0 Mon Sep 17 00:00:00 2001 From: Lucas Date: Fri, 10 Mar 2023 14:55:29 +0100 Subject: [PATCH 2/4] Corrections of the tabs - Change some titles - Change spelling of errors - Put out some sentence from tabs --- .../incompat-dropped-features.md | 123 ++++++++++-------- 1 file changed, 70 insertions(+), 53 deletions(-) diff --git a/_overviews/scala3-migration/incompat-dropped-features.md b/_overviews/scala3-migration/incompat-dropped-features.md index 4ab9f6854e..51cc772eb3 100644 --- a/_overviews/scala3-migration/incompat-dropped-features.md +++ b/_overviews/scala3-migration/incompat-dropped-features.md @@ -25,24 +25,25 @@ Most of these changes can be handled automatically during the [Scala 3 migration The Symbol literal syntax is deprecated in Scala 2.13 and dropped in Scala 3. But the `scala.Symbol` class still exists so that each string literal can be safely replaced by an application of `Symbol`. -{% tabs scala-3-literals_1 %} -{% tab 'Scala 3 Only' %} - This piece of code cannot be compiled with Scala 3: + +{% tabs scala-2-literals_1 %} +{% tab 'Scala 2 Only' %} ~~~scala val values: Map[Symbol, Int] = Map('abc -> 1) -val abc = values('abc) // Migration Warning: symbol literal 'abc is no longer supported +val abc = values('abc) // In Scala 3, Migration Warning: symbol literal 'abc is no longer supported ~~~ +{% endtab %} +{% endtabs %} The [Scala 3 migration compilation](tooling-migration-mode.html) rewrites the code into: -~~~ scala +{% highlight diff %} val values: Map[Symbol, Int] = Map(Symbol("abc") -> 1) -val abc = values(Symbol("abc")) -~~~ -{% endtab %} -{% endtabs %} +-val abc = values('abc) ++val abc = values(Symbol("abc")) +{% endhighlight %} Although the `Symbol` class is useful during the transition, beware that it is deprecated and will be removed from the `scala-library` in a future version. You are recommended, as a second step, to replace every use of `Symbol` with a plain string literals `"abc"` or a custom dedicated class. @@ -54,17 +55,21 @@ The `do` keyword has acquired a different meaning in the [New Control Syntax]({{ To avoid confusion, the traditional `do while ()` construct is dropped. It is recommended to use the equivalent `while ({ ; }) ()` that can be cross-compiled, or the new Scala 3 syntax `while { ; } do ()`. -{% tabs scala-3-do_while_1 %} -{% tab 'Scala 3 Only' %} - The following piece of code cannot be compiled with Scala 3. + +{% tabs scala-2-do_while_1 %} +{% tab 'Scala 2 Only' %} ~~~ scala -do { // Migration Warning: `do while ` is no longer supported +do { // In Scala 3, Migration Warning: `do while ` is no longer supported i += 1 } while (f(i) == 0) ~~~ +{% endtab %} +{% endtabs %} The [Scala 3 migration compilation](tooling-migration-mode.html) rewrites it into. +{% tabs scala-3-do_while_2 %} +{% tab 'Scala 3 Only' %} ~~~ scala while ({ { i += 1 @@ -78,28 +83,29 @@ while ({ { Auto-application is the syntax of calling an empty-paren method such as `def toInt(): Int` without passing an empty argument list. It is deprecated in Scala 2.13 and dropped in Scala 3. -{% tabs scala-3-auto_application_1 %} -{% tab 'Scala 3 Only' %} - The following code is invalid in Scala 3: + +{% tabs scala-2-auto_application_1 %} +{% tab 'Scala 2 Only' %} ~~~ scala object Hello { def message(): String = "Hello" } -println(Hello.message) // Migration Warning: method message must be called with () argument +println(Hello.message) // In Scala 3, Migration Warning: method message must be called with () argument ~~~ +{% endtab %} +{% endtabs %} The [Scala 3 migration compilation](tooling-migration-mode.html) rewrites it into: -~~~ scala +{% highlight diff %} object Hello { def message(): String = "Hello" } -println(Hello.message()) -~~~ -{% endtab %} -{% endtabs %} +-println(Hello.message) ++println(Hello.message()) +{% endhighlight %} Auto-application is covered in detail in [this page]({{ site.scala3ref }}/dropped-features/auto-apply.html) of the Scala 3 reference documentation. @@ -108,54 +114,55 @@ Auto-application is covered in detail in [this page]({{ site.scala3ref }}/droppe Scala 3 introduces [Automatic Eta-Expansion]({{ site.scala3ref }}/changed-features/eta-expansion-spec.html) which will deprecate the method to value syntax `m _`. Furthermore Scala 3 does not allow eta-expansion of values to nullary functions anymore. -{% tabs scala-3-eta_expansion_1 %} -{% tab 'Scala 3 Only' %} - Thus, this piece of code is invalid in Scala 3: -~~~ scala -val x = 1 -val f: () => Int = x _ // Migration Warning: The syntax ` _` is no longer supported; -~~~ -The [Scala 3 migration compilation](tooling-migration-mode.html) rewrites it into: +{% tabs scala-2-eta_expansion_1 %} +{% tab 'Scala 2 Only' %} ~~~ scala val x = 1 -val f: () => Int = (() => x) +val f: () => Int = x _ // In Scala 3, Migration Warning: The syntax ` _` is no longer supported; ~~~ {% endtab %} {% endtabs %} +The [Scala 3 migration compilation](tooling-migration-mode.html) rewrites it into: +{% highlight diff %} +val x = 1 +-val f: () => Int = x _ ++val f: () => Int = (() => x) +{% endhighlight %} + ## `any2stringadd` conversion The implicit `Predef.any2stringadd` conversion is deprecated in Scala 2.13 and dropped in Scala 3. -{% tabs scala-3-any2stringadd_1 %} -{% tab 'Scala 3 Only' %} +This piece of code does not compile anymore in Scala 3. -This piece of code does not compile anymore. +{% tabs scala-2-any2stringadd_1 %} +{% tab 'Scala 2 Only' %} ~~~ scala -val str = new AnyRef + "foo" // Error: value + is not a member of Object +val str = new AnyRef + "foo" // In Scala 3, Error: value + is not a member of Object ~~~ +{% endtab %} +{% endtabs %} The conversion to `String` must be applied explicitly, for instance with `String.valueOf`. -~~~ scala -val str = String.valueOf(new AnyRef) + "foo" -~~~ +{% highlight diff %} +-val str = new AnyRef + "foo" ++val str = String.valueOf(new AnyRef) + "foo" +{% endhighlight %} This rewrite can be applied by the `fix.scala213.Any2StringAdd` Scalafix rule in [`scala/scala-rewrites`](https://index.scala-lang.org/scala/scala-rewrites/scala-rewrites/0.1.2?target=_2.13). -{% endtab %} -{% endtabs %} ## Early Initializer Early initializers are deprecated in Scala 2.13 and dropped in Scala 3. They were rarely used, and mostly to compensate for the lack of [Trait parameters]({{ site.scala3ref }}/other-new-features/trait-parameters.html) which are now supported in Scala 3. -{% tabs scala-3-initializer_1 %} -{% tab 'Scala 3 Only' %} - -That is why the following piece of code does not compile anymore. +That is why the following piece of code does not compile anymore in Scala 3. +{% tabs scala-2-initializer_1 %} +{% tab 'Scala 2 Only' %} ~~~ scala trait Bar { val name: String @@ -166,21 +173,28 @@ object Foo extends { val name = "Foo" } with Bar ~~~ +{% endtab %} +{% endtabs %} The Scala 3 compiler produces two error messages: -~~~ scala +{% highlight text %} -- Error: src/main/scala/early-initializer.scala:6:19 6 |object Foo extends { | ^ | `extends` must be followed by at least one parent +{% endhighlight %} +{% highlight text %} -- [E009] Syntax Error: src/main/scala/early-initializer.scala:8:2 8 |} with Bar | ^^^^ | Early definitions are not supported; use trait parameters instead -~~~ +{% endhighlight %} It suggests to use trait parameters which would give us: + +{% tabs scala-3-initializer_2 %} +{% tab 'Scala 3 Only' %} ~~~ scala trait Bar(name: String) { val size: Int = name.size @@ -194,8 +208,8 @@ object Foo extends Bar("Foo") Since trait parameters are not available in Scala 2.13, it does not cross-compile. If you need a cross-compiling solution you can use an intermediate class that carries the early initialized `val`s and `var`s as constructor parameters. -{% tabs scala-3-initializer_4 %} -{% tab 'Scala 3 Only' %} +{% tabs shared-initializer_4 %} +{% tab 'Scala 2 and 3' %} ~~~ scala abstract class BarEarlyInit(val name: String) extends Bar @@ -215,17 +229,20 @@ class Fizz private (val name: String) extends Bar { Existential type is a [dropped feature]({{ site.scala3ref }}/dropped-features/existential-types.html), which makes the following code invalid. -{% tabs scala-3-existential_1 %} -{% tab 'Scala 3 Only' %} - +{% tabs scala-2-existential_1 %} +{% tab 'Scala 2 Only' %} ~~~ scala -def foo: List[Class[T]] forSome { type T } // Error: Existential types are no longer supported +def foo: List[Class[T]] forSome { type T } // In Scala 3, Error: Existential types are no longer supported ~~~ +{% endtab %} +{% endtabs %} > Existential type is an experimental feature in Scala 2.13 that must be enabled explicitly either by importing `import scala.language.existentials` or by setting the `-language:existentials` compiler flag. -The proposed solution is to introduce an enclosing type that carries the dependent type: +In Scala 3, the proposed solution is to introduce an enclosing type that carries the dependent type: +{% tabs scala-3-existential_1 %} +{% tab 'Scala 3 Only' %} ~~~ scala trait Bar { type T From 85b3546ec9f32abd9ba821d6bbde7bc6d646fcdb Mon Sep 17 00:00:00 2001 From: Lucas Date: Sat, 11 Mar 2023 19:05:12 +0100 Subject: [PATCH 3/4] Change spelling Scala 3 Only to Scala 2 and 3 --- _overviews/scala3-migration/incompat-dropped-features.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_overviews/scala3-migration/incompat-dropped-features.md b/_overviews/scala3-migration/incompat-dropped-features.md index 51cc772eb3..4444860db0 100644 --- a/_overviews/scala3-migration/incompat-dropped-features.md +++ b/_overviews/scala3-migration/incompat-dropped-features.md @@ -241,8 +241,8 @@ def foo: List[Class[T]] forSome { type T } // In Scala 3, Error: Existential typ In Scala 3, the proposed solution is to introduce an enclosing type that carries the dependent type: -{% tabs scala-3-existential_1 %} -{% tab 'Scala 3 Only' %} +{% tabs shared-existential_1 %} +{% tab 'Scala 2 and 3' %} ~~~ scala trait Bar { type T From d919719490f5f127de35af27b348ac149b8fe1ad Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Mon, 13 Mar 2023 09:03:17 +0100 Subject: [PATCH 4/4] Update _overviews/scala3-migration/incompat-dropped-features.md --- _overviews/scala3-migration/incompat-dropped-features.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_overviews/scala3-migration/incompat-dropped-features.md b/_overviews/scala3-migration/incompat-dropped-features.md index 4444860db0..ae7e3e3f1e 100644 --- a/_overviews/scala3-migration/incompat-dropped-features.md +++ b/_overviews/scala3-migration/incompat-dropped-features.md @@ -29,7 +29,7 @@ This piece of code cannot be compiled with Scala 3: {% tabs scala-2-literals_1 %} {% tab 'Scala 2 Only' %} -~~~scala +~~~ scala val values: Map[Symbol, Int] = Map('abc -> 1) val abc = values('abc) // In Scala 3, Migration Warning: symbol literal 'abc is no longer supported