Compatibility guide for Kotlin 1.5 Keeping the Language Modern and Comfortable Updates are among the fundamental principles in Kotlin Language Design. The former says that constructs which obstruct language evolution should be removed, and the latter says that this removal should be well-communicated beforehand to make code migration as smooth as possible.
While most of the language changes were already announced through other channels, like update changelogs or compiler warnings, this document summarizes them all, providing a complete reference for migration from Kotlin 1.4 to Kotlin 1.5.
Basic terms In this document we introduce several kinds of compatibility:
source : source-incompatible change stops code that used to compile fine (without errors or warnings) from compiling anymore
binary : two binary artifacts are said to be binary-compatible if interchanging them doesn't lead to loading or linkage errors
behavioral : a change is said to be behavioral-incompatible if the same program demonstrates different behavior before and after applying the change
Remember that those definitions are given only for pure Kotlin. Compatibility of Kotlin code from the other languages perspective (for example, from Java) is out of the scope of this document.
Language and stdlib Forbid spread operator in signature-polymorphic calls Issue : KT-35226
Component : Core language
Incompatible change type : source
Short summary : Kotlin 1.5 will outlaw the use of spread operator (*) on signature-polymorphic calls
Deprecation cycle :
< 1.5: introduce warning for the problematic operator at call-site
>= 1.5: raise this warning to an error, -XXLanguage:-ProhibitSpreadOnSignaturePolymorphicCall
can be used to temporarily revert to pre-1.5 behavior
Forbid non-abstract classes containing abstract members invisible from that classes (internal/package-private) Issue : KT-27825
Component : Core language
Incompatible change type : source
Short summary : Kotlin 1.5 will outlaw non-abstract classes containing abstract members invisible from that classes (internal/package-private)
Deprecation cycle :
< 1.5: introduce warning for the problematic classes
>= 1.5: raise this warning to an error, -XXLanguage:-ProhibitInvisibleAbstractMethodsInSuperclasses
can be used to temporarily revert to pre-1.5 behavior
Forbid using array based on non-reified type parameters as reified type arguments on JVM Issue : KT-31227
Component : Core language
Incompatible change type : source
Short summary : Kotlin 1.5 will outlaw using array based on non-reified type parameters as reified type arguments on JVM
Deprecation cycle :
< 1.5: introduce warning for the problematic calls
>= 1.5: raise this warning to an error, -XXLanguage:-ProhibitNonReifiedArraysAsReifiedTypeArguments
can be used to temporarily revert to pre-1.5 behavior
Forbid secondary enum class constructors which do not delegate to the primary constructor Issue : KT-35870
Component : Core language
Incompatible change type : source
Short summary : Kotlin 1.5 will outlaw secondary enum class constructors which do not delegate to the primary constructor
Deprecation cycle :
< 1.5: introduce warning for the problematic constructors
>= 1.5: raise this warning to an error, -XXLanguage:-RequiredPrimaryConstructorDelegationCallInEnums
can be used to temporarily revert to pre-1.5 behavior
Forbid exposing anonymous types from private inline functions Issue : KT-33917
Component : Core language
Incompatible change type : source
Short summary : Kotlin 1.5 will outlaw exposing anonymous types from private inline functions
Deprecation cycle :
< 1.5: introduce warning for the problematic constructors
>= 1.5: raise this warning to an error, -XXLanguage:-ApproximateAnonymousReturnTypesInPrivateInlineFunctions
can be used to temporarily revert to pre-1.5 behavior
Forbid passing non-spread arrays after arguments with SAM-conversion Issue : KT-35224
Component : Core language
Incompatible change type : source
Short summary : Kotlin 1.5 will outlaw passing non-spread arrays after arguments with SAM-conversion
Deprecation cycle :
1.3.70: introduce warning for the problematic calls
>= 1.5: raise this warning to an error, -XXLanguage:-ProhibitVarargAsArrayAfterSamArgument
can be used to temporarily revert to pre-1.5 behavior
Support special semantics for underscore-named catch block parameters Issue : KT-31567
Component : Core language
Incompatible change type : source
Short summary : Kotlin 1.5 will outlaw references to the underscore symbol (_
) that is used to omit parameter name of an exception in the catch block
Deprecation cycle :
1.4.20: introduce warning for the problematic references
>= 1.5: raise this warning to an error, -XXLanguage:-ForbidReferencingToUnderscoreNamedParameterOfCatchBlock
can be used to temporarily revert to pre-1.5 behavior
Change implementation strategy of SAM conversion from anonymous class-based to invokedynamic Issue : KT-44912
Component : Kotlin/JVM
Incompatible change type : behavioral
Short summary : Since Kotlin 1.5, implementation strategy of SAM (single abstract method) conversion will be changed from generating an anonymous class to using the invokedynamic
JVM instruction
Deprecation cycle :
Issue : KT-48233
Component : Kotlin/JVM
Incompatible change type : behavioral
Short summary : Kotlin 1.5 uses the IR-based backend for the Kotlin/JVM compiler by default. The old backend is still used by default for earlier language versions.
You might encounter some performance degradation issues using the new compiler in Kotlin 1.5. We are working on fixing such cases.
Deprecation cycle :
< 1.5: by default, the old JVM backend is used
>= 1.5: by default, the IR-based backend is used. If you need to use the old backend in Kotlin 1.5, add the following lines to the project's configuration file to temporarily revert to pre-1.5 behavior:
In Gradle:
tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile> {
kotlinOptions.useOldBackend = true
}
tasks.withType(org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile) {
kotlinOptions.useOldBackend = true
}
In Maven:
<configuration>
<args>
<arg>-Xuse-old-backend</arg>
</args>
</configuration>
Support for this flag will be removed in one of the future releases.
New field sorting in the JVM IR-based backend Issue : KT-46378
Component : Kotlin/JVM
Incompatible change type : behavioral
Short summary : Since version 1.5, Kotlin uses the IR-based backend that sorts JVM bytecode differently: it generates fields declared in the constructor before fields declared in the body, while it's vice versa for the old backend. The new sorting may change the behavior of programs that use serialization frameworks that depend on the field order, such as Java serialization.
Deprecation cycle :
< 1.5: by default, the old JVM backend is used. It has fields declared in the body before fields declared in the constructor.
>= 1.5: by default, the new IR-based backend is used. Fields declared in the constructor are generated before fields declared in the body. As a workaround, you can temporarily switch to the old backend in Kotlin 1.5. To do that, add the following lines to the project's configuration file:
In Gradle:
tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile> {
kotlinOptions.useOldBackend = true
}
tasks.withType(org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile) {
kotlinOptions.useOldBackend = true
}
In Maven:
<configuration>
<args>
<arg>-Xuse-old-backend</arg>
</args>
</configuration>
Support for this flag will be removed in one of the future releases.
Generate nullability assertion for delegated properties with a generic call in the delegate expression Issue : KT-44304
Component : Kotlin/JVM
Incompatible change type : behavioral
Short summary : Since Kotlin 1.5, the Kotlin compiler will emit nullability assertions for delegated properties with a generic call in the delegate expression
Deprecation cycle :
Issue : KT-45861
Component : Core language
Incompatible change type : source
Short summary : Kotlin 1.5 will outlaw calls like contains
, indexOf
, and assertEquals
with senseless arguments to improve type safety
Deprecation cycle :
1.4.0: introduce warning for the problematic constructors
>= 1.5: raise this warning to an error, -XXLanguage:-StrictOnlyInputTypesChecks
can be used to temporarily revert to pre-1.5 behavior
Use the correct order of arguments execution in calls with named vararg Issue : KT-17691
Component : Kotlin/JVM
Incompatible change type : behavioral
Short summary : Kotlin 1.5 will change the order of arguments execution in calls with named vararg
Deprecation cycle :
< 1.5: introduce warning for the problematic constructors
>= 1.5: raise this warning to an error, -XXLanguage:-UseCorrectExecutionOrderForVarargArguments
can be used to temporarily revert to pre-1.5 behavior
Use default value of the parameter in operator functional calls Issue : KT-42064
Component : Kotlin/JVM
Incompatible change type : behavioral
Short summary : Kotlin 1.5 will use default value of the parameter in operator calls
Deprecation cycle :
< 1.5: old behavior (see details in the issue)
>= 1.5: behavior changed, -XXLanguage:-JvmIrEnabledByDefault
can be used to temporarily revert to pre-1.5 behavior
Produce empty reversed progressions in for loops if regular progression is also empty Issue : KT-42533
Component : Kotlin/JVM
Incompatible change type : behavioral
Short summary : Kotlin 1.5 will produce empty reversed progressions in for loops if regular progression is also empty
Deprecation cycle :
< 1.5: old behavior (see details in the issue)
>= 1.5: behavior changed, -XXLanguage:-JvmIrEnabledByDefault
can be used to temporarily revert to pre-1.5 behavior
Straighten Char-to-code and Char-to-digit conversions out Issue : KT-23451
Component : kotlin-stdlib
Incompatible change type : source
Short summary : Since Kotlin 1.5, conversions of Char to number types will be deprecated
Deprecation cycle :
Inconsistent case-insensitive comparison of characters in kotlin.text functions Issue : KT-45496
Component : kotlin-stdlib
Incompatible change type : behavioral
Short summary : Since Kotlin 1.5, Char.equals
will be improved in case-insensitive case by first comparing whether the uppercase variants of characters are equal, then whether the lowercase variants of those uppercase variants (as opposed to the characters themselves) are equal
Deprecation cycle :
Remove default locale-sensitive case conversion API Issue : KT-43023
Component : kotlin-stdlib
Incompatible change type : source
Short summary : Since Kotlin 1.5, default locale-sensitive case conversion functions like String.toUpperCase()
will be deprecated
Deprecation cycle :
Gradually change the return type of collection min and max functions to non-nullable Issue : KT-38854
Component : kotlin-stdlib (JVM)
Incompatible change type : source
Short summary : return type of collection min
and max
functions will be changed to non-nullable in 1.6
Deprecation cycle :
1.4: introduce ...OrNull
functions as synonyms and deprecate the affected API (see details in the issue)
1.5.0: raise the deprecation level of the affected API to error
>=1.6: reintroduce the affected API but with non-nullable return type
Raise the deprecation level of conversions of floating-point types to Short and Byte Issue : KT-30360
Component : kotlin-stdlib (JVM)
Incompatible change type : source
Short summary : conversions of floating-point types to Short
and Byte
deprecated in Kotlin 1.4 with WARNING
level will cause errors since Kotlin 1.5.0.
Deprecation cycle :
Do not mix several JVM variants of kotlin-test in a single project Issue : KT-40225
Component : Gradle
Incompatible change type : behavioral
Short summary : several mutually exclusive kotlin-test
variants for different testing frameworks could have been in a project if one of them is brought by a transitive dependency. From 1.5.0, Gradle won't allow having mutually exclusive kotlin-test
variants for different testing frameworks.
Deprecation cycle :
< 1.5: having several mutually exclusive kotlin-test
variants for different testing frameworks is allowed
>= 1.5: behavior changed,
Gradle throws an exception like "Cannot select module with conflict on capability...". Possible solutions:
use the same kotlin-test
variant and the corresponding testing framework as the transitive dependency brings.
find another variant of the dependency that doesn't bring the kotlin-test
variant transitively, so you can use the testing framework you would like to use.
find another variant of the dependency that brings another kotlin-test
variant transitively, which uses the same testing framework you would like to use.
exclude the testing framework that is brought transitively. The following example is for excluding JUnit 4:
configurations {
testImplementation.get().exclude("org.jetbrains.kotlin", "kotlin-test-junit")
}
After excluding the testing framework, test your application. If it stopped working, rollback excluding changes, use the same testing framework as the library does, and exclude your testing framework.
Last modified: 25 September 2024