Kotlin 1.3 RC is Here: Migrate Your Coroutines!

Posted on by

We’re proud to introduce Kotlin 1.3-RC, the latest preview and release candidate for 1.3.0. This release mostly contains critical bug-fixes related to the new language features. Other notable changes and announcements include:

Ktor is wrapping up its API and looking forward to your feedback. Ktor is a framework for building web applications, HTTP services, mobile and browser applications. It’s elegant, asynchronous and built on coroutines.

The official code style is now used for all new projects. We also encourage you to migrate old projects to the official style.

The main entrypoint can now take no parameters and also can be a suspending function.

entrypoint can now take no parameters and also can be a suspending function. Experimental support for scripting introduced in version 1.2.50 has been reworked and improved.

An experimental kotlinx.serialization plugin has been merged to the main Kotlin project. Now it’s a bundled compiler plugin.

plugin has been merged to the main Kotlin project. Now it’s a bundled compiler plugin. There are new deprecations in the standard library, as well as errors for some old deprecations.

Annotations in the org.jetbrains.annotations package were extracted from the standard library to separate artifacts.

We’d like to thank our external contributors whose commits were included in this release: Toshiaki Kameyama, Cuihtlauac ALVARADO, kenji tomita, Martin Petrov, Denis Vnukov, shiraji, Paul de Vrieze, Raluca Sauciuc, and Ivan Gavrilovic.

The complete list of changes in this release can be found in the changelog.

We appreciate your feedback regarding the new features or any problems that you may run into with the release candidate. The final release of Kotlin 1.3.0 is just around the corner, so now might be the best time ever to provide feedback.

KotlinConf 2018 Online

The main Kotlin event, KotlinConf, is almost here! For those who can’t make it to the conference this year, we’ll be live-streaming the keynotes, closing panel, and the entire track over the 2 main conference days. Sign up to get notified once we go live!

Time to migrate your coroutines

Kotlin 1.3 graduates coroutines to the stable status. It’s a good time to migrate libraries using old experimental coroutines now to get them ready by the time 1.3.0 is out. Our tooling will help you migrate your code.

The migration path for users of experimental kotlinx.coroutines library is the following. You will need to update your code to the latest experimental version of the library which is 0.26.1 at the moment and may receive a few minor updates before Kotlin 1.3 release. Then you can change your project to Kotlin 1.3 and IDE tooling will help you to migrate to 0.26.1-eap13 version that is built for Kotlin 1.3. This migration is mechanical and consists of dropping experimental from the package names. The kotlinx.coroutines version 1.0.0 will be released together with Kotlin 1.3 release and you’ll only need to change the version to 1.0 and recompile your code. Note, that release of kotlinx.coroutines will drop all the deprecated declarations from experimental 0.x releases and will not be binary compatible with 0.x-eap13 releases, so you’ll need to cleanup your source code from uses of deprecated APIs by following the corresponding replacements while your project is still on the latest 0.x version. Some APIs in kotlinx.coroutines will be marked as unstable to be stabilized in later update. An opt-in flag to use unstable APIs will be required, but all the core APIs that you need to launch and work with coroutines will be finalized in 1.0 and will be maintained in a backward compatible way to the same standards as the Kotlin standard library.

Main without parameters

Following the experience of many other successful programming languages, we’re making the string array parameter of the main function optional in 1.3. This means that the idiomatic “Hello, World!” program in Kotlin is now as short as:

fun main() { println("Hello, World!") }

Suspend fun main

Now, the entrypoint can be not only parameterless but also a suspending function. This means you can call any other suspending API from main without the need to wrap everything in runBlocking :

import kotlinx.coroutines.* //sampleStart suspend fun main() = coroutineScope { val task1 = async { fetchResult(id = 42) } val task2 = async { fetchResult(id = 99) } val results = awaitAll(task1, task2) log(results) } //sampleEnd suspend fun fetchResult(id: Int): String { log("started request #$id") delay(500) return "result #$id" } val startedAt = System.currentTimeMillis() fun elapsed() = System.currentTimeMillis() - startedAt fun log(message: Any) = println("At ${elapsed()} ms: $message")

Ktor framework

As Kotlin coroutines are finally graduating from experimental status, this makes it possible to release our asynchronous libraries without fear of future incompatibilities. We’ve been preparing a lot of useful stuff for you, one of the biggest being Ktor – an asynchronous framework for connected applications. It features a mutliplatform HTTP client and a JVM-based HTTP server.

The client is currently available for JVM/Android and iOS; the plan is to extend support to other platforms including JS (browser) and various native platforms. The server runs on the JVM and can use Netty, Jetty, or any servlet engine such as Tomcat.

The Ktor framework is easy to use, well-tested, and highly performant, it starts up instantly, and everything is container-friendly. Extensive documentation is available at https://ktor.io/. You can try it today using version 0.9.5-rc13 compatible with Kotlin 1.3-RC, or version 0.9.5 compatible with Kotlin 1.2.70 if you’re not ready for the newest bits yet.

Join us and help us shape the asynchronous future where we can all write code that’s easy to understand and maintain!

Code style

It’s been a while since we introduced the official coding conventions guide, and now it’s time to move forward. Starting with Kotlin 1.3, all new projects created in IntelliJ IDEA will use the code style settings to comply with the official coding conventions.

While we recommend sharing the .idea/codeStyles directory via VCS, some people don’t like to do it, so we’ve introduced a Gradle property, kotlin.code.style , for setting up the project default, official or obsolete , during the IDE import. It also makes the style available to other IDEs.

Even if you want to keep the old code style, please specify the kotlin.code.style=obsolete setting in your project in order to avoid accidental migration in future releases of Kotlin. The same property is available in Maven.

Scripting

This release brings many changes to the experimental scripting support.

The most important part is the significantly reworked API. We’ve attempted to make it even simpler and cleaner. Although the scripting will remain in the experimental state a while longer, the API in its current form is how we believe it should generally look like.

The unused and not yet implemented parts and features are removed from the API as well. We intend to add many of them back along with the proper implementations in the next releases.

There is a new public artifact: kotlin-main-kts . It contains a script definition and a minimal maven artifacts resolver in a single jar. Its purpose is to simplify the creation and usage of the simple utility scripts that may depend on the external libraries. For example, you can now write the following script:

@file:Repository("https://jcenter.bintray.com") @file:DependsOn("org.jetbrains.kotlinx:kotlinx-html-jvm:0.6.11") import kotlinx.html.* import kotlinx.html.stream.* print(createHTML().html { body { h1 { +"Hello, World!" } } })

Then run it with only kotlin-main-kts.jar in the classpath:

kotlinc -cp <path/to/kotlin-main-kts.jar> -script sample.main.kts

There are many other fixes and improvements related to scripting support in this release. We encourage you to check the examples, try it out, and give us your feedback.

The complete Kotlin scripting proposal along with the current implementation state can be found in the appropriate KEEP-75.

Experimental serialization plugin

Starting with this release, the compiler plugin for kotlinx.serialization is now bundled into the Kotlin compiler. This will improve the stability and make the behavior consistent for all of the platforms the plugin supports.

The serialization compiler plugin remains experimental in Kotlin 1.3, but it’s mature enough to be used in real projects, and we’re in need of your feedback. We’ve created a public proposal that describes the architecture of the plugin — please take a look at KEEP-149 and share your comments/suggestions in the issue.

Inline classes

We have changed the binary representation of inline classes to make it more compact and future-proof, and fixed several remaining critical issues.

Kotlin reflection now handles inline class types in the signature correctly and calls box / unbox methods automatically under the hood.

Standard library

This milestone is more focused on cleanup before release rather than on new features.

hashCode() for nullable types

When implementing generic containers, a common task is to get a hash code of a generic element with unconstrained nullability. Since that element could be null, a safe call and an elvis operator with default were required before: element?.hashCode() ?: 0 .

We’re now introducing the function Any?.hashCode() , which realizes this common pattern. As a result, the above expression simplifies to just element.hashCode() .

Checking for a nullable element in an iterable range

An innocent looking range-check expression value in from..to could be dramatically slow if the value was nullable and the range from..to was iterable and large. In such a case, the overload Iterable<T>.contains(T) was selected for this operation, which resulted in the range being iterated until the value was found (or determined to be absent).

We’ve now introduced a number of contains overloads like IntRange.contains(element: Int?) , which check their argument for null and then execute a fast path ‘contains’ check.

SuccessOrFailure is renamed to Result

The class that encapsulates either a successful or a failed result of Kotlin function, which was released in preview builds of Kotlin 1.3 under the working name of SuccessOrFailure , after review and community feedback had been renamed to Result . This class is primarily used in coroutines as an argument type of Continuation.resumeWith function. There is a number of design leads for potential future extensions of error handing in Kotlin that would require us to redesign semantics of the code that uses this Result class as a return type, so, to avoid breaking such code in the future, Kotlin 1.3 compiler produces an error on such declarations with a few exceptions of standard library functions that are specifically designed to operate on Result type. See KEEP-127 for details.

Sequence and iterator builder functions and their scope class

Before the coroutines’ API is finalized in the standard library, we’d like to rename the buildSequence and buildIterator functions.

The current names were chosen to be consistent with the buildString function and the proposed builder functions for basic collections. However, recently we realized that the sequence and string builder functions are very different in terms of their laziness, and that consistency is actually something unwanted.

Sequence builders were renamed from buildSequence { } and buildIterator { } to just sequence { } and iterator { } . The receiver type of the function that is passed to the builder is now SequenceScope instead of SequenceBuilder .

As a result, code with sequence builders now looks as follows:

import kotlinx.coroutines.* //sampleStart fun idCandidates(baseId: String): Sequence<String> = sequence { yield(baseId) for (suffix in 'a'..'z') { yield(baseId + "-" + suffix) } } //sampleEnd fun main() { idCandidates("base-id").take(10).forEach(::println) }

Widening conversions from signed to unsigned integers are sign extending now

We’re changing how widening conversions work when converting singed integers to wider unsigned ones, to make it more consistent with other languages that support unsigned types.

The Int.toULong() function and the similar ones now perform sign extension instead of zero extension, so (-1).toULong() is equal to ULong.MAX_VALUE ( 0xFFFF_FFFF_FFFF_FFFF ) rather than UInt.MAX_VALUE ( 0x0000_0000_FFFF_FFFF ).

Mutability annotations in a separate artifact

The standard library artifact that is distributed with the compiler has been exempted from the annotations in org.jetbrains.annotations package to match the standard library artifact that is distributed to Maven Central. These annotations can now be found in annotations-13.0.jar and mutability-annotations-compat.jar in the compiler distribution.

Deprecating mixed integer/floating point contains operator for ranges

Earlier we mentioned the problematic ‘contains’ check of a nullable element. Another problem arose when the range was made of integer bounds and the argument was floating point, or vice versa.

The check 3.14 in 1..3 worked, but produced a counter-intuitive outcome: it resulted in true . We’ve deprecated such contains operator overloads and are going to remove them from future versions of Kotlin.

Other deprecation notices

We’re continuing the deprecation cycle and raising the deprecation level of the previously deprecated APIs. Now, usages of such APIs lead to an error rather than a warning.

In this version, the aforementioned deprecated APIs are from the standard library for JS:

jsClass functions

functions kotlin.Synchronized and Volatile annotations

and annotations kotlin.js.Math functions

functions org.junit.Test annotation in kotlin-test-js

If these names don’t look familiar to you, have no worries. If they do, please migrate their usages according to the proposed replacements.

In the next release, 1.4, we’re going to remove jQuery typed declarations from the standard library for JS. Please migrate to the external declarations from the package https://bintray.com/kotlin/js-externals/kotlin-js-jquery.

Command-line compiler

This release adds an alternative way to pass compiler arguments in a file. Instead of the -Xargfile=filename.txt form introduced in Kotlin 1.2.50, you can now pass @filename.txt as an argument to kotlinc , and it will interpret the file content as the arguments, one per line. This allows using kotlinc to compile large numbers of source files or source files with long paths.

One more experimental feature graduated in this release is the progressive compiler mode (introduced in 1.2.50 as well), now available via the -progressive flag.

How to try it

In Maven/Gradle: Add https://dl.bintray.com/kotlin/kotlin-eap as a repository for the build script and your projects. Use 1.3.0-rc-57 as the version number for the compiler plugin and the standard library.

In IntelliJ IDEA: Go to Tools → Kotlin → Configure Kotlin Plugin Updates, select “Early Access Preview 1.3” in the Update channel drop-down list, and then click Check for updates.

The command-line compiler can be downloaded from the Github release page.

On try.kotlinlang.org: Use the drop-down list in the bottom right-hand corner to change the compiler version to 1.3‑RC.