Scala 2.13 编译器使用 -Xsource:3
标志发出有用的迁移警告。
在迁移到 Scala 3 编译器之前,建议在 Scala 2 中启用此标志并解决新警告。
还有一个变体 -Xsource:3-cross
;见下文。注意:在 Scala 2.13.13 中启用 -Xsource:3-cross
会破坏二进制兼容性,请关注 scala/bug#12961 了解详情。
此页面解释了标志背后的详细信息。概述使用 scalac -Xsource:help
显示。
迁移与交叉构建
使用 Scala 2.13.13 及更高版本,-Xsource:3
标志有两种变体
Xsource:3
启用与将代码库迁移到 Scala 3 相关的警告。除了新警告之外,此标志还启用某些良性的 Scala 3 语法,例如import p.*
。Xsource:3-cross
对于在 Scala 2 和 3 之间长期交叉构建的项目很有用。对于使用-Xsource:3
触发警告的某些语言结构,行为会更改以匹配 Scala 3。
本页下面列出了有关各个警告的详细信息。
致命警告和快速修复
默认情况下,Scala 2.13 发出的 Scala 3 迁移警告是致命的,即它们被报告为错误。可以使用 -Wconf
更改此设置,例如 -Wconf:cat=scala3-migration:w
将它们更改为报告为警告。或者,-Xmigration
具有相同的效果。
@nowarn
注释 可用于抑制各个警告,这在启用了致命警告时也能起作用。
Scala 2.13 编译器为许多 Scala 3 迁移警告实现了快速修复。快速修复显示在基于 Metals 的 IDE 中(尚未在 IntelliJ 中),它们可以使用 -quickfix
标志直接应用于源代码,例如 -quickfix:cat=scala3-migration
。另请参阅 scalac -quickfix:help
。
启用的 Scala 3 语法
在 Scala 2 中,-Xsource:3
标志启用以下 Scala 3 语法
import p.*
import p.m as n
import p.{given, *}
case C(xs*)
作为case C(xs @ _*)
的别名A & B
类型交叉作为A with B
的别名- 选择方法
x.f
执行 eta 展开(x.f _
),即使没有预期类型
Scala 3 迁移警告的详细信息
许多 Scala 3 迁移警告很容易理解,并且在 -Xsource:3
和 -Xsource:3-cross
下相同,例如,对于没有显式类型的隐式定义
以下段落说明了 -Xsource:3
和 -Xsource:3-cross
之间行为的变化。
影响二进制编码的更改
从 Scala 2.13.13 开始,-Xsource:3-cross
下有 3 项更改会影响类文件的二进制编码。对于所有这些更改,-Xsource:3
下都会发出致命警告。
- 用例类的构造函数修饰符(
case class C private[p] (x: Int)
)被复制到合成apply
和copy
方法。 - 用例类的合成伴生对象不再扩展
FunctionN
。 - 没有显式返回类型的重写方法从父级继承返回类型(而不是使用方法体的推断类型)。
对于已经使用现有版本在 Scala 2 和 Scala 3 之间进行交叉构建的项目,启用 -Xsource:3-cross
会破坏二进制兼容性。例如,如果某个库定义
- 在 Scala 2.13 上启用
-Xsource:3-cross
会破坏二进制兼容性:现有版本有A.f: String
,新版本会有A.f: Object
- 添加显式结果类型
A.f: String
会破坏 Scala 3 上的二进制兼容性:现有版本有A.f: Object
可以使用版本相关的源文件来解决此问题,请参阅 scala/scala-xml#675 作为示例。
解决案例伴随 FunctionN
父更改目前很困难(Scala 2.13.13),正在 scala/bug#12961 讨论解决方案。
语言语义的更改
下表显示了 -Xsource:3-cross
从 Scala 3 采用语言特性语义的情况。
特性 | -Xsource:3 |
-Xsource:3-cross |
---|---|---|
(x: Any) + "" 已弃用 |
弃用警告 | 不编译,隐式 any2stringadd 无法推断 |
三重引号字符串和原始插值("""\u0061""" )中的 Unicode 转义 |
致命警告,已处理转义 | 未处理转义 |
前导中缀运算符继续上一行1 | 致命警告,第二行是一个单独的表达式 | 操作继续上一行 |
使用 StringContext 对字符串插值进行去糖 |
如果插值引用与 scala.StringContext 不同的作用域中的 StringContext ,则发出致命警告 |
去糖始终使用 scala.StringContext |
在包前缀 p 中找到类型 p.A 的隐式 |
致命警告 | 包前缀 p 不再是隐式搜索范围的一部分 |
示例 1