The Scala 2.13 compiler issues helpful migration warnings with the -Xsource:3
flag.
Before moving to the Scala 3 compiler, it’s recommended to enable this flag in Scala 2 and address the new warnings.
Usage information is shown with scalac -Xsource:help
.
Migration vs cross-building
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 asimport p.*
.- Adding the
-Xsource-features:<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.
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
.
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.
The @nowarn
annotation 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), 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
The -Xsource:3
flag enables the following Scala 3 syntaxes in Scala 2:
import p.*
import p.m as n
import p.{given, *}
case C(xs*)
as an alias forcase C(xs @ _*)
A & B
type intersection as an alias forA with B
- Selecting a method
x.f
performs an eta-expansion (x.f _
), even without an expected type
Scala 3 migration warnings in detail
Many Scala 3 migration warnings are easy to understand, e.g., for implicit definitions without an explicit type:
Enabling Scala 3 features with -Xsource-features
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
.
When enabling a feature, the corresponding migration warning is no longer issued.
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
).
-Xsource:3-cross
is a shorthand for -Xsource:3 -Xsource-features:_
.
Changes in language semantics
The following table shows backported Scala 3 language semantics available in -Xsource-features
/ -Xsource:3-cross
.
Feature flag | -Xsource:3 behavior |
-Xsource-features / -Xsource:3-cross behavior |
---|---|---|
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 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 |
double-definitions : definitions differing in empty parens 2 |
fatal warning | double definition error |
Example 1:
Example 2:
Changes affecting binary encoding
As of Scala 2.13.15, there are 3 changes in -Xsource-features
that affect binary encoding of classfiles:
case-apply-copy-access
: the constructor modifiers of case classes (case class C private[p] (x: Int)
) are copied to the syntheticapply
andcopy
methods.case-companion-function
: the synthetic companion objects of case classes no longer extendFunctionN
.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). For example, if a library defines
- enabling
-Xsource-features:infer-override
breaks binary compatibility on Scala 2.13: existing releases haveA.f: String
, the new version will haveA.f: Object
- adding an explicit result type
A.f: String
breaks binary compatibility on Scala 3: existing releases haveA.f: Object
It is possible to work around this using version-dependent source files, see scala/scala-xml#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
).