Kotlin 1.6.20 Released
Kotlin 1.6.20 has officially been released. It offers previews of future language features, makes the hierarchical structure the default for multiplatform projects, and brings performance improvements for the JVM, JS, and Native platforms.
In this blog post, you’ll find an overview of the following improvements, along with a complete list of the other evolutionary changes:
- New support for defining context-dependent declarations in Kotlin/JVM, resulting from the prototype of context receivers.
- Better interoperability with generic Java classes and interfaces, thanks to definitely non-nullable types.
- Faster build times resulting from the parallel compilation of a single module in the JVM IR backend.
- Streamlined development experience, facilitated by incremental compilation in Kotlin/JS IR.
- Kotlin/Native performance improvements.
- Easier code sharing thanks to the hierarchical structure of multiplatform projects.
How to update
Prototype of context receivers for Kotlin/JVM
With Kotlin 1.6.20, you are no longer limited to having one receiver. If you need more, you can make functions, properties, and classes context-dependent (or contextual) by adding context receivers to their declaration. A contextual declaration does the following:
- It requires all declared context receivers to be present in a caller’s scope as implicit receivers.
- It brings declared context receivers into its body scope as implicit receivers.
To enable context receivers in your project, use the
-Xcontext-receivers compiler option. You can find a detailed description of the feature and its syntax in the KEEP.
Please note that the implementation is a prototype:
-Xcontext-receiversenabled, the compiler will produce pre-release binaries that cannot be used in production code.
- The IDE support for context receivers is minimal for now.
Definitely non-nullable types
To provide better interoperability when extending generic Java classes and interfaces, Kotlin 1.6.20 allows you to mark a generic type parameter as definitely non-nullable on the use site with the new syntax
T & Any. The syntactic form comes from a notation of intersection types and is now limited to a type parameter with nullable upper bounds on the left side of
& and non-nullable
Any on the right side:
Set the language version to 1.7 to enable the feature:
Learn more about definitely non-nullable types in the KEEP.
Please note that definitely non-nullable types are in Beta. They are almost stable, but migration steps may be required in the future. We’ll do our best to minimize any changes you have to make.
Support for parallel compilation of a single module in the JVM backend
In Kotlin 1.6.20, we added the experimental JVM IR backend mode to compile all the files in a module in parallel. Parallel compilation can reduce the total compilation time by up to 15%.
Enable the experimental parallel backend mode with the compiler option
-Xbackend-threads. Use the following arguments for this option:
Nis equal to the number of threads you want to use. It should not be greater than your number of CPU cores; otherwise, parallelization stops being effective because of switching context between threads
0to use one thread for each CPU core
Gradle can run tasks in parallel, but this type of parallelization doesn’t help a lot when a project (or a major part of a project) is just one big task from Gradle’s perspective. If you have a very big monolithic module, use parallel compilation to compile more quickly. If your project consists of lots of small modules and has a build parallelized by Gradle, adding another layer of parallelization may hurt performance because of context switching.
Parallel compilation has some constraints:
- It doesn’t work with kapt because kapt disables the IR backend.
- It requires more JVM heap by design. The amount of heap is proportional to the number of threads.
Incremental compilation for development binaries with Kotlin/JS IR compiler
To make Kotlin/JS development with the IR compiler more efficient, we’re introducing a new incremental compilation mode.
When building development binaries with the
compileDevelopmentExecutableKotlinJs Gradle task in this mode, the compiler caches the results of previous compilations on the module level. It uses the cached compilation results for unchanged source files during subsequent compilations, making them complete more quickly, especially with small changes. Note that this improvement exclusively targets the development process (shortening the edit-build-debug cycle) and doesn’t affect the building of production artifacts.
To enable incremental compilation for development binaries, add the following line to the project’s
In our test projects, the new mode made incremental compilation up to 30% faster. However, the clean build in this mode became slower because of the need to create and populate the caches.
Kotlin/Native performance improvements
Kotlin 1.6.20 brings some performance updates and bug fixes that affect the LLVM IR that Kotlin generates. According to the benchmarks on our internal projects, we achieved the following performance boosts on average:
- 15% reduction in execution time
- 20% reduction in the code size of both release and debug binaries
- 26% reduction in the compilation time of release binaries
These changes also provide a 10% reduction in compilation time for a debug binary on a large internal project.
To achieve this, we’ve implemented static initialization for some of the compiler-generated synthetic objects, improved the way we structure LLVM IR for every function, and optimized the compiler caches.
Hierarchical structure support for multiplatform projects
Kotlin 1.6.20 comes with hierarchical structure support enabled by default. Since introducing it in Kotlin 1.4.0, we’ve significantly improved the frontend and made IDE import stable.
Previously, there were two ways to add code in a multiplatform project. The first was to insert it in a platform-specific source set, which is limited to one target and can’t be reused by other platforms. The second is to use a common source set shared across all the platforms that are currently supported by Kotlin.
Now you can share source code among several similar native targets that reuse a lot of the common logic and third-party APIs. The technology will provide the correct default dependencies and find the exact API available in the shared code. This eliminates a complex build setup and having to use workarounds to get IDE support for sharing source sets among native targets. It also helps prevent unsafe API usages meant for a different target.
The technology will come in handy for library authors too, as a hierarchical project structure allows them to publish and consume libraries with common APIs for a subset of targets.
By default, libraries published with the hierarchical project structure are compatible only with hierarchical structure projects. Learn more about project-library compatibility.
Better code-sharing in your project
Without hierarchical structure support, there is no straightforward way to share code across some but not all Kotlin targets. One popular example is sharing code across all iOS targets and having access to iOS-specific dependencies, like
Thanks to the hierarchical project structure support, you can now achieve this out of the box. In the new structure, source sets form a hierarchy. You can use platform-specific language features and dependencies available for each target that a given source set compiles to.
For example, consider a typical multiplatform project with two targets —
iosX64 for iOS devices and simulators. The Kotlin tooling understands that both targets have the same function and allows you to access that function from the intermediate source set,
The Kotlin toolchain provides the correct default dependencies, like Kotlin/Native stdlib or native libraries. Moreover, Kotlin tooling will try its best to find exactly the API surface area available in the shared code. This prevents such cases as, for example, the use of a macOS-specific function in code shared for Windows.
More opportunities for library authors
When a multiplatform library is published, the API of its intermediate source sets is now properly published alongside it, making it available for consumers. Again, the Kotlin toolchain will automatically figure out the API available in the consumer source set while carefully watching out for unsafe usages, like using an API meant for the JVM in JS code. Learn more about sharing code in libraries.
Configuration and setup
Starting with Kotlin 1.6.20, all your new multiplatform projects will have a hierarchical project structure. No additional setup is required.
- If you’ve already turned it on manually, you can remove the deprecated options from
- For Kotlin 1.6.20, we recommend using Android Studio 2021.1.1 (Bumblebee) or later to get the best experience.
- You can also opt out. To disable hierarchical structure support, set the following options in
Complete list of improvements
@JvmDefaultWithCompatibilityannotation for interfaces
- Compatibility changes in the
- Support for parallel compilation of a single module in the JVM backend
- Support for callable references to function interface constructors
- An update on the new memory manager
- Concurrent implementation for the sweep phase in the new memory manager
- Instantiation of annotation classes
- Interop with Swift async/await: returning
- Better stack traces with
- Support for standalone Android executables
- Performance improvements
- Improved error handling during cinterop modules import
- Support for Xcode 13 libraries
- Incremental compilation for development binaries with IR compiler
- Lazy initialization of top-level properties by default with IR compiler
- Separate JS files for project modules by default with IR compiler
- Improvements to export and TypeScript declaration generation
@AfterTestguarantees for asynchronous tests
- Using relative paths in klibs
yarn.lockfor Kotlin/JS Gradle projects
- Installation of npm dependencies with
- Properties for defining Kotlin compiler execution strategy
- Deprecation of build options for kapt and coroutines
- Removal of the
How to install Kotlin 1.6.20
You can download the latest versions of these IDEs to get extensive support for Kotlin:
- IntelliJ IDEA – for developing Kotlin applications for various platforms.
- Android Studio – for developing Android and cross-platform mobile applications.
Make sure that you have also updated the kotlinx libraries to compatible versions and specified version 1.6.20 of Kotlin in the build scripts of your existing projects.
If you need the command-line compiler, download it from the Github release page.
If you run into any problems
Stay up to date with the latest Kotlin features! Subscribe to receive Kotlin updates by filling out the form to the right of this post.