Skip to content

Commit e93da37

Browse files
authoredMay 1, 2024
Merge pull request #2994 from som-snytt/tweak/xsource
Thoroughly rework instructions for `-Xsource:3` in Scala 2.13.14
2 parents 609e473 + 27b65ec commit e93da37

File tree

1 file changed

+73
-40
lines changed

1 file changed

+73
-40
lines changed
 

‎_overviews/scala3-migration/tooling-scala2-xsource3.md

+73-40
Original file line numberDiff line numberDiff line change
@@ -11,32 +11,31 @@ The Scala 2.13 compiler issues helpful migration warnings with the `-Xsource:3`
1111

1212
Before moving to the Scala 3 compiler, it's recommended to enable this flag in Scala 2 and address the new warnings.
1313

14-
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.**
15-
16-
This page explains the details behind the flags. An overview is shown using `scalac -Xsource:help`.
14+
Usage information is shown with `scalac -Xsource:help`.
1715

1816
## Migration vs cross-building
1917

20-
With Scala 2.13.13 and newer, the `-Xsource:3` flag comes in two variants:
18+
With Scala 2.13.14 and newer, the `-Xsource:3` flag supports two scenarios:
2119

2220
- `Xsource:3` enables warnings relevant for migrating a codebase to Scala 3.
2321
In addition to new warnings, the flag enables certain benign Scala 3 syntaxes such as `import p.*`.
24-
- `Xsource:3-cross` is useful for projects that cross-build between Scala 2 and 3 for a longer period of time.
25-
For certain language constructs that trigger a warning with `-Xsource:3`, the behavior changes to match Scala 3.
26-
27-
Details about individual warnings are listed below on this page.
22+
- Adding the `-Xsource-features:<features>` flag is useful to reduce the maintenance burden of projects that cross-build between Scala 2 and 3.
23+
Certain language constructs have been backported from Scala 3 in order to improve compatibility.
24+
Instead of warning about a behavior change in Scala 3, it adopts the new behavior.
2825

29-
## Fatal warnings and quick fixes
26+
## Warnings as errors, and quick fixes
3027

31-
By default, Scala 3 migration warnings emitted by Scala 2.13 are fatal, i.e., they are reported as errors.
32-
This can be changed using `-Wconf`, for example `-Wconf:cat=scala3-migration:w` changes them to be reported as warnings.
33-
Alternatively, `-Xmigration` has the same effect.
28+
By default, Scala 3 migration warnings emitted by Scala 2.13 are reported as errors, using the default configuration, `-Wconf:cat=scala3-migration:e`.
29+
This ensures that migration messaging is more visible.
30+
Diagnostics can be emitted as warnings by specifying `-Wconf:cat=scala3-migration:w`.
31+
Typically, emitting warnings instead of errors will cause more diagnostics to be reported.
3432

35-
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.
33+
The [`@nowarn` annotation](https://www.scala-lang.org/api/current/scala/annotation/nowarn.html) can be used in program sources to suppress individual warnings.
34+
Diagnostics are suppressed before they are promoted to errors, so that `@nowarn` takes precedence over `-Wconf` and `-Werror`.
3635

3736
The Scala 2.13 compiler implements quick fixes for many Scala 3 migration warnings.
38-
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`.
39-
See also `scalac -quickfix:help`.
37+
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`.
38+
See also `scala -quickfix:help`.
4039

4140
## Enabled Scala 3 syntax
4241

@@ -51,54 +50,88 @@ The `-Xsource:3` flag enables the following Scala 3 syntaxes in Scala 2:
5150

5251
## Scala 3 migration warnings in detail
5352

54-
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:
53+
Many Scala 3 migration warnings are easy to understand, e.g., for implicit definitions without an explicit type:
5554

56-
{% highlight text %}
55+
{% highlight scala %}
5756
scala> object O { implicit val s = "" }
5857
^
5958
error: Implicit definition must have explicit type (inferred String) [quickfixable]
6059
{% endhighlight %}
6160

62-
The next paragraphs explain where the behavior changes between `-Xsource:3` and `-Xsource:3-cross`.
61+
## Enabling Scala 3 features with `-Xsource-features`
6362

64-
### Changes affecting binary encoding
63+
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`.
6564

66-
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`.
65+
When enabling a feature, the corresponding migration warning is no longer issued.
6766

68-
1. The constructor modifiers of case classes (`case class C private[p] (x: Int)`) are copied to the synthetic `apply` and `copy` methods.
69-
1. The synthetic companion objects of case classes no longer extend `FunctionN`.
70-
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).
67+
{% highlight scala %}
68+
scala> raw"\u0061"
69+
^
70+
warning: Unicode escapes in raw interpolations are deprecated; use literal characters instead
71+
val res0: String = a
7172

72-
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
73+
scala> :setting -Xsource:3
7374

74-
{% highlight scala %}
75-
trait A { def f: Object }
76-
class B extends A { def f = "hi" }
77-
{% endhighlight %}
75+
scala> raw"\u0061"
76+
^
77+
error: Unicode escapes in raw interpolations are ignored in Scala 3 (or with -Xsource-features:unicode-escapes-raw); use literal characters instead
78+
Scala 3 migration messages are errors under -Xsource:3. Use -Wconf / @nowarn to filter them or add -Xmigration to demote them to warnings.
79+
Applicable -Wconf / @nowarn filters for this fatal warning: msg=<part of the message>, cat=scala3-migration, site=res1
7880

79-
- 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`
80-
- adding an explicit result type `A.f: String` breaks binary compatibility on Scala 3: existing releases have `A.f: Object`
81+
scala> :setting -Xsource-features:unicode-escapes-raw
8182

82-
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.
83+
scala> raw"\u0061"
84+
val res1: String = \u0061
85+
{% endhighlight %}
8386

84-
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).
87+
For every such language feature, a migration warning is issued under plain `-Xsource:3`.
88+
Enabling the feature silences the warning and adopts the changed behavior.
89+
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`).
90+
91+
`-Xsource:3-cross` is a shorthand for `-Xsource:3 -Xsource-features:_`.
8592

8693
### Changes in language semantics
8794

88-
The following table shows cases where `-Xsource:3-cross` adopts language feature semantics from Scala 3.
95+
The following table shows backported Scala 3 language semantics available in `-Xsource-features` / `-Xsource:3-cross`.
8996

90-
| Feature | `-Xsource:3` | `-Xsource:3-cross` |
97+
| Feature flag | `-Xsource:3` behavior | `-Xsource-features` / `-Xsource:3-cross` behavior |
9198
|--- |--- |--- |
92-
| `(x: Any) + ""` is deprecated | deprecation warning | does not compile, implicit `any2stringadd` is not inferred |
93-
| Unicode escapes in triple-quoted strings and raw interpolations (`"""\u0061"""`) | fatal warning, escape is processed | escape is not processed |
94-
| Leading infix operators continue the previous line <sup>1</sup> | fatal warning, second line is a separate expression | operation continues the previous line |
95-
| 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` |
96-
| 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 |
99+
| `any2stringadd`: `(x: Any) + ""` is deprecated | deprecation warning | does not compile, implicit `any2stringadd` is not inferred |
100+
| `unicode-escapes-raw`: unicode escapes in triple-quoted strings and raw interpolations (`"""\u0061"""`) | fatal warning, escape is processed | escape is not processed |
101+
| `leading-infix`: leading infix operators continue the previous line <sup>1</sup> | fatal warning, second line is a separate expression | operation continues the previous line |
102+
| `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` |
103+
| `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 |
104+
| `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 |
105+
| `case-apply-copy-access`: modifiers of synthetic methods | fatal warning | constructor modifiers are used for apply / copy methods of case classes |
106+
| `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 |
107+
| `infer-override`: override type inference | fatal warning | inferred type of member uses type of overridden member |
97108

98109
Example 1:
99110

100-
{% highlight text %}
111+
{% highlight scala %}
101112
def f =
102113
1
103114
+ 2
104115
{% endhighlight %}
116+
117+
### Changes affecting binary encoding
118+
119+
As of Scala 2.13.14, there are 3 changes in `-Xsource-features` that affect binary encoding of classfiles:
120+
121+
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.
122+
1. `case-companion-function`: the synthetic companion objects of case classes no longer extend `FunctionN`.
123+
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).
124+
125+
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
126+
127+
{% highlight scala %}
128+
trait A { def f: Object }
129+
class B extends A { def f = "hi" }
130+
{% endhighlight %}
131+
132+
- 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`
133+
- adding an explicit result type `A.f: String` breaks binary compatibility on Scala 3: existing releases have `A.f: Object`
134+
135+
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.
136+
137+
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`).

0 commit comments

Comments
 (0)
Failed to load comments.