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 語法

-Xsource:3 旗標會在 Scala 2 中啟用下列 Scala 3 語法

  • 匯入 p.*
  • 匯入 p.m 為 n
  • 匯入 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" }
  • 啟用 -Xsource:3-cross 會中斷 Scala 2.13 的二進制相容性:現有發布版本有 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
三引號字串和原始插補中的 Unicode 逸出字元 ("""\u0061""") 致命警告,已處理逸出字元 未處理逸出字元
前導中綴運算子會繼續前一行 1 致命警告,第二行是獨立的表達式 運算會繼續前一行
使用 StringContext 對字串插補器進行去糖 如果插補參照與 scala.StringContext 不同的範圍內的 StringContext,則會產生致命警告 去糖始終使用 scala.StringContext
在封裝前綴 p 中找到類型 p.A 的隱含值 致命警告 封裝前綴 p 不再是隱含搜尋範圍的一部分

範例 1

  def f =
    1
    + 2

此頁面的貢獻者