13.6.2.3 Kotlin 2.2.x 兼容性指南

原文链接: https://kotlinlang.org/docs/compatibility-guide-22.html

13.6.2.3 Kotlin 2.2.x 兼容性指南

保持语言的现代性 和 舒适的更新 是 Kotlin 语言设计中的基本原则。前者指出,阻碍语言演进的构造应该被移除;后者指出,这种移除应事先充分沟通,以便代码迁移尽可能顺畅。

虽然大多数语言变更已经通过其他渠道公布过(例如更新日志或编译器警告),但本文汇总了所有这些变更,为从 Kotlin 2.1 迁移到 Kotlin 2.2 提供完整参考。

基本术语

本文介绍了以下几种兼容性:

  • 源码级:源码不兼容的变更会让原本能正常编译(无错误或警告)的代码不再能编译
  • 二进制级:如果互换两个二进制产物不会导致加载或链接错误,则称它们是二进制兼容的
  • 行为级:如果同一个程序在应用变更前后的行为不同,则该变更属于行为不兼容

请记住,这些定义仅针对纯 Kotlin。从其他语言(例如 Java)的视角来看 Kotlin 代码的兼容性不在本文讨论范围内。

语言

放弃对 1.6 和 1.7 的 -language-version 支持

Issue:KT-71793 组件:编译器 不兼容变更类型:源码级 简要说明:从 Kotlin 2.2 开始,编译器不再支持 -language-version=1.6 或 -language-version=1.7。这意味着不再支持早于 1.8 的语言特性集。不过,语言本身仍与 Kotlin 1.0 完全向后兼容。弃用周期:- 2.1.0:使用 -language-version 指定 1.6 和 1.7 版本时报告警告 - 2.2.0:使用 -language-version 指定 1.8 和 1.9 版本时报告警告;把 1.6 和 1.7 的警告提升为错误

默认为带注解的 lambda 启用 invokedynamic

Issue:KTLC-278 组件:核心语言 不兼容变更类型:行为级 简要说明:带注解的 lambda 现在默认通过 LambdaMetafactory 使用 invokedynamic,其行为与 Java lambda 保持一致。这会影响依赖从生成的 lambda 类中获取注解的反射代码。要回退到旧行为,请使用 -Xindy-allow-annotated-lambdas=false 编译器选项。弃用周期:- 2.2.0:默认为带注解的 lambda 启用 invokedynamic

在 K2 中禁止对展开类型带型变的类型别名进行构造器调用和继承

Issue:KTLC-4 组件:核心语言 不兼容变更类型:源码级 简要说明:对于展开为使用 out 等型变修饰符的类型的类型别名,K2 编译器不再支持对其进行构造器调用和继承。这解决了这样的不一致:直接使用原类型不被允许,而通过类型别名进行同样的使用却被允许。要迁移,请在需要的地方显式使用原类型。弃用周期:- 2.0.0:对展开为带型变修饰符类型的类型别名上的构造器调用或父类型用法报告警告 - 2.2.0:把该警告提升为错误

禁止从 Kotlin getter 生成合成属性

Issue:KTLC-272 组件:核心语言 不兼容变更类型:源码级 简要说明:对于在 Kotlin 中定义的 getter,不再允许生成合成属性。这会影响 Java 类继承 Kotlin 类的情况,以及处理 java.util.LinkedHashSet 等映射类型的情况。要迁移,请把属性访问替换为直接调用相应的 getter 函数。弃用周期:- 2.0.0:对访问由 Kotlin getter 生成的合成属性报告警告 - 2.2.0:把该警告提升为错误

修改 JVM 上接口函数默认方法的生成方式

Issue:KTLC-269 组件:核心语言 不兼容变更类型:二进制级 简要说明:接口中声明的函数现在会被编译为 JVM 默认方法,除非另有配置。当无关的父类型定义了冲突的实现时,这可能导致 Java 代码出现编译错误。该行为由稳定的 -jvm-default 编译器选项控制,它取代了现已弃用的 -Xjvm-default 选项。要恢复之前的行为(仅在 DefaultImpls 类和子类中生成默认实现),请使用 -jvm-default=disable。弃用周期:- 2.2.0:-jvm-default 编译器选项默认设置为 enable

禁止在注解属性上使用以字段为目标的注解

Issue:KTLC-7 组件:核心语言 不兼容变更类型:源码级 简要说明:注解属性上不再允许使用以字段为目标的注解。虽然这些注解没有任何可观察的效果,但该变更可能影响依赖它们的自定义 IR 插件。要迁移,请从该属性上移除以字段为目标的注解。弃用周期:- 2.1.0:注解属性上的 @JvmField 注解被弃用并给出警告 - 2.1.20:对注解属性上的所有以字段为目标的注解报告警告 - 2.2.0:把该警告提升为错误

禁止在类型别名中使用 reified 类型参数

Issue:KTLC-5 组件:核心语言 不兼容变更类型:源码级 简要说明:类型别名中的类型参数不再允许使用 reified 修饰符。reified 类型参数只在内联函数中有效,因此在类型别名中使用它们没有效果。要迁移,请从 typealias 声明中移除 reified 修饰符。弃用周期:- 2.1.0:对类型别名中的 reified 类型参数报告警告 - 2.2.0:把该警告提升为错误

修正内联值类在 Number 和 Comparable 上的类型检查

Issue:KTLC-21 组件:Kotlin/JVM 不兼容变更类型:行为级 简要说明:在 is 和 as 检查中,内联值类不再被视为 java.lang.Number 或 java.lang.Comparable 的实现者。当应用于装箱的内联类时,这些检查此前会返回不正确的结果。该优化现在只适用于原始类型及其包装类。弃用周期:- 2.2.0:启用新行为

禁止来自间接依赖的不可访问泛型类型

Issue:KTLC-3 组件:核心语言 不兼容变更类型:源码级 简要说明:当使用编译器不可见的间接依赖中的类型时,K2 编译器现在会报告错误。这会影响 lambda 参数或泛型类型实参等情况,即由于缺少依赖而无法获得所引用的类型。弃用周期:- 2.0.0:对 lambda 中不可访问的泛型类型以及某些不可访问泛型类型实参的用法报告错误;对 lambda 中不可访问的非泛型类型以及表达式类型和父类型中不可访问的类型实参报告警告 - 2.1.0:把 lambda 中不可访问非泛型类型的警告提升为错误 - 2.2.0:把表达式类型中不可访问类型实参的警告提升为错误

对类型参数边界实施可见性检查

Issue:KTLC-274 组件:核心语言 不兼容变更类型:源码级 简要说明:函数和属性不再能使用可见性比该声明本身更严格的类型参数边界。这防止了间接触及不可访问的类型;此前这类代码能正常编译,但在某些情况下会导致运行时失败或 IR 校验错误。弃用周期:- 2.1.0:当类型参数的边界在声明的可见性作用域内不可见时报告警告 - 2.2.0:把该警告提升为错误

在非私有内联函数中暴露私有类型时报告错误

Issue:KT-70916 组件:核心语言 不兼容变更类型:源码级 简要说明:不再允许从非私有内联函数访问私有类型、函数或属性。要迁移,可以避免引用私有实体、把该函数改为私有,或者移除 inline 修饰符。请注意,移除 inline 会破坏二进制兼容性。弃用周期:- 2.2.0:从非私有内联函数访问私有类型或成员时报告错误

禁止在作为参数默认值的 lambda 中使用非局部 return

Issue:KTLC-286 组件:核心语言 不兼容变更类型:源码级 简要说明:在作为参数默认值使用的 lambda 中,不再允许使用非局部 return 语句。这种写法以前能够编译,但会导致运行时崩溃。要迁移,请改写该 lambda 以避免非局部 return,或把逻辑移到默认值之外。弃用周期:- 2.2.0:对作为参数默认值使用的 lambda 中的非局部 return 报告错误

标准库

弃用 kotlin.native.Throws

Issue:KT-72137 组件:Kotlin/Native 不兼容变更类型:源码级 简要说明:kotlin.native.Throws 已被弃用;请改用公共的 kotlin.Throws 注解。弃用周期:- 1.9.0:使用 kotlin.native.Throws 时报告警告 - 2.2.0:把该警告提升为错误

弃用 AbstractDoubleTimeSource

Issue:KT-72137 组件:kotlin-stdlib 不兼容变更类型:源码级 简要说明:AbstractDoubleTimeSource 已被弃用;请改用 AbstractLongTimeSource。弃用周期:- 1.8.20:使用 AbstractDoubleTimeSource 时报告警告 - 2.2.0:把该警告提升为错误

工具

修正 KotlinCompileTool 中的 setSource() 函数以替换源

Issue:KT-59632 组件:Gradle 不兼容变更类型:行为级 简要说明:KotlinCompileTool 接口中的 setSource() 函数现在会替换已配置的源,而不是追加到它们。如果你想在不替换现有源的情况下添加源,请使用 source() 函数。弃用周期:- 2.2.0:启用新行为

弃用 KotlinCompilationOutput#resourcesDirProvider 属性

Issue:KT-70620 组件:Gradle 不兼容变更类型:源码级 简要说明:KotlinCompilationOutput#resourcesDirProvider 属性已被弃用。请改为在 Gradle 构建脚本中使用 KotlinSourceSet.resources 来添加额外的资源目录。弃用周期:- 2.1.0:KotlinCompilationOutput#resourcesDirProvider 被弃用并给出警告 - 2.2.0:把该警告提升为错误

弃用 BaseKapt.annotationProcessorOptionProviders 属性

Issue:KT-58009 组件:Gradle 不兼容变更类型:源码级 简要说明:BaseKapt.annotationProcessorOptionProviders 属性已被弃用,改用 BaseKapt.annotationProcessorOptionsProviders,后者接受 ListProperty<CommandLineArgumentProvider> 而不是 MutableList<Any>。这明确规定了期望的元素类型,并防止因添加错误元素(例如嵌套列表)而导致的运行时失败。如果你当前的代码把列表作为单个元素添加,请把 add() 函数替换为 addAll() 函数。弃用周期:- 2.2.0:在 API 中强制使用新类型

弃用 kotlin-android-extensions 插件

Issue:KT-72341 组件:Gradle 不兼容变更类型:源码级 简要说明:kotlin-android-extensions 插件已被弃用。请改用单独的插件 kotlin-parcelize 来生成 Parcelable 实现,并用 Android Jetpack 的视图绑定来替代合成视图。弃用周期:- 1.4.20:该插件被弃用 - 2.1.20:引入配置错误,且不再执行任何插件代码 - 2.2.0:移除插件代码 - 2.4.0:移除该插件 ID

弃用 kotlinOptions DSL

Issue:KT-54110 组件:Gradle 不兼容变更类型:源码级 简要说明:通过 kotlinOptions DSL 以及相关的 KotlinCompile<KotlinOptions> 任务接口配置编译器选项的能力已被弃用,改用新的 compilerOptions DSL。作为该弃用的一部分,kotlinOptions 接口中的所有属性现在也都被单独标记为已弃用。要迁移,请使用 compilerOptions DSL 配置编译器选项。迁移指南请参阅从 kotlinOptions {} 迁移到 compilerOptions {}。弃用周期:- 2.0.0:对 kotlinOptions DSL 报告警告 - 2.2.0:把该警告提升为错误,并弃用 kotlinOptions 中的所有属性

移除 kotlin.incremental.useClasspathSnapshot 属性

Issue:KT-62963 组件:Gradle 不兼容变更类型:源码级 简要说明:kotlin.incremental.useClasspathSnapshot Gradle 属性已被移除。该属性用于控制已弃用的基于历史的 JVM 增量编译模式,后者自 Kotlin 1.8.20 起已被默认启用的基于 classpath 的方式取代。弃用周期:- 2.0.20:以警告形式弃用 kotlin.incremental.useClasspathSnapshot 属性 - 2.2.0:移除该属性

Kotlin 脚本相关的弃用

Issues:KT-71685、KT-75632、KT-76196。组件:脚本 不兼容变更类型:源码级 简要说明:Kotlin 2.2.0 弃用了对以下内容的支持:* REPL:要继续通过 kotlinc 使用 REPL,请使用 -Xrepl 编译器选项来选择启用。* JSR-223:因为该 JSR 处于 Withdrawn(已撤回)状态。JSR-223 实现仍可在语言版本 1.9 下工作,但未来没有迁移到 K2 编译器的计划。* KotlinScriptMojo Maven 插件。如果你继续使用它,会看到编译器警告。更多信息请参阅我们的博客文章。弃用周期:- 2.1.0:以警告形式弃用 kotlinc 中 REPL 的使用 - 2.2.0:要通过 kotlinc 使用 REPL,请用 -Xrepl 编译器选项选择启用;弃用 JSR-223,切换到语言版本 1.9 可以恢复支持;弃用 KotlinScriptMojo Maven 插件 - 2.4.0:移除通过 KotlinScriptMojo Maven 插件执行 Kotlin 脚本的能力

弃用消歧分类器属性

Issue:KT-58231 组件:Gradle 不兼容变更类型:源码级 简要说明:用于控制 Kotlin Gradle 插件如何对源集名称和 IDE 导入进行消歧的选项已经过时。因此,KotlinTarget 接口中的以下属性现已被弃用:* useDisambiguationClassifierAsSourceSetNamePrefix * overrideDisambiguationClassifierOnIdeImport 弃用周期:- 2.0.0:使用这些 Gradle 属性时报告警告 - 2.1.0:把该警告提升为错误 - 2.2.0:移除这些 Gradle 属性

弃用 commonization 参数

Issue:KT-75161 组件:Gradle 不兼容变更类型:源码级 简要说明:Kotlin Gradle 插件中用于实验性 commonization 模式的参数已被弃用。这些参数可能产生无效的编译产物并被缓存。要删除受影响的产物:1. 从 gradle.properties 文件中移除以下选项:none kotlin.mpp.enableOptimisticNumberCommonization kotlin.mpp.enablePlatformIntegerCommonization 2. 清理 ~/.konan/*/klib/commonized 目录中的 commonization 缓存,或运行以下命令:bash ./gradlew cleanNativeDistributionCommonization 弃用周期:- 2.2.0:以错误形式弃用 commonization 参数 - 2.2.20:移除 commonization 参数

弃用对旧式元数据编译的支持

Issue:KT-61817 组件:Gradle 不兼容变更类型:源码级 简要说明:用于设置分层结构以及在公共源集与中间源集之间创建中间源集的选项已经过时。以下编译器选项已被移除:* isCompatibilityMetadataVariantEnabled * withGranularMetadata * isKotlinGranularMetadataEnabled 弃用周期:- 2.2.0:从 Kotlin Gradle 插件中移除这些编译器选项

弃用 KotlinCompilation.source API

Issue:KT-64991 组件:Gradle 不兼容变更类型:源码级 简要说明:KotlinCompilation.source API 的访问已被弃用,该 API 曾允许把 Kotlin 源集直接添加到 Kotlin 编译中。弃用周期:- 1.9.0:使用 KotlinCompilation.source 时报告警告 - 1.9.20:把该警告提升为错误 - 2.2.0:从 Kotlin Gradle 插件中移除 KotlinCompilation.source;尝试使用它会在构建脚本编译期间导致 “unresolved reference” 错误

弃用目标预设 API

Issue:KT-71698 组件:Gradle 不兼容变更类型:源码级 简要说明:Kotlin Multiplatform 目标的目标预设已经过时;jvm() 或 iosSimulatorArm64() 等目标 DSL 函数现在覆盖了相同的使用场景。所有与预设相关的 API 都已被弃用:* org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension 中的 presets 属性 * org.jetbrains.kotlin.gradle.plugin.KotlinTargetPreset 接口及其所有继承者 * fromPreset 的各重载 弃用周期:- 1.9.20:对任何使用预设相关 API 的地方报告警告 - 2.0.0:把该警告提升为错误 - 2.2.0:从 Kotlin Gradle 插件的公共 API 中移除预设相关 API;仍然使用它的源码会因 “unresolved reference” 错误而失败,二进制文件(例如 Gradle 插件)如果不针对最新版本的 Kotlin Gradle 插件重新编译,可能会出现链接错误

弃用 Apple 目标快捷方式

Issue:KT-70615 组件:Gradle 不兼容变更类型:源码级 简要说明:Kotlin Multiplatform DSL 中的 ios()、watchos() 和 tvos() 目标快捷方式已被弃用。这些快捷方式原本用于为 Apple 目标部分创建源集层级。Kotlin Multiplatform Gradle 插件现在提供了内置的层级模板。请改为指定目标列表,插件会自动为它们设置中间源集。弃用周期:- 1.9.20:使用目标快捷方式时报告警告;改为默认启用默认层级模板 - 2.1.0:使用目标快捷方式时报告错误 - 2.2.0:从 Kotlin Multiplatform Gradle 插件中移除目标快捷方式 DSL

弃用 publishAllLibraryVariants() 函数

Issue:KT-60623 组件:Gradle 不兼容变更类型:源码级 简要说明:publishAllLibraryVariants() 函数已被弃用。它原本用于发布 Android 目标的所有构建变体。现在不再推荐这种做法,因为它可能导致变体解析出问题,尤其是在使用多个 flavor 和构建类型时。请改用指定构建变体的 publishLibraryVariants() 函数。弃用周期:- 2.2.0:publishAllLibraryVariants() 被弃用

弃用 android 目标

Issue:KT-71608 组件:Gradle 不兼容变更类型:源码级 简要说明:当前 Kotlin DSL 中的 android 目标名称已被弃用。请改用 androidTarget。弃用周期:- 1.9.0:在 Kotlin Multiplatform 项目中使用 android 名称时引入弃用警告 - 2.1.0:把该警告提升为错误 - 2.2.0:从 Kotlin Multiplatform Gradle 插件中移除 android 目标 DSL

弃用 CInteropProcess 中的 konanVersion

Issue:KT-71069 组件:Gradle 不兼容变更类型:源码级 简要说明:CInteropProcess 任务中的 konanVersion 属性已被弃用。请改用 CInteropProcess.kotlinNativeVersion。弃用周期:- 2.1.0:使用 konanVersion 属性时报告警告 - 2.2.0:把该警告提升为错误 - 2.3.0:从 Kotlin Gradle 插件中移除 konanVersion 属性

弃用 CInteropProcess 中的 destinationDir

Issue:KT-71068 组件:Gradle 不兼容变更类型:源码级 简要说明:CInteropProcess 任务中的 destinationDir 属性已被弃用。请改用 CInteropProcess.destinationDirectory.set() 函数。弃用周期:- 2.1.0:使用 destinationDir 属性时报告警告 - 2.2.0:把该警告提升为错误 - 2.3.0:从 Kotlin Gradle 插件中移除 destinationDir 属性

弃用 kotlinArtifacts API

Issue:KT-74953 组件:Gradle 不兼容变更类型:源码级 简要说明:实验性的 kotlinArtifacts API 已被弃用。请使用 Kotlin Gradle 插件中现有的 DSL 来构建最终的本地二进制文件。如果这不足以完成迁移,请在这个 YouTrack issue 中留言。弃用周期:- 2.2.0:使用 kotlinArtifacts API 时报告警告 - 2.3.0:把该警告提升为错误