Scala 3 迁移指南

Scala 2 带 -Xsource:3

语言

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 下相同,例如,对于没有显式类型的隐式定义

scala> object O { implicit val s = "" }
                               ^
       error: Implicit definition must have explicit type (inferred String) [quickfixable]

以下段落说明了 -Xsource:3-Xsource:3-cross 之间行为的变化。

影响二进制编码的更改

从 Scala 2.13.13 开始,-Xsource:3-cross 下有 3 项更改会影响类文件的二进制编码。对于所有这些更改,-Xsource:3 下都会发出致命警告。

  1. 用例类的构造函数修饰符(case class C private[p] (x: Int))被复制到合成 applycopy 方法。
  2. 用例类的合成伴生对象不再扩展 FunctionN
  3. 没有显式返回类型的重写方法从父级继承返回类型(而不是使用方法体的推断类型)。

对于已经使用现有版本在 Scala 2 和 Scala 3 之间进行交叉构建的项目,启用 -Xsource:3-cross 会破坏二进制兼容性。例如,如果某个库定义

trait A { def f: Object }
class B extends A { def f = "hi" }
  • 在 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

  def f =
    1
    + 2

此页面的贡献者