13.6.8.3 Kotlin 1.6.x 兼容性指南

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

13.6.8.3 Kotlin 1.6.x 兼容性指南

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

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

基本术语

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

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

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

语言

默认让带有 enum、sealed 和 Boolean 主语的 when 语句完备

Issue:KT-47709 组件:核心语言 不兼容变更类型:源码级 简要说明:Kotlin 1.6 会对带有 enum、sealed 或 Boolean 主语的 when 语句不完备的情况发出警告 弃用周期:- 1.6.0:当带有 enum、sealed 或 Boolean 主语的 when 语句不完备时引入警告(在渐进模式下报告错误)- 1.7.0:把该警告提升为错误

弃用 when 带主语中令人困惑的语法

Issue:KT-48385 组件:核心语言 不兼容变更类型:源码级 简要说明:Kotlin 1.6 将弃用 when 条件表达式中若干令人困惑的语法构造 弃用周期:- 1.6.20:对受影响的表达式引入弃用警告 - 1.8.0:把该警告提升为错误 - >= 1.8:把某些已弃用的构造重新用于新的语言特性

禁止在伴生对象和嵌套对象的父构造器调用中访问类成员

Issue:KT-25289 组件:核心语言 不兼容变更类型:源码级 简要说明:如果伴生对象和普通对象父构造器调用的实参的接收者引用了包含它的声明,Kotlin 1.6 将对该实参报告错误 弃用周期:- 1.5.20:对存在问题的实参引入警告 - 1.6.0:把该警告提升为错误,可以用 -XXLanguage:-ProhibitSelfCallsInNestedObjects 临时回退到 1.6 之前的行为

类型可空性增强的改进

Issue:KT-48623 组件:Kotlin/JVM 不兼容变更类型:源码级 简要说明:Kotlin 1.7 将改变它加载和解释 Java 代码中类型可空性注解的方式 弃用周期:- 1.4.30:对更精确的类型可空性可能导致错误的情况引入警告 - 1.7.0:推断更精确的 Java 类型可空性,可以用 -XXLanguage:-TypeEnhancementImprovementsInStrictMode 临时回退到 1.7 之前的行为

防止不同数值类型之间的隐式强制转换

Issue:KT-48645 组件:Kotlin/JVM 不兼容变更类型:行为级 简要说明:在语义上只需要向下转换到某种原始数值类型时,Kotlin 将避免自动把数值转换为该原始数值类型 弃用周期:- < 1.5.30:所有受影响情况下使用旧行为 - 1.5.30:修复生成的属性委托访问器中的向下转换行为,可以用 -Xuse-old-backend 临时回退到 1.5.30 修复之前的行为 - >= 1.6.20:修复其他受影响情况下的向下转换行为

禁止声明其容器注解违反 JLS 的可重复注解类

Issue:KT-47928 组件:Kotlin/JVM 不兼容变更类型:源码级 简要说明:Kotlin 1.6 将检查可重复注解的容器注解是否满足与 JLS 9.6.3 相同的要求:数组类型的值方法、保留策略和目标 弃用周期:- 1.5.30:对违反 JLS 要求的可重复容器注解声明引入警告(在渐进模式下报告错误)- 1.6.0:把该警告提升为错误,可以用 -XXLanguage:-RepeatableAnnotationContainerConstraints 临时禁用错误报告

禁止在可重复注解类中声明名为 Container 的嵌套类

Issue:KT-47971 组件:Kotlin/JVM 不兼容变更类型:源码级 简要说明:Kotlin 1.6 将检查在 Kotlin 中声明的可重复注解是否含有使用预定义名称 Container 的嵌套类 弃用周期:- 1.5.30:对 Kotlin 可重复注解类中名为 Container 的嵌套类引入警告(在渐进模式下报告错误)- 1.6.0:把该警告提升为错误,可以用 -XXLanguage:-RepeatableAnnotationContainerConstraints 临时禁用错误报告

禁止在主构造器中覆盖接口属性的属性上使用 @JvmField

Issue:KT-32753 组件:Kotlin/JVM 不兼容变更类型:源码级 简要说明:Kotlin 1.6 将禁止对在主构造器中声明、且覆盖接口属性的属性使用 @JvmField 注解 弃用周期:- 1.5.20:对主构造器中此类属性上的 @JvmField 注解引入警告 - 1.6.0:把该警告提升为错误,可以用 -XXLanguage:-ProhibitJvmFieldOnOverrideFromInterfaceInPrimaryConstructor 临时禁用错误报告

弃用编译器选项 -Xjvm-default 的 enable 和 compatibility 模式

Issue:KT-46329 组件:Kotlin/JVM 不兼容变更类型:源码级 简要说明:Kotlin 1.6.20 将对使用 -Xjvm-default 编译器选项的 enable 和 compatibility 模式发出警告 弃用周期:- 1.6.20:对 -Xjvm-default 编译器选项的 enable 和 compatibility 模式引入警告 - >= 1.8.0:把该警告提升为错误

禁止从公共 ABI 内联函数中调用 super

Issue:KT-45379 组件:核心语言 不兼容变更类型:源码级 简要说明:Kotlin 1.6 将禁止从公有或受保护的内联函数和属性中调用带 super 限定符的函数 弃用周期:- 1.5.0:对公有或受保护的内联函数或属性访问器中的 super 调用引入警告 - 1.6.0:把该警告提升为错误,可以用 -XXLanguage:-ProhibitSuperCallsFromPublicInline 临时禁用错误报告

禁止从公共内联函数中调用 protected 构造器

Issue:KT-48860 组件:核心语言 不兼容变更类型:源码级 简要说明:Kotlin 1.6 将禁止从公有或受保护的内联函数和属性中调用受保护的构造器 弃用周期:- 1.4.30:对公有或受保护的内联函数或属性访问器中的受保护构造器调用引入警告 - 1.6.0:把该警告提升为错误,可以用 -XXLanguage:-ProhibitProtectedConstructorCallFromPublicInline 临时禁用错误报告

禁止从文件私有类型中暴露私有嵌套类型

Issue:KT-20094 组件:核心语言 不兼容变更类型:源码级 简要说明:Kotlin 1.6 将禁止从文件私有类型中暴露私有嵌套类型和内部类 弃用周期:- 1.5.0:对从文件私有类型中暴露的私有类型引入警告 - 1.6.0:把该警告提升为错误,可以用 -XXLanguage:-PrivateInFileEffectiveVisibility 临时禁用错误报告

类型上的注解在若干情况下不分析注解目标

Issue:KT-28449 组件:核心语言 不兼容变更类型:源码级 简要说明:Kotlin 1.6 将不再允许在不应适用于类型的注解出现在类型上 弃用周期:- 1.5.20:在渐进模式下引入错误 - 1.6.0:引入错误,可以用 -XXLanguage:-ProperCheckAnnotationsTargetInTypeUsePositions 临时禁用错误报告

禁止调用带尾随 lambda 的名为 suspend 的函数

Issue:KT-22562 组件:核心语言 不兼容变更类型:源码级 简要说明:Kotlin 1.6 将不再允许调用名为 suspend、且以尾随 lambda 形式传入唯一函数类型实参的函数 弃用周期:- 1.3.0:对此类函数调用引入警告 - 1.6.0:把该警告提升为错误 - >= 1.7.0:引入语言文法变更,使 { 之前的 suspend 被解析为关键字

标准库

移除 minus/removeAll/retainAll 中脆弱的 contains 优化

Issue:KT-45438 组件:kotlin-stdlib 不兼容变更类型:行为级 简要说明:对于那些从 collection/iterable/array/sequence 中移除若干元素的函数和运算符,Kotlin 1.6 将不再把其参数转换为 set。弃用周期:- < 1.6:旧行为:在某些情况下把参数转换为 set - 1.6.0:如果函数参数是集合,则不再把它转换为 Set。如果不是集合,则可以改为转换为 List。在 JVM 上可以通过设置系统属性 kotlin.collections.convert_arg_to_set_in_removeAll=true 临时恢复旧行为 - >= 1.7:上述系统属性将不再生效

修改 Random.nextLong 的值生成算法

Issue:KT-47304 组件:kotlin-stdlib 不兼容变更类型:行为级 简要说明:Kotlin 1.6 改变了 Random.nextLong 函数中的值生成算法,以避免生成超出指定范围的值。弃用周期:- 1.6.0:立即修复该行为

逐步把集合 min 和 max 函数的返回类型改为不可为空

Issue:KT-38854 组件:kotlin-stdlib 不兼容变更类型:源码级 简要说明:集合 min 和 max 函数的返回类型将在 Kotlin 1.7 中改为不可为空 弃用周期:- 1.4.0:引入 ...OrNull 函数作为同义替代,并弃用受影响的 API(详见该 issue)- 1.5.0:把受影响 API 的弃用级别提升为错误 - 1.6.0:从公共 API 中隐藏这些已弃用的函数 - >= 1.7:重新引入受影响的 API,但返回类型为不可为空

弃用浮点数组函数:contains、indexOf、lastIndexOf

Issue:KT-28753 组件:kotlin-stdlib 不兼容变更类型:源码级 简要说明:Kotlin 弃用浮点数组函数 contains、indexOf、lastIndexOf,它们使用 IEEE-754 顺序而不是全序来比较值 弃用周期:- 1.4.0:以警告形式弃用受影响的函数 - 1.6.0:把弃用级别提升为错误 - >= 1.7:从公共 API 中隐藏这些已弃用的函数

把声明从 kotlin.dom 和 kotlin.browser 包迁移到 kotlinx.*

Issue:KT-39330 组件:kotlin-stdlib(JS)不兼容变更类型:源码级 简要说明:kotlin.dom 和 kotlin.browser 包中的声明被移到相应的 kotlinx.* 包中,为把它们从标准库中提取出来做准备 弃用周期:- 1.4.0:在 kotlinx.dom 和 kotlinx.browser 包中引入替代 API - 1.4.0:弃用 kotlin.dom 和 kotlin.browser 包中的 API,并建议改用上述新 API - 1.6.0:把弃用级别提升为错误 - >= 1.7:从标准库中移除这些已弃用的函数 - >= 1.7:把 kotlinx.* 包中的 API 移到一个单独的库

让 Regex.replace 函数在 Kotlin/JS 中不再是内联函数

Issue:KT-27738 组件:kotlin-stdlib(JS)不兼容变更类型:源码级 简要说明:带函数式 transform 参数的 Regex.replace 函数在 Kotlin/JS 中将不再是内联函数 弃用周期:- 1.6.0:从受影响的函数上移除 inline 修饰符

当替换字符串包含分组引用时 JVM 与 JS 中 Regex.replace 函数的行为不同

Issue:KT-28378 组件:kotlin-stdlib(JS)不兼容变更类型:行为级 简要说明:在使用替换模式字符串时,Kotlin/JS 中的 Regex.replace 函数将遵循与 Kotlin/JVM 相同的模式语法 弃用周期:- 1.6.0:修改 Kotlin/JS 标准库中 Regex.replace 的替换模式处理方式

在 JS 正则中使用 Unicode 大小写折叠

Issue:KT-45928 组件:kotlin-stdlib(JS)不兼容变更类型:行为级 简要说明:Kotlin/JS 中的 Regex 类在调用底层 JS 正则表达式引擎时会使用 unicode 标志,以按 Unicode 规则搜索和比较字符。这带来了对 JS 环境的某些版本要求,并导致对正则模式字符串中不必要转义的更严格校验。弃用周期:- 1.5.0:在 JS Regex 类的大多数函数中启用 Unicode 大小写折叠 - 1.6.0:在 Regex.replaceFirst 函数中启用 Unicode 大小写折叠

弃用部分仅 JS 的 API

Issue:KT-48587 组件:kotlin-stdlib(JS)不兼容变更类型:源码级 简要说明:标准库中若干仅 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.7.0:把弃用级别提升为错误 - 1.8.0:从公共 API 中移除这些已弃用的函数

在 Kotlin/JS 中从类的公共 API 中隐藏实现和互操作专用函数

Issue:KT-48587 组件:kotlin-stdlib(JS)不兼容变更类型:源码级、二进制级 简要说明:函数 HashMap.createEntrySet 和 AbstactMutableCollection.toJSON 的可见性改为 internal 弃用周期:- 1.6.0:把这些函数改为 internal,从而把它们从公共 API 中移除

工具

弃用 KotlinGradleSubplugin 类

Issue:KT-48830 组件:Gradle 不兼容变更类型:源码级 简要说明:类 KotlinGradleSubplugin 将被弃用,改用 KotlinCompilerPluginSupportPlugin 弃用周期:- 1.6.0:把弃用级别提升为错误 - >= 1.7.0:移除这个已弃用的类

移除 kotlin.useFallbackCompilerSearch 构建选项

Issue:KT-46719 组件:Gradle 不兼容变更类型:源码级 简要说明:移除已弃用的 ‘kotlin.useFallbackCompilerSearch’ 构建选项 弃用周期:- 1.5.0:把弃用级别提升为警告 - 1.6.0:移除这个已弃用的选项

移除若干编译器选项

Issue:KT-48847 组件:Gradle 不兼容变更类型:源码级 简要说明:移除已弃用的 noReflect 和 includeRuntime 编译器选项 弃用周期:- 1.5.0:把弃用级别提升为错误 - 1.6.0:移除这些已弃用的选项

弃用 useIR 编译器选项

Issue:KT-48847 组件:Gradle 不兼容变更类型:源码级 简要说明:隐藏已弃用的 useIR 编译器选项 弃用周期:- 1.5.0:把弃用级别提升为警告 - 1.6.0:隐藏该选项 - >= 1.7.0:移除这个已弃用的选项

弃用 kapt.use.worker.api Gradle 属性

Issue:KT-48826 组件:Gradle 不兼容变更类型:源码级 简要说明:弃用 kapt.use.worker.api 属性,它曾允许通过 Gradle Workers API 运行 kapt(默认:true)弃用周期:- 1.6.20:把弃用级别提升为警告 - >= 1.8.0:移除该属性

移除 kotlin.parallel.tasks.in.project Gradle 属性

Issue:KT-46406 组件:Gradle 不兼容变更类型:源码级 简要说明:移除 kotlin.parallel.tasks.in.project 属性 弃用周期:- 1.5.20:把弃用级别提升为警告 - 1.6.20:移除该属性

弃用 kotlin.experimental.coroutines Gradle DSL 选项和 kotlin.coroutines Gradle 属性

Issue:KT-50369 组件:Gradle 不兼容变更类型:源码级 简要说明:弃用 kotlin.experimental.coroutines Gradle DSL 选项和 kotlin.coroutines 属性 弃用周期:- 1.6.20:把弃用级别提升为警告 - >= 1.7.0:移除该 DSL 选项和该属性