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 禁止將註解的類型直接或間接地用作其參數類型之一。 這可防止建立迴圈。 但是,您可以使用作為註解類型的
Array
或vararg
的參數類型。棄用週期:
- 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 將禁止在違反該類型參數宣告的變異數的位置中,在該類別的內部類別中使用具有
in
或out
變異數的外部類別的類型參數。棄用週期:
- 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
,即使此方法不適用於 KotlinEnum
類型。 Kotlin 1.9 將禁止使用此屬性,建議改為遷移到擴充功能屬性declaringJavaClass
。棄用週期:
- 1.7.0: 報告關於
declaringClass
屬性用法的警告(或在漸進模式下報告錯誤), 建議遷移到declaringJavaClass
擴充功能- 1.9.0: 將警告提升為錯誤, 可以使用
-XXLanguage:-ProhibitEnumDeclaringClass
暫時還原為 1.9 之前的行為- 2.0.0: 移除
declaringClass
合成屬性
棄用編譯器選項 -Xjvm-default 的啟用和相容性模式
元件: Kotlin/JVM
不相容變更類型: 原始碼
簡短摘要: Kotlin 1.9 禁止使用
-Xjvm-default
編譯器選項的enable
和compatibility
模式。棄用週期:
- 1.6.20: 在
-Xjvm-default
編譯器選項的enable
和compatibility
模式上引入警告- 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.dom
和kotlin.browser
套件的宣告已移至相應的kotlinx.*
套件,以準備從 stdlib 中提取它們。棄用週期:
- 1.4.0: 在
kotlinx.dom
和kotlinx.browser
套件中引入替換 API- 1.4.0: 棄用
kotlin.dom
和kotlin.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: 刪除屬性