What's new in Kotlin 2.5.0-Beta2
The Kotlin 2.5.0-Beta2 release is out! Here are some details of this EAP release:
Standard library: New experimental functions for simplifying common patterns with
ifexpressions and experimental support for Unicode code points.Kotlin/JVM: Support for Java 28.
Kotlin/Native: Incremental compilation enabled by default on Apple targets and Swift export in Beta with a new DSL.
Kotlin Multiplatform: New experimental compilation scheme for Kotlin Multiplatform and new publication format for multiplatform libraries.
Kotlin/JS: Support for the
es2020target.Kotlin compiler: More consistent inline function behavior during
klibcompilation.
Update to Kotlin 2.5.0-Beta2
The latest version of Kotlin is included in the latest versions of IntelliJ IDEA and Android Studio.
To update to the new Kotlin version, make sure your IDE is updated to the latest version and change the Kotlin version to 2.5.0-Beta2 in your build scripts.
Language
Kotlin 2.5.0-Beta2 stabilizes multiple language features introduced in earlier releases. It also introduces experimental companion extensions and blocks, and full value classes.
Stable language features
Kotlin 2.3.0−2.4.0 introduced a few language features as Experimental. We're happy to announce that the following language features are now Stable in this release:
The
@IntroducedAtannotation to generate version-based overloads for optional parameters.The unused return value checker, which is now enabled by default.
Name-based destructuring in
only-syntaxmode, which is now the default.In this mode, the "old" destructuring syntax
val (x, y)keeps its position-based behavior, while the "new" syntax(val x, val y)performs name-based destructuring. You can find an overview of the feature in this video:
Companion extensions and blocks
Kotlin 2.5.0-Beta2 introduces companion extensions and companion blocks.
Previously, to declare extensions, functions, and properties that you could access through a type's name, the type needed to have a companion object. Companion extensions and blocks remove this requirement and let you:
Declare a companion extension by adding the
companionmodifier to a top-level extension, even if the type it extends has no companion object.Declare functions and properties in a
companion {}block inside a class or interface without creating an object instance. On platforms that support static members, the compiler generates these declarations as static members. As a result, you don't need to annotate them with@JvmStaticon the JVM.
Here's an example that declares UnitX as a companion extension and Zero in a companion block:
For more information about the design, see the feature's KEEP. You can also read about the feature in our blog post.
Companion extensions and blocks are Experimental. To opt in, add the following compiler option to your build file:
We would appreciate your feedback in YouTrack.
Full value classes
Before Kotlin 2.5.0-Beta2, inline value classes let you create a custom wrapper type around a single value. If your type needed multiple properties, you had to use a regular class or data class. But for these classes, two instances that contain the same data can still be distinguished by their references, even when that distinction has no meaning for the type. This can limit runtime optimizations and allow code to depend unnecessarily on whether the same object reference is preserved.
Kotlin 2.5.0-Beta2 introduces experimental full value classes that let you define types where the properties together make up the value and the identity of individual instances doesn't matter. For example, you can declare a full value class Complex to represent a complex number with real and imaginary properties:
The compiler automatically generates equals(), hashCode(), and toString() functions for full value classes, similar to data classes. However, there:
are no
componentN()functions. Instead, you can use name-based destructuring. You don't need to opt in.is no
copy()function. In the future, you can usecopy varsinstead. For more information, see KT-44653.
For more information about the differences compared to data classes, see the KEEP's section about inheritance.
Abstract value classes
Full value classes can be abstract. Unlike interfaces, they can define initialization logic that every subclass runs during construction.
For example, the OrderedInterval value class accepts start and end as constructor parameters. The IntInterval value class stores the values in its start and end properties.
For more information, see the KEEP's section about inheritance.
Value objects
Full value classes can have no properties. These are called value objects and are useful for representing types with only one possible value without an identity, such as states or tokens. For example:
For more information, see the KEEP's section about value objects.
How to enable
This feature is Experimental. To opt in, add the following compiler option to your build file:
Changes to inline value class declarations
With these new value classes, value class no longer necessarily means inline. Inline value classes have an externally observable inline representation, while other value classes don't expose their runtime representation in the same way. This distinction matters for Spring and serialization libraries, which handle inline value classes differently.
To make the distinction explicit, in the future, the compiler will require inline value classes to be declared explicitly through the inline modifier and @JvmInline value class declarations. A plain value class declaration will no longer be treated as inline.
We plan a staged migration to change this behavior:
Kotlin 2.5.20 will report a warning for unmarked single-field value classes.
Kotlin 2.6.0 or 2.7.0 will raise this warning to an error.
You can use the -Xinline-value-class-migration=warning and -Xinline-value-class-migration=strict compiler options to prepare your code for this change.
For more information, see the KEEP.
Prepare your library's classes for migration to value classes
As a library author, you can use the @WillBecomeValue annotation to prepare your library's regular classes for a future migration to full value classes. The compiler warns users when their code relies on object identity, for example through reference equality (===), synchronization, or identity hash codes. These warnings give users time to update their code before you migrate the classes.
The annotation is Experimental and requires you to opt in with @OptIn(ExperimentalValueClassApi::class). Your library's users don't need this opt-in to use the annotated classes.
For more information, see the KEEP.
Improved checks for equality comparisons on structural classes
Kotlin 2.5.0-Beta2 introduces additional analysis of equality comparisons involving data classes, data objects, final value classes, and enum classes, collectively referred to as structural classes.
The compiler uses strict equality checks for these classes to report comparisons that always return false with == or true with !=, based on the known types of the operands. These checks help catch mistakes such as comparing a vector with a point, even when both classes have the same properties:
The compiler can also use equality checks to smart-cast the right-hand operand.
To enable this feature, add the following compiler option to your build file:
For more information, see the feature's KEEP.
Standard library
In this release, the Kotlin standard library has new experimental functions to simplify your if expressions and experimental support for Unicode code points.
New functions for simplifying common patterns with if expressions
Kotlin 2.5.0-Beta2 introduces new standard library functions that let you inspect a Boolean value before returning it or return a nullable result depending on that value.
Previously, these patterns required explicit if expressions with else branches. You can now simplify them with the following functions:
onTrue()runs a specified code block when aBooleanvalue istrueand returns the original Boolean value.onFalse()runs a specified code block when aBooleanvalue isfalseand returns the original Boolean value.ifOrNull()runs a specified code block and returns its result if theBooleanvalue istrue. If the value isfalse, the function returnsnullwithout running the block.
These functions are Experimental and require opt-in with the @OptIn(ExperimentalStdlibApi::class) annotation or the -opt-in=kotlin.ExperimentalStdlibApi compiler option.
Here's an example:
We would appreciate your feedback in YouTrack.
Support for Unicode code points
Kotlin 2.5.0-Beta2 introduces the CodePoint inline value class and the related APIs in the kotlin.text.unicode package. This allows you to work with Unicode code points across platforms.
A Char represents one UTF-16 code unit. However, some Unicode code points require two Char values, known as a surrogate pair. When a program iterates over a string as Char values, it processes each half of a surrogate pair as a separate element.
The CodePoint value class represents a Unicode code point and uses Int as its underlying type to store its integer value. It provides access to properties such as the number of UTF-16 code units needed to represent it, its Unicode category, and whether it is a letter, digit, or whitespace.
The new APIs let you count and iterate over code points, convert their case, and append, insert, replace, or delete them in text. You can also compare code points, perform arithmetic, create ranges, and traverse text in both directions. The text APIs continue to use UTF-16 code-unit offsets for positions.
These APIs are Experimental and require opt-in with the @OptIn(ExperimentalUnicodeApi::class) annotation or the -opt-in=kotlin.text.unicode.ExperimentalUnicodeApi compiler option.
For more information, see the feature's KEEP.
Kotlin/JVM
Starting with Kotlin 2.5.0-Beta2, the compiler can generate classes containing Java 28 bytecode.
Kotlin/Native
Kotlin 2.5.0-Beta2 enables incremental compilation by default on Apple targets and promotes Swift export to Beta with a new Gradle DSL.
Incremental compilation enabled by default on Apple targets
Starting with Kotlin 2.5.0-Beta2, incremental compilation of klib artifacts is enabled by default on Apple targets.
With incremental compilation, if only a part of the klib artifact produced by the project module changes, only the affected part of the klib is further recompiled into a binary.
This optimization was first introduced in Kotlin 1.9.20 and has proven to drastically reduce compilation time for debug builds in certain cases.
The new default is only relevant to Apple targets. Incremental compilation is not supported on Windows (MinGW toolchain). And for Linux, it's still required to opt in with:
Note that in some cases, this optimization may come with a performance cost for clean builds. To work around that, you can try the new binary option designed to run a special compilation mode on clean builds. The option is Experimental, opt in with:
If you face unexpected problems with incremental compilation, you can disable it manually by setting the following option in your gradle.properties file:
Please report any problems in YouTrack.
For more tips on improving compilation time, see our documentation.
Swift export goes Beta with a new Gradle DSL
In Kotlin 2.5.0-Beta2, Swift export graduates to Beta and receives a more ergonomic Gradle DSL. The new DSL reduces duplication and increases configuration reuse, making it easier to expose your Kotlin code to Swift.
The main changes are:
Feature | Before | After |
|---|---|---|
Entry point |
|
|
Collapse rule property |
|
|
Exporting declared dependencies |
| Exported automatically; no explicit |
Overriding dependency configuration |
|
|
Compiler arguments |
| Removed |
Here's a complete build configuration that uses the new Swift export DSL:
In addition, Swift export configuration is now publishable: if a library author provides option overrides, Gradle automatically consumes and applies them during Swift export.
If you run into any issues, report them in YouTrack or get an invite and join the #swift-export Slack channel.
Kotlin Multiplatform
Kotlin 2.5.0-Beta2 introduces a new experimental compilation scheme for Kotlin Multiplatform and a new publication format that significantly decreases the size of published multiplatform libraries.
New experimental compilation scheme for Kotlin Multiplatform
Kotlin 2.5.0-Beta2 introduces a new experimental compilation scheme for Kotlin Multiplatform (KMP) that makes the compiler handle common source sets more consistently with the IDE. This change prevents common code from accidentally resolving to platform-specific declarations, improves consistency in overload resolution and type inference, and enables us to implement incremental compilation for common source sets. Learn more about KMP separate compilation and how to try it in our blog post.
New publication format for Kotlin Multiplatform libraries
Kotlin 2.5.0-Beta2 introduces a new publication format for Kotlin Multiplatform libraries that significantly decreases the size of a published library. The new format publishes platform artifacts (except for JVM and Android) as a single .kar archive, which is a ZIP archive additionally compressed with XZ.
This change addresses the publication size limits recently introduced to Maven Central. With the new format, adding a new target no longer creates new files, so the publication size doesn't increase that much. In some cases, the total publication is even smaller than a single-target one before. For example, for the cryptography-kotlin library, the published artifact set went from 7539 files and 91 MB to 1036 files and 23 MB for the whole multi-module project.
To enable the new format for a specific module, configure it in the module's build script:
Alternatively, to enable it for all modules in your project, add the following property to your gradle.properties file:
While publishing in the new format is still Experimental, consumption of such artifacts is already available for all projects. This change is relevant to library authors only and doesn't affect developers of final applications.
Please share your feedback and report any problems in YouTrack.
Kotlin/JS
Kotlin 2.5.0-Beta2 adds the es2020 target to the Kotlin/JS compiler and Gradle plugin. Previously, only the es5 and es2015 targets were available, and support for newer JavaScript features, such as BigInt, had to be enabled separately targeting ES2015. By targeting ES2020, you can use all supported JavaScript features up to ECMAScript 2020, including BigInt, without additional configuration.
To enable the new target, set target to es2020 in the compilerOptions {} block:
Kotlin compiler
Kotlin 2.5.0-Beta2 brings more improvements to function inlining during klib compilation and improves type inference performance.
Consistent cross-module function inlining during klib compilation
Kotlin 2.4.0 enabled consistent intra-module function inlining on Kotlin/Native, Kotlin/JS, and Kotlin/Wasm during klib compilation. The consistency of function inlining across different Kotlin platforms makes it easier to provide compatibility guarantees.
Kotlin 2.4.0 also introduced the possibility to enable cross-module inlining during klib compilation, ensuring that all inline functions in a project are consistently inlined. Kotlin 2.5.0-Beta2 enables cross-module inlining by default.
If you face unexpected problems with this feature, you can disable it with the following command-line compiler option:
Please share your feedback and report any problems in YouTrack.
Improved type inference performance
Kotlin 2.5.0-Beta2 improves compiler performance by reducing the number of constraints generated during type inference. Previously, complex generic code could generate excessive constraints, causing compilation or IDE analysis to hang. This change may affect type inference in certain edge cases, particularly those involving builder inference or complex platform types with unusual bounds. As a result, the compiler may infer different types, select different overloads, or report different diagnostics. These differences can be an expected result of the improvement.
The functionality is enabled by default. To restore the previous type inference behavior, use the -XXLanguage:-EliminateSecondKindIncorporation option.
We would appreciate your feedback in YouTrack.
Breaking changes and deprecations
Kotlin 2.5.0-Beta2 introduces an error as the next step to raising the minimum JDK version required to run the Kotlin compiler from JDK 8 to JDK 17. We're raising the minimum required JDK to speed up development and give the compiler access to new libraries that require newer Java versions. JDK 17 has a long support window and helps us maintain compatibility with newer versions of Gradle and Maven. Opt out of the error with the -Xallow-pre-17-runtime-jdk compiler option. This option will be removed in Kotlin 2.5.20 or 2.6.0 when JDK 17 becomes mandatory.
If you have difficulty upgrading your project, share your experience on YouTrack or reach out directly to developers on Kotlin Slack. Get an invite and join the #compiler channel.