Compatibility guide for Kotlin 2.1 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 2.0 to Kotlin 2.1.
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 Change the typeOf() function behavior on Kotlin/Native Issue : KT-70754
Component : Core language
Incompatible change type : behavioral
Short summary : The behavior of the typeOf()
function on Kotlin/Native is aligned with Kotlin/JVM to ensure consistency across platforms.
Deprecation cycle :
Prohibit exposing types through type parameters' bounds Issue : KT-69653
Component : Core language
Incompatible change type : source
Short summary : Exposing types with lower visibility through type parameter bounds is now prohibited, addressing inconsistencies in type visibility rules. This change ensures that bounds on type parameters follow the same visibility rules as classes, preventing issues like IR validation errors in the JVM.
Deprecation cycle :
Prohibit inheriting an abstract var property and a val property with the same name Issue : KT-58659
Component : Core language
Incompatible change type : source
Short summary : If a class inherits an abstract var
property from an interface and a val
property with the same name from a superclass, it now triggers a compilation error. This resolves runtime crashes caused by missing setters in such cases.
Deprecation cycle :
2.1.0: report a warning (or an error in progressive mode) when a class inherits an abstract var
property from an interface and a val
property with the same name from a superclass
2.2.0: raise the warning to an error
Report error when accessing uninitialized enum entries Issue : KT-68451
Component : Core language
Incompatible change type : source
Short summary : The compiler now reports an error when uninitialized enum entries are accessed during enum class or entry initialization. This aligns the behavior with member property initialization rules, preventing runtime exceptions and ensuring consistent logic.
Deprecation cycle :
Changes in K2 smart cast propagation Issue : KTLC-34
Component : Core language
Incompatible change type : behavioral
Short summary : The K2 compiler changes its behavior for smart cast propagation by introducing bidirectional propagation of type information for inferred variables, like val x = y
. Explicitly typed variables, such as val x: T = y
, no longer propagate type information, ensuring stricter adherence to declared types.
Deprecation cycle :
Correct the handling of member-extension property overrides in Java subclasses Issue : KTLC-35
Component : Core language
Incompatible change type : behavioral
Short summary : The getter for member-extension properties overridden by Java subclasses is now hidden in the subclass's scope, aligning its behavior with that of regular Kotlin properties.
Deprecation cycle :
Correct visibility alignment for getters and setters of var properties overriding a protected val Issue : KTLC-36
Component : Core language
Incompatible change type : binary
Short summary : The visibility of getters and setters for var
properties overriding a protected val
property is now consistent, with both inheriting the visibility of the overridden val
property.
Deprecation cycle :
Raise severity of JSpecify nullability mismatch diagnostics to errors Issue : KTLC-11
Component : Core language
Incompatible change type : source
Short summary : Nullability mismatches from org.jspecify.annotations
, such as @NonNull
, @Nullable
, and @NullMarked
are now treated as errors instead of warnings, enforcing stricter type safety for Java interoperability. To adjust the severity of these diagnostics, use the -Xnullability-annotations
compiler option.
Deprecation cycle :
1.6.0: report warnings for potential nullability mismatches
1.8.20: expand warnings to specific JSpecify annotations, including: @Nullable
, @NullnessUnspecified
, @NullMarked
, and legacy annotations in org.jspecify.nullness
(JSpecify 0.2 and earlier)
2.0.0: add support for the @NonNull
annotation
2.1.0: change default mode to strict
for JSpecify annotations, converting warnings into errors; use -Xnullability-annotations=@org.jspecify.annotations:warning
or -Xnullability-annotations=@org.jspecify.annotations:ignore
to override the default behavior
Change overload resolution to prioritize extension functions over invoke calls in ambiguous cases Issue : KTLC-37
Component : Core language
Incompatible change type : behavioral
Short summary : Overload resolution now consistently prioritizes extension functions over invoke calls in ambiguous cases. This resolves inconsistencies in the resolution logic for local functions and properties. The change applies only after recompilation, without affecting precompiled binaries.
Deprecation cycle :
Prohibit returning nullable values from lambdas in SAM constructors of JDK function interfaces Issue : KTLC-42
Component : Core language
Incompatible change type : source
Short summary : Returning nullable values from lambdas in SAM constructors of JDK function interfaces now triggers a compilation error if the specified type argument is non-nullable. This resolves issues where nullability mismatches could lead to runtime exceptions, ensuring stricter type safety.
Deprecation cycle :
Correct handling of private members conflicting with public members in Kotlin/Native Issue : KTLC-43
Component : Core language
Incompatible change type : behavioral
Short summary : In Kotlin/Native, private members no longer override or conflict with public members in a superclass, aligning behavior with Kotlin/JVM. This resolves inconsistencies in override resolution and eliminates unexpected behavior caused by separate compilation.
Deprecation cycle :
Forbid access to private operator functions in public inline functions Issue : KTLC-71
Component : Core language
Incompatible change type : source
Short summary : Private operator functions such as getValue()
, setValue()
, provideDelegate()
, hasNext()
, and next()
can no longer be accessed in public inline functions.
Deprecation cycle :
Prohibit passing invalid arguments to invariant parameters annotated with @UnsafeVariance Issue : KTLC-72
Component : Core language
Incompatible change type : source
Short summary : The compiler now ignores @UnsafeVariance
annotations during type checks, enforcing stricter type safety for invariant type parameters. This prevents invalid calls that rely on @UnsafeVariance
to bypass expected type checks.
Deprecation cycle :
Report nullability errors for error-level nullable arguments of warning-level Java types Issue : KTLC-100
Component : Core language
Incompatible change type : source
Short summary : The compiler now detects nullability mismatches in Java methods where a warning-level nullable type contains type arguments with stricter, error-level nullability. This ensures that previously ignored errors in type arguments are reported correctly.
Deprecation cycle :
Report implicit usages of inaccessible types Issue : KTLC-3
Component : Core language
Incompatible change type : source
Short summary : The compiler now reports usages of inaccessible types in function literals and type arguments, preventing compilation and runtime failures caused by incomplete type information.
Deprecation cycle :
2.0.0: report warnings for function literals with parameters or receivers of inaccessible non-generic types and for types with inaccessible type argument; report errors for function literals with parameters or receivers of inaccessible generic types and for types with inaccessible generic type arguments in specific scenarios
2.1.0: raise warnings to errors for function literals with parameters and receivers of inaccessible non-generic types
2.2.0: raise warnings to errors for types with inaccessible type arguments
Standard library Deprecate locale-sensitive case conversion functions for Char and String Issue : KT-43023
Component : kotlin-stdlib
Incompatible change type : source
Short summary : Among other Kotlin standard library APIs, locale-sensitive case conversion functions for Char
and String
, such as Char.toUpperCase()
and String.toLowerCase()
, are deprecated. Replace them with locale-agnostic alternatives like String.lowercase()
or explicitly specify the locale for locale-sensitive behavior, such as String.lowercase(Locale.getDefault())
.
For a comprehensive list of deprecated Kotlin standard library APIs in Kotlin 2.1.0, see KT-71628 .
Deprecation cycle :
1.4.30: introduce locale-agnostic alternatives as experimental API
1.5.0: deprecate locale-sensitive case conversion functions with a warning
2.1.0: raise the warning to an error
Remove kotlin-stdlib-common JAR artifact Issue : KT-62159
Component : kotlin-stdlib
Incompatible change type : binary
Short summary : The kotlin-stdlib-common.jar
artifact, previously used for legacy multiplatform declarations metadata, is deprecated and replaced by .klib
files as the standard format for common multiplatform declarations metadata. This change does not affect the main kotlin-stdlib.jar
or kotlin-stdlib-all.jar
artifacts.
Deprecation cycle :
Deprecate appendln() in favor of appendLine() Issue : KTLC-27
Component : kotlin-stdlib
Incompatible change type : source
Short summary : StringBuilder.appendln()
is deprecated in favor of StringBuilder.appendLine()
.
Deprecation cycle :
Issue : KT-69545
Component : kotlin-stdlib
Incompatible change type : source
Short summary : Freezing-related APIs in Kotlin/Native, previously marked with the @FreezingIsDeprecated
annotation, are now deprecated. This aligns with the introduction of the new memory manager that removes the need for freezing objects for thread sharing. For migration details, see the Kotlin/Native migration guide .
Deprecation cycle :
Change Map.Entry behavior to fail-fast on structural modification Issue : KTLC-23
Component : kotlin-stdlib
Incompatible change type : behavioral
Short summary : Accessing a Map.Entry
key-value pair after its associated map has been structurally modified now throws a ConcurrentModificationException
.
Deprecation cycle :
Deprecate KotlinCompilationOutput#resourcesDirProvider Issue : KT-69255
Component : Gradle
Incompatible change type : source
Short summary : The KotlinCompilationOutput#resourcesDirProvider
field is deprecated. Use KotlinSourceSet.resources
in your Gradle build script instead to add additional resource directories.
Deprecation cycle :
Deprecate registerKotlinJvmCompileTask(taskName, moduleName) function Issue : KT-69927
Component : Gradle
Incompatible change type : source
Short summary : The registerKotlinJvmCompileTask(taskName, moduleName)
function is deprecated in favor of the new registerKotlinJvmCompileTask(taskName, compilerOptions, explicitApiMode)
function, which now accepts KotlinJvmCompilerOptions
. This allows you to pass a compilerOptions
instance, typically from an extension or target, with values used as conventions for the task's options.
Deprecation cycle :
Deprecate registerKaptGenerateStubsTask(taskName) function Issue : KT-70383
Component : Gradle
Incompatible change type : source
Short summary : The registerKaptGenerateStubsTask(taskName)
function is deprecated. Use the new registerKaptGenerateStubsTask(compileTask, kaptExtension, explicitApiMode)
function instead. This new version allows you to link values as conventions from the relevant KotlinJvmCompile
task, ensuring both tasks are using the same set of options.
Deprecation cycle :
Deprecate KotlinTopLevelExtension and KotlinTopLevelExtensionConfig interfaces Issue : KT-71602
Component : Gradle
Incompatible change type : behavioral
Short summary : KotlinTopLevelExtension
and KotlinTopLevelExtensionConfig
interfaces are deprecated in favor of a new KotlinTopLevelExtension
interface. This interface merges KotlinTopLevelExtensionConfig
, KotlinTopLevelExtension
, and KotlinProjectExtension
to streamline API hierarchy, and provide official access to the JVM toolchain and compiler properties.
Deprecation cycle :
Remove kotlin-compiler-embeddable from build runtime dependencies Issue : KT-61706
Component : Gradle
Incompatible change type : source
Short summary : The kotlin-compiler-embeddable
dependency is removed from the runtime in Kotlin Gradle Plugin (KGP). Required modules are now included directly in KGP artifacts, with the Kotlin language version limited to 2.0 to support compatibility with Gradle Kotlin runtime in versions below 8.2.
Deprecation cycle :
Hide compiler symbols from the Kotlin Gradle Plugin API Issue : KT-70251
Component : Gradle
Incompatible change type : source
Short summary : Compiler module symbols bundled within the Kotlin Gradle Plugin (KGP), such as KotlinCompilerVersion
, are hidden from the public API to prevent unintended access in build scripts.
Deprecation cycle :
Add support for multiple stability configuration files Issue : KT-68345
Component : Gradle
Incompatible change type : source
Short summary : The stabilityConfigurationFile
property in the Compose extension is deprecated in favor of a new stabilityConfigurationFiles
property, which allows specifying multiple configuration files.
Deprecation cycle :
Issue : KT-65565
Component : Gradle
Incompatible change type : source
Short summary : Support for these platform plugin IDs have been removed:
Deprecation cycle :
Last modified: 26 November 2024