跳至主要内容

Kotlin 1.9 的相容性指南

保持語言現代化舒適的更新 是 Kotlin 語言設計的基本原則。 前者表示應移除阻礙語言發展的結構,而後者表示應事先充分溝通此移除,以使程式碼遷移盡可能順暢。

雖然大多數語言變更已透過其他管道(如更新變更日誌或編譯器警告)宣布,但本文總結了所有這些變更,為從 Kotlin 1.8 遷移到 Kotlin 1.9 提供了完整的參考。

基本術語

在本文中,我們介紹了幾種相容性:

  • 原始碼 (source):原始碼不相容的變更會阻止過去可以正常編譯(沒有錯誤或警告)的程式碼再也無法編譯
  • 二進位碼 (binary):如果交換兩個二進位碼產物不會導致載入或連結錯誤,則稱它們是二進位碼相容的
  • 行為 (behavioral):如果同一個程式在套用變更前後表現出不同的行為,則稱該變更是行為不相容的

請記住,這些定義僅適用於純 Kotlin。 從其他語言的角度來看,Kotlin 程式碼的相容性(例如,從 Java)不在本文的範圍內。

語言

移除語言版本 1.3

問題: KT-61111

元件: 核心語言

不相容變更類型: 原始碼

簡短摘要: Kotlin 1.9 引入語言版本 1.9 並移除對語言版本 1.3 的支援。

棄用週期:

  • 1.6.0: 報告警告
  • 1.9.0: 將警告提升為錯誤

禁止在超介面類型為函式常值時呼叫父類別建構函式 (super constructor)

問題: KT-46344

元件: 核心語言

不相容變更類型: 原始碼

簡短摘要: 如果介面繼承自函式常值類型,Kotlin 1.9 會禁止呼叫父類別建構函式,因為不存在此類建構函式。

棄用週期:

  • 1.7.0: 報告警告(或在漸進模式下報告錯誤)
  • 1.9.0: 將警告提升為錯誤

禁止註解參數類型中的迴圈

問題: KT-47932

元件: 核心語言

不相容變更類型: 原始碼

簡短摘要: Kotlin 1.9 禁止將註解的類型直接或間接地用作其參數類型之一。 這可防止建立迴圈。 但是,您可以使用作為註解類型的 Arrayvararg 的參數類型。

棄用週期:

  • 1.7.0: 報告關於註解參數類型中的迴圈的警告(或在漸進模式下報告錯誤)
  • 1.9.0: 將警告提升為錯誤,可以使用 -XXLanguage:-ProhibitCyclesInAnnotations 暫時還原為 1.9 之前的行為

禁止在沒有參數的函式類型上使用 @ExtensionFunctionType 註解

問題: KT-43527

元件: 核心語言

不相容變更類型: 原始碼

簡短摘要: Kotlin 1.9 禁止在沒有參數的函式類型上或在不是函式類型的類型上使用 @ExtensionFunctionType 註解。

棄用週期:

  • 1.7.0: 報告關於不是函式類型的類型上的註解的警告,報告關於函式類型的類型上的註解的錯誤
  • 1.9.0: 將函式類型的警告提升為錯誤

禁止在賦值時 Java 欄位類型不符

問題: KT-48994

元件: Kotlin/JVM

不相容變更類型: 原始碼

簡短摘要: 如果 Kotlin 1.9 檢測到賦值給 Java 欄位的值的類型與 Java 欄位的預測類型不符,則會報告編譯器錯誤。

棄用週期:

  • 1.6.0: 當預測的 Java 欄位類型與賦值的值類型不符時,報告警告(或在漸進模式下報告錯誤)
  • 1.9.0: 將警告提升為錯誤,可以使用 -XXLanguage:-RefineTypeCheckingOnAssignmentsToJavaFields 暫時還原為 1.9 之前的行為

在平台類型可空性斷言例外中沒有原始碼摘錄

問題: KT-57570

元件: Kotlin/JVM

不相容變更類型: 行為

簡短摘要: 在 Kotlin 1.9 中,表示式空值檢查的例外訊息不包括原始碼摘錄。 而是顯示方法或欄位的名稱。 如果表示式不是方法或欄位,則訊息中不會提供其他資訊。

棄用週期:

  • < 1.9.0: 表示式空值檢查產生的例外訊息包含原始碼摘錄
  • 1.9.0: 表示式空值檢查產生的例外訊息僅包含方法或欄位名稱,可以使用 -XXLanguage:-NoSourceCodeInNotNullAssertionExceptions 暫時還原為 1.9 之前的行為

禁止將父類別呼叫委託給抽象父類別成員

問題: KT-45508, KT-49017, KT-38078

元件: 核心語言

不相容變更類型: 原始碼

簡短摘要: 當明確或隱含的父類別呼叫委託給父類別的 抽象 成員時,即使超介面中有預設實作,Kotlin 也會報告編譯錯誤。

棄用週期:

  • 1.5.20: 引入在使用未覆寫所有抽象成員的非抽象類別時發出警告
  • 1.7.0: 如果父類別呼叫實際上存取了父類別中的抽象成員,則報告警告
  • 1.7.0: 如果啟用 -Xjvm-default=all-Xjvm-default=all-compatibility 相容模式,則在所有受影響的情況下報告錯誤; 在漸進模式下報告錯誤
  • 1.8.0: 在宣告具有父類別中未覆寫的抽象方法的具體類別的情況下,以及 Any 方法的父類別呼叫在父類別中被覆寫為抽象時,報告錯誤
  • 1.9.0: 在所有受影響的情況下報告錯誤,包括對父類別中抽象方法的明確父類別呼叫

棄用 when-with-subject 中令人困惑的語法

問題: KT-48385

元件: 核心語言

不相容變更類型: 原始碼

簡短摘要: Kotlin 1.6 棄用了 when 條件表示式中的幾個令人困惑的語法結構。

棄用週期:

  • 1.6.20: 在受影響的表示式上引入棄用警告
  • 1.8.0: 將此警告提升為錯誤, 可以使用 -XXLanguage:-ProhibitConfusingSyntaxInWhenBranches 暫時還原為 1.8 之前的行為
  • >= 2.1: 將一些已棄用的結構重新用於新的語言功能

防止不同數值類型之間的隱含強制轉換

問題: KT-48645

元件: Kotlin/JVM

不相容變更類型: 行為

簡短摘要: Kotlin 將避免自動將數值轉換為基本數值類型,在語義上只需要向下轉換到該類型。

棄用週期:

  • < 1.5.30: 所有受影響情況下的舊行為
  • 1.5.30: 修復產生的屬性委託存取器中的向下轉換行為, 可以使用 -Xuse-old-backend 暫時還原為 1.5.30 之前的修復行為
  • >= 2.0: 修復其他受影響情況下的向下轉換行為

禁止在泛型類型別名用法中違反上限(類型別名的類型參數的類型引數中使用的類型參數)

問題: KT-54066

元件: 核心語言

不相容變更類型: 原始碼

簡短摘要: 如果類型別名類型參數用作類型別名的類型引數的泛型類型引數,Kotlin 將禁止使用具有違反別名類型相應類型參數上限限制的類型引數的類型別名,例如 typealias Alias<T> = Base<List<T>>

棄用週期:

  • 1.8.0: 當泛型類型別名用法具有違反別名類型相應類型參數上限約束的類型引數時,報告警告
  • 2.0.0: 將警告提升為錯誤

在公有簽章中近似本機類型時保留可空性

問題: KT-53982

元件: 核心語言

不相容變更類型: 原始碼、二進位碼

簡短摘要: 當從沒有明確指定回傳類型的表示式主體函式回傳本機或匿名類型時,Kotlin 編譯器會使用該類型的已知超類型推斷(或近似)回傳類型。 在此過程中,編譯器可以推斷出實際上可以回傳空值的非可空類型。

棄用週期:

  • 1.8.0: 使用彈性超類型近似彈性類型
  • 1.8.0: 當推斷宣告具有應為可空的非可空類型時,報告警告,提示使用者明確指定類型
  • 2.0.0: 使用可空超類型近似可空類型, 可以使用 -XXLanguage:-KeepNullabilityWhenApproximatingLocalType 暫時還原為 2.0 之前的行為

不要透過覆寫傳播棄用

問題: KT-47902

元件: 核心語言

不相容變更類型: 原始碼

簡短摘要: Kotlin 1.9 將不再從父類別中已棄用的成員傳播棄用到子類別中的覆寫成員,從而提供了一種明確的機制來棄用父類別的成員,同時使其在子類別中保持非棄用狀態。

棄用週期:

  • 1.6.20: 報告警告,其中包含未來行為變更的訊息以及在已棄用成員的覆寫上抑制此警告或明確編寫 @Deprecated 註解的提示
  • 1.9.0: 停止將棄用狀態傳播到覆寫的成員。 此變更也會立即在漸進模式下生效

禁止在註解類別中的任何地方(除了其參數宣告)使用集合常值

問題: KT-39041

元件: 核心語言

不相容變更類型: 原始碼

簡短摘要: Kotlin 允許以受限制的方式使用集合常值 - 用於將陣列傳遞給註解類別的參數或為這些參數指定預設值。 然而,除此之外,Kotlin 允許在註解類別中的任何其他地方使用集合常值,例如,在其巢狀物件中。 Kotlin 1.9 將禁止在註解類別中的任何地方使用集合常值,除了其參數的預設值。

棄用週期:

  • 1.7.0: 報告關於註解類別中巢狀物件中的陣列常值的警告(或在漸進模式下報告錯誤)
  • 1.9.0: 將警告提升為錯誤

禁止在預設值表示式中轉發引用參數

問題: KT-25694

元件: 核心語言

不相容變更類型: 原始碼

簡短摘要: Kotlin 1.9 將禁止在其他參數的預設值表示式中轉發引用參數。 這確保了在預設值表示式中存取參數時,它已經有一個傳遞給函式或由其自己的預設值表示式初始化的值。

棄用週期:

  • 1.7.0: 當預設值在另一個在其之前的參數的預設值中引用時,報告警告(或在漸進模式下報告錯誤)
  • 1.9.0: 將警告提升為錯誤, 可以使用 -XXLanguage:-ProhibitIllegalValueParameterUsageInDefaultArguments 暫時還原為 1.9 之前的行為

禁止在內聯函式參數上進行擴充功能呼叫

問題: KT-52502

元件: 核心語言

不相容變更類型: 原始碼

簡短摘要: 雖然 Kotlin 允許將內聯函式參數作為接收器傳遞給另一個內聯函式,但在編譯此類程式碼時始終會導致編譯器例外。 Kotlin 1.9 將禁止此操作,因此報告錯誤而不是使編譯器崩潰。

棄用週期:

  • 1.7.20: 報告關於內聯函式參數上的內聯擴充功能呼叫的警告(或在漸進模式下報告錯誤)
  • 1.9.0: 將警告提升為錯誤

禁止使用匿名函式引數呼叫名為 suspend 的中綴函式

問題: KT-49264

元件: 核心語言

不相容變更類型: 原始碼

簡短摘要: Kotlin 1.9 將不再允許呼叫名為 suspend 的中綴函式,該函式具有作為匿名函式常值傳遞的函式類型的單一引數。

棄用週期:

  • 1.7.20: 報告關於具有匿名函式常值的 suspend 中綴呼叫的警告
  • 1.9.0: 將警告提升為錯誤, 可以使用 -XXLanguage:-ModifierNonBuiltinSuspendFunError 暫時還原為 1.9 之前的行為
  • TODO: 變更剖析器解譯 suspend fun 權杖序列的方式

禁止針對其變異數在內部類別中使用捕獲的類型參數

問題: KT-50947

元件: 核心語言

不相容變更類型: 原始碼

簡短摘要: Kotlin 1.9 將禁止在違反該類型參數宣告的變異數的位置中,在該類別的內部類別中使用具有 inout 變異數的外部類別的類型參數。

棄用週期:

  • 1.7.0: 當外部類別的類型參數使用位置違反該參數的變異數規則時,報告警告(或在漸進模式下報告錯誤)
  • 1.9.0: 將警告提升為錯誤, 可以使用 -XXLanguage:-ReportTypeVarianceConflictOnQualifierArguments 暫時還原為 1.9 之前的行為

禁止在複合賦值運算子中遞迴呼叫沒有明確回傳類型的函式

問題: KT-48546

元件: 核心語言

不相容變更類型: 原始碼

簡短摘要: Kotlin 1.9 將禁止在複合賦值運算子的引數中呼叫沒有明確指定回傳類型的函式,因為它目前在該函式主體內的其他表示式中執行此操作。

棄用週期:

  • 1.7.0: 當沒有明確指定回傳類型的函式在該函式主體中的複合賦值運算子引數中以遞迴方式呼叫時,報告警告(或在漸進模式下報告錯誤)
  • 1.9.0: 將警告提升為錯誤

禁止對具有可空邊界的 Kotlin 泛型參數進行具有預期的 @NotNull T 的不健全呼叫

問題: KT-36770

元件: Kotlin/JVM

不相容變更類型: 原始碼

簡短摘要: Kotlin 1.9 將禁止方法呼叫,其中將潛在可空泛型類型的值傳遞給 Java 方法的 @NotNull 註解參數。

棄用週期:

  • 1.5.20: 當在預期非可空類型的地方傳遞不受約束的泛型類型參數時,報告警告
  • 1.9.0: 報告類型不符錯誤而不是上述警告, 可以使用 -XXLanguage:-ProhibitUsingNullableTypeParameterAgainstNotNullAnnotated 暫時還原為 1.8 之前的行為

禁止從此列舉的條目初始化器存取列舉類別的伴生物件的成員

問題: KT-49110

元件: 核心語言

不相容變更類型: 原始碼

簡短摘要: Kotlin 1.9 將禁止從列舉條目初始化器存取列舉的伴生物件的所有類型。

棄用週期:

  • 1.6.20: 報告關於此類伴生成員存取的警告(或在漸進模式下報告錯誤)
  • 1.9.0: 將警告提升為錯誤, 可以使用 -XXLanguage:-ProhibitAccessToEnumCompanionMembersInEnumConstructorCall 暫時還原為 1.8 之前的行為

棄用並移除 Enum.declaringClass 合成屬性

問題: KT-49653

元件: Kotlin/JVM

不相容變更類型: 原始碼

簡短摘要: Kotlin 允許在從基礎 Java 類別 java.lang.Enum 的方法 getDeclaringClass() 產生的 Enum 值上使用合成屬性 declaringClass,即使此方法不適用於 Kotlin Enum 類型。 Kotlin 1.9 將禁止使用此屬性,建議改為遷移到擴充功能屬性 declaringJavaClass

棄用週期:

  • 1.7.0: 報告關於 declaringClass 屬性用法的警告(或在漸進模式下報告錯誤), 建議遷移到 declaringJavaClass 擴充功能
  • 1.9.0: 將警告提升為錯誤, 可以使用 -XXLanguage:-ProhibitEnumDeclaringClass 暫時還原為 1.9 之前的行為
  • 2.0.0: 移除 declaringClass 合成屬性

棄用編譯器選項 -Xjvm-default 的啟用和相容性模式

問題: KT-46329, KT-54746

元件: Kotlin/JVM

不相容變更類型: 原始碼

簡短摘要: Kotlin 1.9 禁止使用 -Xjvm-default 編譯器選項的 enablecompatibility 模式。

棄用週期:

  • 1.6.20: 在 -Xjvm-default 編譯器選項的 enablecompatibility 模式上引入警告
  • 1.9.0: 將此警告提升為錯誤

禁止在建構器推論內容中將類型變數隱含地推斷到上限

問題: KT-47986

元件: 核心語言

不相容變更類型: 原始碼

簡短摘要: Kotlin 2.0 將禁止在缺少建構器推論 lambda 函式範圍內的任何使用位置類型資訊的情況下,將類型變數推斷到相應類型參數的上限,就像它目前在其他內容中執行的一樣。

棄用週期:

  • 1.7.20: 當在缺少使用位置類型資訊的情況下,將類型參數推斷到宣告的上限時,報告警告(或在漸進模式下報告錯誤)
  • 2.0.0: 將警告提升為錯誤

標準函式庫

當 Range/Progression 開始實作 Collection 時,警告可能的過載解析變更

問題: KT-49276

元件: 核心語言 / kotlin-stdlib

不相容變更類型: 原始碼

簡短摘要: 計劃在 Kotlin 1.9 中在標準級數和從其繼承的具體範圍中實作 Collection 介面。 如果某個方法有兩個過載,一個接受元素,另一個接受集合,則這可能會使過載解析中選擇不同的過載。 當使用範圍或級數引數呼叫此類過載方法時,Kotlin 將透過報告警告或錯誤來使此情況可見。

棄用週期:

  • 1.6.20: 當使用標準級數或其範圍繼承者作為引數呼叫過載方法時,報告警告 如果此級數/範圍實作 Collection 介面,則在未來會導致在此呼叫中選擇另一個過載
  • 1.8.0: 將此警告提升為錯誤
  • 2.1.0: 停止報告錯誤,在級數中實作 Collection 介面,從而變更受影響情況下的過載解析結果

將宣告從 kotlin.dom 和 kotlin.browser 套件遷移到 kotlinx.*

問題: KT-39330

元件: kotlin-stdlib (JS)

不相容變更類型: 原始碼

簡短摘要: 來自 kotlin.domkotlin.browser 套件的宣告已移至相應的 kotlinx.* 套件,以準備從 stdlib 中提取它們。

棄用週期:

  • 1.4.0: 在 kotlinx.domkotlinx.browser 套件中引入替換 API
  • 1.4.0: 棄用 kotlin.domkotlin.browser 套件中的 API,並建議使用上面的新 API 作為替換
  • 1.6.0: 將棄用層級提升為錯誤
  • 1.8.20: 從 JS-IR 目標的 stdlib 中移除已棄用的函式
  • >= 2.0: 將 kotlinx.* 套件中的 API 移至單獨的函式庫

棄用一些僅限 JS 的 API

問題: KT-48587

元件: kotlin-stdlib (JS)

不相容變更類型: 原始碼

簡短摘要: stdlib 中的許多僅限 JS 的函式已被棄用以供移除。 它們包括:String.concat(String)String.match(regex: String)String.matches(regex: String) 和在陣列上採用比較函式的 sort 函式,例如 Array<out T>.sort(comparison: (a: T, b: T) -> Int)

棄用週期:

  • 1.6.0: 使用警告棄用受影響的函式
  • 1.9.0: 將棄用層級提升為錯誤
  • >=2.0: 從公有 API 中移除已棄用的函式

工具

從 Gradle 設定中移除 enableEndorsedLibs 標誌

問題: KT-54098

元件: Gradle

不相容變更類型: 原始碼

簡短摘要: Gradle 設定中不再支援 enableEndorsedLibs 標誌。

棄用週期:

  • < 1.9.0: Gradle 設定中支援 enableEndorsedLibs 標誌
  • 1.9.0: 支援 Gradle 設定中的 enableEndorsedLibs 標誌

移除 Gradle 慣例

問題: KT-52976

元件: Gradle

不相容變更類型: 原始碼

簡短摘要: Gradle 慣例已在 Gradle 7.1 中棄用,並已在 Gradle 8 中移除。

棄用週期:

  • 1.7.20: Gradle 慣例已棄用
  • 1.9.0: Gradle 慣例已移除

移除 KotlinCompile 任務的 classpath 屬性

問題: KT-53748

元件: Gradle

不相容變更類型: 原始碼

簡短摘要: 移除了 KotlinCompile 任務的 classpath 屬性。

棄用週期:

  • 1.7.0: classpath 屬性已棄用
  • 1.8.0: 將棄用層級提升為錯誤
  • 1.9.0: 從公有 API 中移除已棄用的函式

棄用 kotlin.internal.single.build.metrics.file 屬性

問題: KT-53357

元件: Gradle

不相容變更類型: 原始碼

簡短摘要: 棄用用於定義建構報告單一檔案的 kotlin.internal.single.build.metrics.file 屬性。 請改用具有 kotlin.build.report.output=single_file 的屬性 kotlin.build.report.single_file

棄用週期:

  • 1.8.0: 將棄用層級提升為警告
  • >= 1.9: 刪除屬性