Scala 2 with -Xsource:3
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 withscalac -Xsource:help.
Migration vs cross-building
With Scala 2.13.14 and newer, the-Xsource:3 flag supports two scenarios:
Xsource:3enables 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 alsoscala -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 nimport p.{given, *}case C(xs*)as an alias forcase C(xs @ _*)A & Btype intersection as an alias forA with B
Scala 3 migration warnings in detail
Many Scala 3 migration warnings are easy to understand, e.g., for implicit definitions without an explicit type:
scala>objectO{implicitvals=""}^error:Implicitdefinitionmusthaveexplicittype(inferredString)[quickfixable]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.
scala>raw"\u0061"^warning:Unicodeescapesinrawinterpolationsaredeprecated;useliteralcharactersinsteadvalres0:String=ascala>:setting-Xsource:3scala>raw"\u0061"^error:UnicodeescapesinrawinterpolationsareignoredinScala3(orwith-Xsource-features:unicode-escapes-raw);useliteralcharactersinsteadScala3migrationmessagesareerrorsunder-Xsource:3.Use-Wconf/@nowarntofilterthemoradd-Xmigrationtodemotethemtowarnings.Applicable-Wconf/@nowarnfiltersforthisfatalwarning:msg=<partofthemessage>,cat=scala3-migration,site=res1scala>:setting-Xsource-features:unicode-escapes-rawscala>raw"\u0061"valres1:String=\u0061For 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, implicitany2stringadd 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 line1 | fatal warning, second line is a separate expression | operation continues the previous line |
string-context-scope: desugaring of string interpolators usingStringContext | fatal warning if the interpolation references aStringContext in scope different fromscala.StringContext | desugaring always usesscala.StringContext |
package-prefix-implicits: an implicit for typep.A is found in the package prefixp | fatal warning | the package prefixp is no longer part of the implicit search scope |
implicit-resolution: specificity during implicit search | fatal warning | use Scala-3-styledownwards 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 parens2 | fatal warning | double definition error |
eta-expand-always:x.f eta-expands (x.f _) even without an expected type | compilation error (“missing argument list”) | x.f expands to a function value |
Example 1:
deff=1+2Example 2:
classC(x:Int){defx():Int=x// allowed in Scala 2, double definition error in Scala 3}Changes affecting binary encoding
As of Scala 2.13.18, 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 syntheticapplyandcopymethods.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 useMiMa to detect such changes). For example, if a library defines
traitA{deff:Object}classBextendsA{deff="hi"}- enabling
-Xsource-features:infer-overridebreaks 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: Stringbreaks binary compatibility on Scala 3: existing releases haveA.f: Object
It is possible to work around this using version-dependent source files, seescala/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).
Contributors to this page:
Contents
- Compatibility Reference
- Source Level
- Classpath Level
- Runtime
- Metaprogramming
- Tour of the Migration Tools
- Scala 2 with -Xsource:3
- Scala 3 Migration Mode
- Migration Tutorial
- Prerequisites
- Porting an sbt Project (using sbt-scala3-migrate)
- Porting an sbt Project (by hand)
- Cross-Building a Macro Library
- Mixing Scala 2.13 and Scala 3 Macros
- Scala 3 Syntax Rewriting
- Incompatibility Table
- Syntactic Changes
- Dropped Features
- Contextual Abstractions
- Other Changed Features
- Type Checker
- Type Inference
- Compiler Options
- Compiler Options Lookup Table
- New Compiler Options
- Scaladoc settings compatibility between Scala2 and Scala3
- Compiler Plugins
- Kind Projector Migration
- External Resources