Scala 3 迁移指南

类路径级别

语言

在你的代码中,你可以使用公共类型和术语,并调用在不同模块或库中定义的公共方法。只要类型检查器(这是验证代码语义一致性的编译器阶段)能够从包含它们的类文件中读取这些类型、术语和方法的签名,它就能很好地工作。

在 Scala 2 中,签名存储在一种称为 Pickle 格式的专用格式中。在 Scala 3 中,情况略有不同,因为它依赖于 TASTy 格式,而这不仅仅是一种签名布局。但是,为了从 Scala 2.13 迁移到 Scala 3,只有签名是有用的。

Scala 3 Unpickler

第一个好消息是 Scala 3 编译器能够读取 Scala 2.13 Pickle 格式,因此它可以对依赖于使用 Scala 2.13 编译的模块或库的代码进行类型检查。

Scala 3 解释器在社区构建中已经经过多年广泛测试。使用它是安全的。

Scala 3 模块可以依赖 Scala 2.13 工件

Scala 3 module depending on a Scala 2.13 artifact

作为 sbt 构建,它看起来像这样

// build.sbt (sbt 1.5 or higher)
lazy val foo = project.in(file("foo"))
  .settings(scalaVersion := "3.3.1")
  .dependsOn(bar)

lazy val bar = project.in(file("bar"))
  .settings(scalaVersion := "2.13.11")

或者,如果 bar 是已发布的 Scala 2.13 库,我们可以有

lazy val foo = project.in(file("foo"))
  .settings(
    scalaVersion := "3.3.1",
    libraryDependencies += ("org.bar" %% "bar" % "1.0.0").cross(CrossVersion.for3Use2_13)
  )

我们在 sbt 中使用 CrossVersion.for3Use2_13 来解析 bar_2.13 而不是 bar_3

标准库

一个值得注意的例子是 Scala 2.13 库。我们确实已经决定 Scala 2.13 库是 Scala 3 的官方标准库。

请注意,标准库是由构建工具自动提供的,您不需要手动配置它。

Scala 2.13 TASTy 读取器

第二个好消息是 Scala 2.13 可以使用 -Ytasty-reader 来使用 Scala 3 库。

支持的功能

TASTy 读取器支持所有传统语言功能以及以下 Scala 3 功能

它部分支持

它不支持更高级的功能

Scala 2.13 模块可以依赖 Scala 3 工件

通过使用 -Ytasty-reader 启用 TASTy 读取器,Scala 2.13 模块可以依赖 Scala 3 工件。

Scala 2 module depending on a Scala 3 artifact

作为 sbt 构建,它看起来像这样

// build.sbt (sbt 1.5 or higher)
lazy val foo = project.in.file("foo")
  .settings(
    scalaVersion := "2.13.11",
    scalacOptions += "-Ytasty-reader"
  )
  .dependsOn(bar)

lazy val bar = project.in(file("bar"))
  .settings(scalaVersion := "3.3.1")

或者,如果 bar 是已发布的 Scala 3 库

lazy val foo = project.in.file("foo")
  .settings(
    scalaVersion := "2.13.11",
    scalacOptions += "-Ytasty-reader",
    libraryDependencies += ("org.bar" %% "bar" % "1.0.0").cross(CrossVersion.for2_13Use3)
  )

类似于 CrossVersion.for2_13Use3,我们在 sbt 中使用 CrossVersion.for3Use2_13 来解析 bar_3 而不是 bar_2.13

互操作性概述

简而言之,我们具有向后和向前兼容性,因此迁移可以逐步进行

即使其库依赖项尚未移植(宏库除外),您也可以一次移植一个模块的大型 Scala 应用程序。

在过渡期间,您可以在两个 2.13 模块之间插入一个 Scala 3 模块。

Sandwich pattern

只要所有库都解析为单个二进制版本,则允许这样做:您可以在同一类路径中拥有 lib-foo_3lib-bar_2.13,但不能拥有 lib-foo_3lib-foo_2.13

中间带有 2.13 模块的倒置模式也是可能的。

库维护者免责声明

除非您确切地知道自己在做什么,否则不建议发布依赖于 Scala 2.13 库(不包括 scala-library)或反之亦然的 Scala 3 库。原因是为了防止库用户最终在类路径中拥有同一 foo 库的两个冲突版本 foo_2.13foo_3,在某些情况下,此问题无法解决。

此页面的贡献者