13.6.5.3 Kotlin 1.9.x 兼容性指南
13 分钟阅读
原文链接: https://kotlinlang.org/docs/compatibility-guide-19.html
13.6.5.3 Kotlin 1.9.x 兼容性指南
保持语言的现代性 和 舒适的更新 是 Kotlin 语言设计中的基本原则。前者指出,阻碍语言演进的构造应该被移除;后者指出,这种移除应事先充分沟通,以便代码迁移尽可能顺畅。
虽然大多数语言变更已经通过其他渠道公布过(例如更新日志或编译器警告),但本文汇总了所有这些变更,为从 Kotlin 1.8 迁移到 Kotlin 1.9 提供完整参考。
基本术语
本文介绍了以下几种兼容性:
- 源码级:源码不兼容的变更会让原本能正常编译(无错误或警告)的代码不再能编译
- 二进制级:如果互换两个二进制产物不会导致加载或链接错误,则称它们是二进制兼容的
- 行为级:如果同一个程序在应用变更前后的行为不同,则该变更属于行为不兼容
请记住,这些定义仅针对纯 Kotlin。从其他语言(例如 Java)的视角来看 Kotlin 代码的兼容性不在本文讨论范围内。
语言
移除语言版本 1.3
Issue:KT-61111 组件:核心语言 不兼容变更类型:源码级 简要说明:Kotlin 1.9 引入了语言版本 1.9,并移除了对语言版本 1.3 的支持。弃用周期:- 1.6.0:报告警告 - 1.9.0:把该警告提升为错误
当父接口类型为函数字面量时禁止父构造器调用
Issue:KT-46344 组件:核心语言 不兼容变更类型:源码级 简要说明:如果某个接口继承自函数字面量类型,Kotlin 1.9 禁止父构造器调用,因为并不存在这样的构造器。弃用周期:* 1.7.0:报告警告(在渐进模式下报告错误)* 1.9.0:把该警告提升为错误
禁止注解参数类型中出现循环
Issue:KT-47932 组件:核心语言 不兼容变更类型:源码级 简要说明:Kotlin 1.9 禁止把注解自身的类型直接或间接用作其参数类型之一。这可以防止形成循环。不过,允许参数类型是该注解类型的
Array或vararg。弃用周期:* 1.7.0:对注解参数类型中的循环报告警告(在渐进模式下报告错误)* 1.9.0:把该警告提升为错误,可以用-XXLanguage:-ProhibitCyclesInAnnotations临时回退到 1.9 之前的行为
禁止在没有参数的函数类型上使用 @ExtensionFunctionType 注解
Issue:KT-43527 组件:核心语言 不兼容变更类型:源码级 简要说明:Kotlin 1.9 禁止在没有参数的函数类型上,或在并非函数类型的类型上使用
@ExtensionFunctionType注解。弃用周期:* 1.7.0:对非函数类型上的注解报告警告,对是函数类型的类型上的注解报告错误 * 1.9.0:把针对函数类型的警告提升为错误
禁止 Java 字段类型在赋值时不匹配
Issue:KT-48994 组件:Kotlin/JVM 不兼容变更类型:源码级 简要说明:如果 Kotlin 1.9 检测到赋给 Java 字段的值的类型与该 Java 字段的投影类型不匹配,就会报告编译器错误。弃用周期:* 1.6.0:当投影后的 Java 字段类型与所赋值的类型不匹配时报告警告(在渐进模式下报告错误)* 1.9.0:把该警告提升为错误,可以用
-XXLanguage:-RefineTypeCheckingOnAssignmentsToJavaFields临时回退到 1.9 之前的行为
平台类型可空性断言异常中不再包含源码片段
Issue:KT-57570 组件:Kotlin/JVM 不兼容变更类型:行为级 简要说明:在 Kotlin 1.9 中,表达式 null 检查的异常消息不再包含源码片段,而是显示方法或字段的名称。如果该表达式不是方法或字段,消息中不提供额外信息。弃用周期:* < 1.9.0:表达式 null 检查生成的异常消息包含源码片段 * 1.9.0:表达式 null 检查生成的异常消息只包含方法或字段名称,可以用
-XXLanguage:-NoSourceCodeInNotNullAssertionExceptions临时回退到 1.9 之前的行为
禁止把父调用委托给抽象的父类成员
Issues: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 带主语中令人困惑的语法
Issue:KT-48385 组件:核心语言 不兼容变更类型:源码级 简要说明:Kotlin 1.6 弃用了
when条件表达式中若干令人困惑的语法构造。弃用周期:- 1.6.20:对受影响的表达式引入弃用警告 - 1.8.0:把该警告提升为错误,可以用-XXLanguage:-ProhibitConfusingSyntaxInWhenBranches临时回退到 1.8 之前的行为 - >= 2.1:把某些已弃用的构造重新用于新的语言特性
防止不同数值类型之间的隐式强制转换
Issue:KT-48645 组件:Kotlin/JVM 不兼容变更类型:行为级 简要说明:在语义上只需要向下转换到某种原始数值类型时,Kotlin 将避免自动把数值转换为该原始数值类型。弃用周期:- < 1.5.30:所有受影响情况下使用旧行为 - 1.5.30:修复生成的属性委托访问器中的向下转换行为,可以用
-Xuse-old-backend临时回退到 1.5.30 修复之前的行为 - >= 2.0:修复其他受影响情况下的向下转换行为
禁止在泛型类型别名使用中违反上界(在别名类型某个类型实参的泛型类型实参中使用类型参数)
Issue:KT-54066 组件:核心语言 不兼容变更类型:源码级 简要说明:当类型别名的类型参数被用作别名类型某个类型实参的泛型类型实参时(例如
typealias Alias<T> = Base<List<T>>),Kotlin 将禁止使用违反别名类型相应类型参数上界限制的类型实参来使用该类型别名。弃用周期:- 1.8.0:当泛型类型别名的用法中存在违反别名类型相应类型参数上界约束的类型实参时报告警告 - 2.0.0:把该警告提升为错误
在公共签名中近似局部类型时保留可空性
Issue:KT-53982 组件:核心语言 不兼容变更类型:源码级、二进制级 简要说明:当局部类型或匿名类型从未显式指定返回类型的表达式体函数中返回时,Kotlin 编译器会使用该类型已知的父类型来推断(或近似)返回类型。在此过程中,编译器可能推断出不可为空的类型,而实际上可能返回 null 值。弃用周期:- 1.8.0:用灵活的父类型近似灵活类型 - 1.8.0:当某个声明被推断为不可为空、但本应可为空的类型时报告警告,提示用户显式指定类型 - 2.0.0:用可为空的父类型近似可为空的类型,可以用
-XXLanguage:-KeepNullabilityWhenApproximatingLocalType临时回退到 2.0 之前的行为
不通过覆盖传播弃用
Issue:KT-47902 组件:核心语言 不兼容变更类型:源码级 简要说明:Kotlin 1.9 不再把父类中某个已弃用成员的弃用状态传播到子类中覆盖它的成员,从而提供了一种明确的机制:可以弃用父类的某个成员,同时在子类中保持它未被弃用。弃用周期:- 1.6.20:报告一条警告,说明未来的行为变更,并提示要么抑制该警告,要么在已弃用成员的覆盖上显式写上
@Deprecated注解 - 1.9.0:停止把弃用状态传播给被覆盖的成员。该变更在渐进模式下也会立即生效
禁止在注解类中除参数声明之外的任何地方使用集合字面量
Issue:KT-39041 组件:核心语言 不兼容变更类型:源码级 简要说明:Kotlin 允许以受限的方式使用集合字面量——把数组传给注解类的参数,或为这些参数指定默认值。但除此之外,Kotlin 曾允许在注解类内部的任何其他地方使用集合字面量,例如在其嵌套对象中。Kotlin 1.9 将禁止在注解类中除参数默认值之外的任何地方使用集合字面量。弃用周期:- 1.7.0:对注解类嵌套对象中的数组字面量报告警告(在渐进模式下报告错误)- 1.9.0:把该警告提升为错误
禁止在默认值表达式中前向引用参数
Issue:KT-25694 组件:核心语言 不兼容变更类型:源码级 简要说明:Kotlin 1.9 将禁止在其他参数的默认值表达式中前向引用参数。这确保当某个参数在默认值表达式中被访问时,它已经具有值:要么是传给函数的值,要么是由它自己的默认值表达式初始化得到的值。弃用周期:- 1.7.0:当带有默认值的参数在它之前的另一个参数的默认值中被引用时报告警告(在渐进模式下报告错误)- 1.9.0:把该警告提升为错误,可以用
-XXLanguage:-ProhibitIllegalValueParameterUsageInDefaultArguments临时回退到 1.9 之前的行为
禁止对内联函数式参数进行扩展调用
Issue:KT-52502 组件:核心语言 不兼容变更类型:源码级 简要说明:虽然 Kotlin 曾允许把内联函数式参数作为接收者传给另一个内联函数,但编译这类代码时总是导致编译器异常。Kotlin 1.9 将禁止这一做法,从而报告错误而不是让编译器崩溃。弃用周期:- 1.7.20:对针对内联函数式参数的内联扩展调用报告警告(在渐进模式下报告错误)- 1.9.0:把该警告提升为错误
禁止以匿名函数实参调用名为 suspend 的中缀函数
Issue:KT-49264 组件:核心语言 不兼容变更类型:源码级 简要说明:Kotlin 1.9 不再允许调用名为
suspend、且其唯一参数为函数类型并以匿名函数字面量形式传入的中缀函数。弃用周期:- 1.7.20:对带匿名函数字面量的 suspend 中缀调用报告警告 - 1.9.0:把该警告提升为错误,可以用-XXLanguage:-ModifierNonBuiltinSuspendFunError临时回退到 1.9 之前的行为 - TODO:改变解析器对suspend fun记号序列的解释方式
禁止在内部类中违反型变规则使用捕获的类型参数
Issue:KT-50947 组件:核心语言 不兼容变更类型:源码级 简要说明:如果外部类的类型参数具有
in或out型变,Kotlin 1.9 将禁止在该类的内部类中,以违反该类型参数所声明型变的位置使用它。弃用周期:- 1.7.0:当外部类类型参数的使用位置违反该参数的型变规则时报告警告(在渐进模式下报告错误)- 1.9.0:把该警告提升为错误,可以用-XXLanguage:-ReportTypeVarianceConflictOnQualifierArguments临时回退到 1.9 之前的行为
禁止在复合赋值运算符中递归调用没有显式返回类型的函数
Issue:KT-48546 组件:核心语言 不兼容变更类型:源码级 简要说明:Kotlin 1.9 将禁止在函数体内复合赋值运算符的实参中调用一个没有显式指定返回类型的函数,就像它目前在该函数体内其他表达式中已禁止的那样。弃用周期:- 1.7.0:当没有显式指定返回类型的函数在其函数体内复合赋值运算符的实参中被递归调用时报告警告(在渐进模式下报告错误)- 1.9.0:把该警告提升为错误
禁止在期望 @NotNull T 而给出的 Kotlin 泛型参数有可空边界时进行不健全的调用
Issue:KT-36770 组件:Kotlin/JVM 不兼容变更类型:源码级 简要说明:Kotlin 1.9 将禁止这样的方法调用:为 Java 方法中带有
@NotNull注解的参数传入一个可能可为空的泛型类型的值。弃用周期:- 1.5.20:当把不受约束的泛型类型参数传给期望非空类型的位置时报告警告 - 1.9.0:用类型不匹配错误取代上述警告,可以用-XXLanguage:-ProhibitUsingNullableTypeParameterAgainstNotNullAnnotated临时回退到 1.8 之前的行为
禁止从枚举的条目初始化器中访问该枚举伴生对象的成员
Issue:KT-49110 组件:核心语言 不兼容变更类型:源码级 简要说明:Kotlin 1.9 将禁止从枚举条目初始化器中对枚举的伴生对象进行任何形式的访问。弃用周期:- 1.6.20:对此类伴生成员访问报告警告(在渐进模式下报告错误)- 1.9.0:把该警告提升为错误,可以用
-XXLanguage:-ProhibitAccessToEnumCompanionMembersInEnumConstructorCall临时回退到 1.8 之前的行为
弃用并移除 Enum.declaringClass 合成属性
Issue: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 的 enable 和 compatibility 模式
Issues:KT-46329、KT-54746 组件:Kotlin/JVM 不兼容变更类型:源码级 简要说明:Kotlin 1.9 禁止使用
-Xjvm-default编译器选项的enable和compatibility模式。弃用周期:- 1.6.20:对-Xjvm-default编译器选项的enable和compatibility模式引入警告 - 1.9.0:把该警告提升为错误
禁止在构建器推断上下文中把类型变量隐式推断为某个上界
Issue:KT-47986 组件:核心语言 不兼容变更类型:源码级 简要说明:在构建器推断 lambda 函数的作用域内,如果没有任何使用处的类型信息,Kotlin 2.0 将禁止把类型变量推断为相应类型参数的上界,就像它目前在其他上下文中已禁止的那样。弃用周期:- 1.7.20:当在使用处没有类型信息的情况下把类型参数推断为声明的上界时报告警告(在渐进模式下报告错误)- 2.0.0:把该警告提升为错误
标准库
当 Range/Progression 开始实现 Collection 时对潜在的重载解析变化发出警告
Issue:KT-49276 组件:核心语言 / kotlin-stdlib 不兼容变更类型:源码级 简要说明:计划在 Kotlin 1.9 中让标准 progression 及继承自它们的具名 range 实现
Collection接口。如果某个方法有两个重载(一个接受元素,另一个接受集合),这可能导致重载解析选中不同的重载。Kotlin 会通过在以 range 或 progression 为实参调用此类重载方法时报告警告或错误来让这种情况显现出来。弃用周期:- 1.6.20:如果该 progression/range 实现Collection接口会导致此次调用将来选中另一个重载,则以标准 progression 或其 range 继承者作为实参调用重载方法时报告警告 - 1.8.0:把该警告提升为错误 - 2.1.0:停止报告该错误,在 progression 中实现Collection接口,从而在受影响的情况下改变重载解析结果
把声明从 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.8.20:从 JS-IR 目标的标准库中移除已弃用的函数 - >= 2.0:把 kotlinx.* 包中的 API 移到一个单独的库
弃用部分仅 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.9.0:把弃用级别提升为错误 - >=2.0:从公共 API 中移除这些已弃用的函数
工具
从 Gradle 设置中移除 enableEndorsedLibs 标志
Issue:KT-54098 组件:Gradle 不兼容变更类型:源码级 简要说明:Gradle 设置中不再支持
enableEndorsedLibs标志。弃用周期:- < 1.9.0:Gradle 设置中支持enableEndorsedLibs标志 - 1.9.0:Gradle 设置中不支持enableEndorsedLibs标志
移除 Gradle 约定
Issue:KT-52976 组件:Gradle 不兼容变更类型:源码级 简要说明:Gradle 约定在 Gradle 7.1 中被弃用,并已在 Gradle 8 中移除。弃用周期:- 1.7.20:Gradle 约定被弃用 - 1.9.0:Gradle 约定被移除
移除 KotlinCompile 任务的 classpath 属性
Issue:KT-53748 组件:Gradle 不兼容变更类型:源码级 简要说明:
KotlinCompile任务的classpath属性已被移除。弃用周期:- 1.7.0:classpath属性被弃用 - 1.8.0:把弃用级别提升为错误 - 1.9.0:从公共 API 中移除这些已弃用的函数
弃用 kotlin.internal.single.build.metrics.file 属性
Issue:KT-53357 组件:Gradle 不兼容变更类型:源码级 简要说明:弃用用于为构建报告指定单个文件的
kotlin.internal.single.build.metrics.file属性。请改用kotlin.build.report.single_file属性并配合kotlin.build.report.output=single_file。弃用周期:* 1.8.0:把弃用级别提升为警告 * >= 1.9:删除该属性