From cc111ca2a2509e01911bd2d715f3f0ad66036aa6 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Sat, 9 Mar 2024 18:32:11 -0800 Subject: [PATCH 1/3] Explain -Xsource-features --- .../tooling-scala2-xsource3.md | 44 +++++++++++++------ 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/_overviews/scala3-migration/tooling-scala2-xsource3.md b/_overviews/scala3-migration/tooling-scala2-xsource3.md index 42171c23dc..03a1b47dcb 100644 --- a/_overviews/scala3-migration/tooling-scala2-xsource3.md +++ b/_overviews/scala3-migration/tooling-scala2-xsource3.md @@ -21,18 +21,24 @@ With Scala 2.13.13 and newer, the `-Xsource:3` flag comes in two variants: - `Xsource:3` enables warnings relevant for migrating a codebase to Scala 3. In addition to new warnings, the flag enables certain benign Scala 3 syntaxes such as `import p.*`. - - `Xsource:3-cross` is useful for projects that cross-build between Scala 2 and 3 for a longer period of time. - For certain language constructs that trigger a warning with `-Xsource:3`, the behavior changes to match Scala 3. + - `Xsource:3-cross` is useful for projects that cross-build between Scala 2 and 3. + It is intended to reduce the maintenance burden of a cross-built project over time. + Certain language constructs have been backported from Scala 3 in order to improve compatibility. + Instead of warning about a behavior change in Scala 3, it adopts the new behavior. + These features can be selectively enabled using `-Xsource-features` (since 2.13.14). Details about individual warnings are listed below on this page. -## Fatal warnings and quick fixes +## Warnings as errors, and quick fixes -By default, Scala 3 migration warnings emitted by Scala 2.13 are fatal, i.e., they are reported as errors. -This can be changed using `-Wconf`, for example `-Wconf:cat=scala3-migration:w` changes them to be reported as warnings. -Alternatively, `-Xmigration` has the same effect. +By default, Scala 3 migration warnings emitted by Scala 2.13 are reported as errors, +using the default configuration, `-Wconf:cat=scala3-migration:e`. +That ensures that migration messaging is more visible. +Diagnostics can be emitted as warnings by specifying `-Wconf:cat=scala3-migration:w`. +Typically, emitting warnings instead of errors will cause more diagnostics to be reported. -The [`@nowarn` annotation](https://www.scala-lang.org/api/current/scala/annotation/nowarn.html) can be used to suppress individual warnings, which also works with fatal warnings enabled. +The [`@nowarn` annotation](https://www.scala-lang.org/api/current/scala/annotation/nowarn.html) can be used in program sources to suppress individual warnings. +Diagnostics are suppressed before they are promoted to errors, so that `@nowarn` takes precedence over `-Wconf` and `-Werror`. The Scala 2.13 compiler implements quick fixes for many Scala 3 migration warnings. Quick fixes are displayed in Metals-based IDEs (not yet in IntelliJ), and they can be applied directly to the source code using the `-quickfix` flag, for example `-quickfix:cat=scala3-migration`. @@ -81,19 +87,29 @@ class B extends A { def f = "hi" } It is possible to work around this using version-dependent source files, see [scala/scala-xml#675](https://github.com/scala/scala-xml/pull/675) as an example. -Working around the case companion `FunctionN` parent change is currently difficult (Scala 2.13.13), a solution is being discussed at [scala/bug#12961](https://github.com/scala/bug/issues/12961). +Working around the case companion `FunctionN` parent change is difficult in Scala 2.13.13. + +From Scala 2.13.14, binary incompatible features can be selectively enabled under `-Xsource-features`, where the features can be enumerated. ### Changes in language semantics The following table shows cases where `-Xsource:3-cross` adopts language feature semantics from Scala 3. +Optionally, they can be selected using `-Xsource-features`. +`-Xsource:3-cross` is a shorthand for `-Xsource:3 -Xsource-features:_`. +However, since the scope of available features may expand in future versions, +it is recommended to either specify them explicitly or fix them to the grouped features `-Xsource-features:v2.13.13` or `-Xsource-features:v2.13.14`. -| Feature | `-Xsource:3` | `-Xsource:3-cross` | +| `-Xsource-features` | `-Xsource:3` | `-Xsource:3-cross` | |--- |--- |--- | -| `(x: Any) + ""` is deprecated | deprecation warning | does not compile, implicit `any2stringadd` is not inferred | -| Unicode escapes in triple-quoted strings and raw interpolations (`"""\u0061"""`) | fatal warning, escape is processed | escape is not processed | -| Leading infix operators continue the previous line 1 | fatal warning, second line is a separate expression | operation continues the previous line | -| Desugaring of string interpolators using `StringContext` | fatal warning if the interpolation references a `StringContext` in scope different from `scala.StringContext` | desugaring always uses `scala.StringContext` | -| An implicit for type `p.A` is found in the package prefix `p` | fatal warning | the package prefix `p` is no longer part of the implicit search scope | +| `(x: Any) + ""` is deprecated (`any2stringadd`) | deprecation warning | does not compile, implicit `any2stringadd` is not inferred | +| Unicode escapes in triple-quoted strings and raw interpolations (`"""\u0061"""`) (`unicode-escapes-raw`) | fatal warning, escape is processed | escape is not processed | +| Leading infix operators continue the previous line 1 (`leading-infix`) | fatal warning, second line is a separate expression | operation continues the previous line | +| Desugaring of string interpolators using `StringContext` (`string-context-scope`) | fatal warning if the interpolation references a `StringContext` in scope different from `scala.StringContext` | desugaring always uses `scala.StringContext` | +| An implicit for type `p.A` is found in the package prefix `p` (`package-prefix-implicits`) | fatal warning | the package prefix `p` is no longer part of the implicit search scope | +| (`implicit-resolution`) | fatal warning | use Scala-3-style downwards comparisons for implicit search and overloading resolution | +| (`case-apply-copy-access`) | warning | constructor modifiers are used for apply / copy methods of case classes | +| (`case-companion-function`) | warning | synthetic case companion objects no longer extend FunctionN | +| (`infer-override`) | warning | inferred type of member uses type of overridden member | Example 1: From 874642244f3e264e08e84754ee794d683ca63456 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Fri, 19 Apr 2024 11:52:32 -0700 Subject: [PATCH 2/3] More feature words, C.apply adaptation --- _overviews/scala3-migration/tooling-scala2-xsource3.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/_overviews/scala3-migration/tooling-scala2-xsource3.md b/_overviews/scala3-migration/tooling-scala2-xsource3.md index 03a1b47dcb..5498ea9ce0 100644 --- a/_overviews/scala3-migration/tooling-scala2-xsource3.md +++ b/_overviews/scala3-migration/tooling-scala2-xsource3.md @@ -106,10 +106,10 @@ it is recommended to either specify them explicitly or fix them to the grouped f | Leading infix operators continue the previous line 1 (`leading-infix`) | fatal warning, second line is a separate expression | operation continues the previous line | | Desugaring of string interpolators using `StringContext` (`string-context-scope`) | fatal warning if the interpolation references a `StringContext` in scope different from `scala.StringContext` | desugaring always uses `scala.StringContext` | | An implicit for type `p.A` is found in the package prefix `p` (`package-prefix-implicits`) | fatal warning | the package prefix `p` is no longer part of the implicit search scope | -| (`implicit-resolution`) | fatal warning | use Scala-3-style downwards comparisons for implicit search and overloading resolution | -| (`case-apply-copy-access`) | warning | constructor modifiers are used for apply / copy methods of case classes | -| (`case-companion-function`) | warning | synthetic case companion objects no longer extend FunctionN | -| (`infer-override`) | warning | inferred type of member uses type of overridden member | +| Specificity during implicit search (`implicit-resolution`) | fatal warning | use Scala-3-style downwards comparisons for implicit search and overloading resolution | +| Modifiers of synthetic methods (`case-apply-copy-access`) | fatal warning | constructor modifiers are used for apply / copy methods of case classes | +| Companions are Functions (`case-companion-function`) | fatal warning at use site | synthetic case companion objects no longer extend FunctionN, but are adapted at use site with warning | +| Override type inference (`infer-override`) | fatal warning | inferred type of member uses type of overridden member | Example 1: From 27b65eccb342c9675428bd43f4b77891a9bf2d6d Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Mon, 22 Apr 2024 11:26:29 +0200 Subject: [PATCH 3/3] more adjustments to Xsource-features --- .../tooling-scala2-xsource3.md | 113 ++++++++++-------- 1 file changed, 65 insertions(+), 48 deletions(-) diff --git a/_overviews/scala3-migration/tooling-scala2-xsource3.md b/_overviews/scala3-migration/tooling-scala2-xsource3.md index 5498ea9ce0..63ecbb6e8b 100644 --- a/_overviews/scala3-migration/tooling-scala2-xsource3.md +++ b/_overviews/scala3-migration/tooling-scala2-xsource3.md @@ -11,29 +11,22 @@ The Scala 2.13 compiler issues helpful migration warnings with the `-Xsource:3` Before moving to the Scala 3 compiler, it's recommended to enable this flag in Scala 2 and address the new warnings. -There is also a variant, `-Xsource:3-cross`; see below. **Note: Enabling `-Xsource:3-cross` in Scala 2.13.13 breaks binary compatibility, follow [scala/bug#12961](https://github.com/scala/bug/issues/12961) for details.** - -This page explains the details behind the flags. An overview is shown using `scalac -Xsource:help`. +Usage information is shown with `scalac -Xsource:help`. ## Migration vs cross-building -With Scala 2.13.13 and newer, the `-Xsource:3` flag comes in two variants: +With Scala 2.13.14 and newer, the `-Xsource:3` flag supports two scenarios: - `Xsource:3` enables warnings relevant for migrating a codebase to Scala 3. In addition to new warnings, the flag enables certain benign Scala 3 syntaxes such as `import p.*`. - - `Xsource:3-cross` is useful for projects that cross-build between Scala 2 and 3. - It is intended to reduce the maintenance burden of a cross-built project over time. + - Adding the `-Xsource-features:` flag is useful to reduce the maintenance burden of projects that cross-build between Scala 2 and 3. Certain language constructs have been backported from Scala 3 in order to improve compatibility. Instead of warning about a behavior change in Scala 3, it adopts the new behavior. - These features can be selectively enabled using `-Xsource-features` (since 2.13.14). - -Details about individual warnings are listed below on this page. ## Warnings as errors, and quick fixes -By default, Scala 3 migration warnings emitted by Scala 2.13 are reported as errors, -using the default configuration, `-Wconf:cat=scala3-migration:e`. -That ensures that migration messaging is more visible. +By default, Scala 3 migration warnings emitted by Scala 2.13 are reported as errors, using the default configuration, `-Wconf:cat=scala3-migration:e`. +This ensures that migration messaging is more visible. Diagnostics can be emitted as warnings by specifying `-Wconf:cat=scala3-migration:w`. Typically, emitting warnings instead of errors will cause more diagnostics to be reported. @@ -41,8 +34,8 @@ The [`@nowarn` annotation](https://www.scala-lang.org/api/current/scala/annotati Diagnostics are suppressed before they are promoted to errors, so that `@nowarn` takes precedence over `-Wconf` and `-Werror`. The Scala 2.13 compiler implements quick fixes for many Scala 3 migration warnings. -Quick fixes are displayed in Metals-based IDEs (not yet in IntelliJ), and they can be applied directly to the source code using the `-quickfix` flag, for example `-quickfix:cat=scala3-migration`. -See also `scalac -quickfix:help`. +Quick fixes are displayed in Metals-based IDEs (not yet in IntelliJ), or they can be applied directly to the source code using the `-quickfix` flag, for example `-quickfix:cat=scala3-migration`. +See also `scala -quickfix:help`. ## Enabled Scala 3 syntax @@ -57,64 +50,88 @@ The `-Xsource:3` flag enables the following Scala 3 syntaxes in Scala 2: ## Scala 3 migration warnings in detail -Many Scala 3 migration warnings are easy to understand and identical under `-Xsource:3` and `-Xsource:3-cross`, e.g., for implicit definitions without an explicit type: +Many Scala 3 migration warnings are easy to understand, e.g., for implicit definitions without an explicit type: -{% highlight text %} +{% highlight scala %} scala> object O { implicit val s = "" } ^ error: Implicit definition must have explicit type (inferred String) [quickfixable] {% endhighlight %} -The next paragraphs explain where the behavior changes between `-Xsource:3` and `-Xsource:3-cross`. +## Enabling Scala 3 features with `-Xsource-features` -### Changes affecting binary encoding +Certain Scala 3 language changes have been backported and can be enabled using `-Xsource-features`; usage and available features are shown with `-Xsource-features:help`. -As of Scala 2.13.13, there are 3 changes under `-Xsource:3-cross` that affect binary encoding of classfiles. For all of these changes a fatal warning is issued under `-Xsource:3`. +When enabling a feature, the corresponding migration warning is no longer issued. - 1. The constructor modifiers of case classes (`case class C private[p] (x: Int)`) are copied to the synthetic `apply` and `copy` methods. - 1. The synthetic companion objects of case classes no longer extend `FunctionN`. - 1. Overriding methods without an explicit return type inherit the return type from the parent (instead of using the inferred type of the method body). +{% highlight scala %} +scala> raw"\u0061" + ^ + warning: Unicode escapes in raw interpolations are deprecated; use literal characters instead +val res0: String = a -For projects that are already cross-building between Scala 2 and Scala 3 with existing releases for both, enabling `-Xsource:3-cross` breaks binary compatibility. For example, if a library defines +scala> :setting -Xsource:3 -{% highlight scala %} -trait A { def f: Object } -class B extends A { def f = "hi" } -{% endhighlight %} +scala> raw"\u0061" + ^ + error: Unicode escapes in raw interpolations are ignored in Scala 3 (or with -Xsource-features:unicode-escapes-raw); use literal characters instead + Scala 3 migration messages are errors under -Xsource:3. Use -Wconf / @nowarn to filter them or add -Xmigration to demote them to warnings. + Applicable -Wconf / @nowarn filters for this fatal warning: msg=, cat=scala3-migration, site=res1 - - enabling `-Xsource:3-cross` breaks binary compatibility on Scala 2.13: existing releases have `A.f: String`, the new version will have `A.f: Object` - - adding an explicit result type `A.f: String` breaks binary compatibility on Scala 3: existing releases have `A.f: Object` +scala> :setting -Xsource-features:unicode-escapes-raw -It is possible to work around this using version-dependent source files, see [scala/scala-xml#675](https://github.com/scala/scala-xml/pull/675) as an example. +scala> raw"\u0061" +val res1: String = \u0061 +{% endhighlight %} -Working around the case companion `FunctionN` parent change is difficult in Scala 2.13.13. +For every such language feature, a migration warning is issued under plain `-Xsource:3`. +Enabling the feature silences the warning and adopts the changed behavior. +To avoid silent language changes when upgrading to a new Scala 2.13 version, it is recommended to enable features explicitly or use a group (e.g., `-Xsource-features:v2.13.14`). -From Scala 2.13.14, binary incompatible features can be selectively enabled under `-Xsource-features`, where the features can be enumerated. +`-Xsource:3-cross` is a shorthand for `-Xsource:3 -Xsource-features:_`. ### Changes in language semantics -The following table shows cases where `-Xsource:3-cross` adopts language feature semantics from Scala 3. -Optionally, they can be selected using `-Xsource-features`. -`-Xsource:3-cross` is a shorthand for `-Xsource:3 -Xsource-features:_`. -However, since the scope of available features may expand in future versions, -it is recommended to either specify them explicitly or fix them to the grouped features `-Xsource-features:v2.13.13` or `-Xsource-features:v2.13.14`. +The following table shows backported Scala 3 language semantics available in `-Xsource-features` / `-Xsource:3-cross`. -| `-Xsource-features` | `-Xsource:3` | `-Xsource:3-cross` | +| Feature flag | `-Xsource:3` behavior | `-Xsource-features` / `-Xsource:3-cross` behavior | |--- |--- |--- | -| `(x: Any) + ""` is deprecated (`any2stringadd`) | deprecation warning | does not compile, implicit `any2stringadd` is not inferred | -| Unicode escapes in triple-quoted strings and raw interpolations (`"""\u0061"""`) (`unicode-escapes-raw`) | fatal warning, escape is processed | escape is not processed | -| Leading infix operators continue the previous line 1 (`leading-infix`) | fatal warning, second line is a separate expression | operation continues the previous line | -| Desugaring of string interpolators using `StringContext` (`string-context-scope`) | fatal warning if the interpolation references a `StringContext` in scope different from `scala.StringContext` | desugaring always uses `scala.StringContext` | -| An implicit for type `p.A` is found in the package prefix `p` (`package-prefix-implicits`) | fatal warning | the package prefix `p` is no longer part of the implicit search scope | -| Specificity during implicit search (`implicit-resolution`) | fatal warning | use Scala-3-style downwards comparisons for implicit search and overloading resolution | -| Modifiers of synthetic methods (`case-apply-copy-access`) | fatal warning | constructor modifiers are used for apply / copy methods of case classes | -| Companions are Functions (`case-companion-function`) | fatal warning at use site | synthetic case companion objects no longer extend FunctionN, but are adapted at use site with warning | -| Override type inference (`infer-override`) | fatal warning | inferred type of member uses type of overridden member | +| `any2stringadd`: `(x: Any) + ""` is deprecated | deprecation warning | does not compile, implicit `any2stringadd` is not inferred | +| `unicode-escapes-raw`: unicode escapes in triple-quoted strings and raw interpolations (`"""\u0061"""`) | fatal warning, escape is processed | escape is not processed | +| `leading-infix`: leading infix operators continue the previous line 1 | fatal warning, second line is a separate expression | operation continues the previous line | +| `string-context-scope`: desugaring of string interpolators using `StringContext` | fatal warning if the interpolation references a `StringContext` in scope different from `scala.StringContext` | desugaring always uses `scala.StringContext` | +| `package-prefix-implicits`: an implicit for type `p.A` is found in the package prefix `p` | fatal warning | the package prefix `p` is no longer part of the implicit search scope | +| `implicit-resolution`: specificity during implicit search | fatal warning | use Scala-3-style [downwards comparisons](https://github.com/scala/scala/pull/6037) for implicit search and overloading resolution | +| `case-apply-copy-access`: modifiers of synthetic methods | fatal warning | constructor modifiers are used for apply / copy methods of case classes | +| `case-companion-function`: companions are Functions | fatal warning at use site | synthetic case companion objects no longer extend FunctionN, but are adapted at use site with warning | +| `infer-override`: override type inference | fatal warning | inferred type of member uses type of overridden member | Example 1: -{% highlight text %} +{% highlight scala %} def f = 1 + 2 {% endhighlight %} + +### Changes affecting binary encoding + +As of Scala 2.13.14, there are 3 changes in `-Xsource-features` that affect binary encoding of classfiles: + + 1. `case-apply-copy-access`: the constructor modifiers of case classes (`case class C private[p] (x: Int)`) are copied to the synthetic `apply` and `copy` methods. + 1. `case-companion-function`: the synthetic companion objects of case classes no longer extend `FunctionN`. + 1. `infer-override`: overriding methods without an explicit return type inherit the return type from the parent (instead of using the inferred type of the method body). + +For projects that are already cross-building between Scala 2 and 3 with existing releases for both, enabling these changes breaks binary compatibility (make sure to use [MiMa to detect such changes](https://github.com/lightbend/mima)). For example, if a library defines + +{% highlight scala %} +trait A { def f: Object } +class B extends A { def f = "hi" } +{% endhighlight %} + + - enabling `-Xsource-features:infer-override` breaks binary compatibility on Scala 2.13: existing releases have `A.f: String`, the new version will have `A.f: Object` + - adding an explicit result type `A.f: String` breaks binary compatibility on Scala 3: existing releases have `A.f: Object` + +It is possible to work around this using version-dependent source files, see [scala/scala-xml#675](https://github.com/scala/scala-xml/pull/675) as an example. + +Instead of implementing such workarounds, it might be easier not to enable changes affecting binary encoding (`-Xsource-features:v2.13.14,-case-apply-copy-access,-case-companion-function,-infer-override`).