What's new in Kotlin 2.1.20-RC3
The Kotlin 2.1.20-RC3 release is out! Here are some details of this EAP release:
Kotlin Multiplatform: new DSL to replace Gradle's Application plugin
Kotlin/Wasm: default custom formatters and migration to Provider API
Standard library: common atomic types, improved UUID support, and new time tracking functionality
IDE support
The Kotlin plugins that support 2.1.20-RC3 are bundled in the latest IntelliJ IDEA and Android Studio. You don't need to update the Kotlin plugin in your IDE. All you need to do is to change the Kotlin version to 2.1.20-RC3 in your build scripts.
See Update to a new release for details.
Kotlin K2 compiler: new default kapt plugin
Starting with Kotlin 2.1.20-RC3, the K2 implementation of the kapt compiler plugin is enabled by default for all the projects.
The JetBrains team launched the new implementation of the kapt plugin with the K2 compiler back in Kotlin 1.9.20. Since then, we have further developed the internal implementation of K2 kapt and made its behavior similar to that of the K1 version, while significantly improving its performance as well.
If you encounter any issues when using kapt with the K2 compiler, you can temporarily revert to the previous plugin implementation.
To do this, add the following option to the gradle.properties
file of your project:
Please report any issues to our issue tracker.
Kotlin Multiplatform: new DSL to replace Gradle's Application plugin
Starting with Gradle 8.7, the Application plugin is no longer compatible with the Kotlin Multiplatform Gradle plugin. Kotlin 2.1.20-RC3 introduces an Experimental DSL to achieve similar functionality. The new executable {}
block configures execution tasks and Gradle distributions for JVM targets.
Before using the DSL, add the following to your build script:
Then, add the new executable {}
block. For example:
In this example, Gradle's Distribution plugin is applied on the first executable {}
block.
If you run into any issues, report them in our issue tracker or let us know in our public Slack channel.
Kotlin/Native: new inlining optimization
Kotlin 2.1.20-RC3 introduces a new inlining optimization pass, which comes before the actual code generation phase.
The new inlining pass in the Kotlin/Native compiler should perform better than the standard LLVM inliner and improve the runtime performance of the generated code.
The new inlining pass is currently Experimental. To try it out, use the following compiler option:
Our experiments show that 40 is a good compromise threshold for the optimization. According to our benchmarks, this gives an overall performance improvement of 9.5%. Of course, you can try out other values, too.
If you experience increased binary size or compilation time, please report such issues in YouTrack.
Kotlin/Wasm
Custom formatters enabled by default
Before, you had to manually configure custom formatters to improve debugging in web browsers when working with Kotlin/Wasm code.
In this release, custom formatters are enabled by default in development builds, so no additional Gradle configuration is needed.
To use this feature, you only need to ensure that custom formatters are enabled in your browser's developer tools:
In Chrome DevTools, it's available via Settings | Preferences | Console:
In Firefox DevTools, it's available via Settings | Advanced settings:
This change primarily affects development builds. If you have specific requirements for production builds, you need to adjust your Gradle configuration accordingly. Add the following compiler option to the wasmJs {}
block:
Migration to Provider API for Kotlin/Wasm and Kotlin/JS properties
Previously, properties in Kotlin/Wasm and Kotlin/JS extensions were mutable (var
) and assigned directly in build scripts:
Now, properties are exposed through the Provider API, and you must use the .set()
function to assign values:
The Provider API ensures that values are lazily computed and properly integrated with task dependencies, improving build performance.
With this change, direct property assignments are deprecated in favor of *EnvSpec
classes, such as NodeJsEnvSpec
and YarnRootEnvSpec
.
Additionally, several alias tasks have been removed to avoid confusion:
Deprecated task | Replacement |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
If you only use Kotlin/JS or Kotlin/Wasm in build scripts, no action is required as Gradle automatically handles assignments.
However, if you maintain a plugin based on the Kotlin Gradle Plugin, and your plugin does not apply kotlin-dsl
, you must update property assignments to use the .set()
function.
Gradle
Support for version 8.11
Kotlin 2.1.20-RC3 is now compatible with the latest stable Gradle version, 8.11, and supports its features.
Kotlin Gradle plugin compatible with Gradle's Isolated Projects
Since Kotlin 2.1.0, you've been able to preview Gradle's Isolated Projects feature in your projects.
Previously, you had to configure the Kotlin Gradle plugin to make your project compatible with the Isolated Projects feature before you could try it out. In Kotlin 2.1.20-RC3, this additional step is no longer necessary.
Now, to enable the Isolated Projects feature, you only need to set the system property.
Gradle’s Isolated Projects feature is supported in Kotlin Gradle plugins for both multiplatform projects and projects that contain only the JVM or Android target.
Specifically for multiplatform projects, if you notice problems with your Gradle build after upgrading, you can opt out of the new Kotlin Gradle plugin behavior by setting:
However, if you use this Gradle property in your multiplatform project, you can't use the Isolated Projects feature.
We would appreciate your feedback on this feature in YouTrack.
Support for adding custom Gradle publication variants
Kotlin 2.1.20-RC3 introduces support for adding custom Gradle publication variants. This feature is available for multiplatform projects and projects targeting the JVM.
This feature is Experimental. To opt in, use the @OptIn(ExperimentalKotlinGradlePluginApi::class)
annotation.
To add a custom Gradle publication variant, invoke the adhocSoftwareComponent()
function, which returns an instance of AdhocComponentWithVariants
that you can configure in the Kotlin DSL:
Standard library
Common atomic types
In Kotlin 2.1.20-RC3, we are introducing common atomic types in the standard library's kotlin.concurrent.atomics
package, enabling shared, platform-independent code for thread-safe operations. This simplifies development for Kotlin Multiplatform projects by removing the need to duplicate atomic-dependent logic across source sets.
The kotlin.concurrent.atomics
package and its properties are Experimental. To opt in, use the @OptIn(ExperimentalAtomicApi::class)
annotation or the compiler option -opt-in=kotlin.ExperimentalAtomicApi
.
Here's an example that shows how you can use AtomicInt
to safely count processed items across multiple threads:
To enable seamless interoperability between Kotlin's atomic types and Java's java.util.concurrent.atomic
atomic types, the API provides the .asJavaAtomic()
and .asKotlinAtomic()
extension functions. On the JVM, Kotlin atomics and Java atomics are the same types in runtime, so you can transform Java atomics into Kotlin atomics and vice versa without any overhead.
Here's an example that shows how Kotlin and Java atomic types can work together:
Changes in UUID parsing, formatting, and comparability
The JetBrains team continues to improve the support for UUIDs introduced to the standard library in 2.0.20.
Previously, the parse()
function only accepted UUIDs in the hex-and-dash format. With Kotlin 2.1.20-RC3, you can use parse()
for both the hex-and-dash and the plain hexadecimal (without dashes) formats.
We've also introduced functions specific to operations with the hex-and-dash format in this release:
parseHexDash()
parses UUIDs from the hex-and-dash format.toHexDashString()
converts aUuid
into aString
in the hex-and-dash format (mirroring the functionality oftoString()
).
These functions work similarly to parseHex()
and toHexString()
, which were introduced earlier for the hexadecimal format. Explicit naming for parsing and formatting functionality should improve code clarity and your overall experience with UUIDs.
UUIDs in Kotlin are now Comparable
. Starting with Kotlin 2.1.20-RC3, you can directly compare and sort values of the Uuid
type. This enables the use of the <
and >
operators, standard library extensions available exclusively for Comparable
types or their collections (such as sorted()
), and allows passing UUIDs to any functions or APIs that require the Comparable
interface.
Remember that the UUID support in the standard library is still Experimental. To opt in, use the @OptIn(ExperimentalUuidApi::class)
annotation or the compiler option -opt-in=kotlin.uuid.ExperimentalUuidApi
:
New time tracking functionality
Starting with Kotlin 2.1.20-RC3, the standard library provides the ability to represent a moment in time. This functionality was previously only available in kotlinx-datetime
, an official Kotlin library.
The kotlinx.datetime.Clock interface is introduced to the standard library as kotlin.time.Clock
and the kotlinx.datetime.Instant
class as kotlin.time.Instant
. These concepts naturally align with the time
package in the standard library because they’re only concerned with moments in time compared to a more complex calendar and timezone functionality that remains in kotlinx-datetime
.
Instant
and Clock
are useful when you need precise time tracking without considering time zones or dates. For example, you can use them to log events with timestamps, measure durations between two points in time, and obtain the current moment for system processes.
To provide interoperability with other languages, additional converter functions are available:
.toKotlinInstant()
converts a time value to akotlin.time.Instant
instance..toJavaInstant()
converts thekotlin.time.Instant
value to ajava.time.Instant
value.Instant.toJSDate()
converts thekotlin.time.Instant
value to an instance of the JSDate
class. This conversion is not precise, JS uses millisecond precision to represent dates, while Kotlin allows for nanosecond resolution.
The new time features of the standard library are still Experimental. To opt in, use the @OptIn(ExperimentalTime::class)
annotation:
For more information on the implementation, see this KEEP proposal.
Compose compiler: source information included by default
The Compose compiler Gradle plugin enables including source information by default on all platforms. The includeSourceInformation
option was already enabled for Android, this change aligns the plugin behavior across platforms and allows support for new runtime features.
Remember to check if you set this option using freeCompilerArgs
: when used along with the plugin, it can fail the build due to an option being set twice.
Breaking changes and deprecations
To align Kotlin Multiplatform with upcoming changes in Gradle, we are phasing out the withJava()
function. Java source sets are now created by default.
How to update to Kotlin 2.1.20-RC3
Starting from IntelliJ IDEA 2023.3 and Android Studio Iguana (2023.2.1) Canary 15, the Kotlin plugin is distributed as a bundled plugin included in your IDE. This means that you can't install the plugin from JetBrains Marketplace anymore. The bundled plugin supports upcoming Kotlin EAP releases.
To update to the new Kotlin EAP version, change the Kotlin version to 2.1.20-RC3 in your build scripts.