Kotlin 1.3.50 released

We’re happy to announce the release of Kotlin 1.3.50 today. In addition to the quality and tooling improvements, the main focus for this version has been on:

  • Designing a new Duration and Time Measurement API (available for preview).
  • Working on an improved Java-to-Kotlin converter.
  • Experimental generation of external declarations for npm dependencies in Gradle Kotlin/JS projects (using Dukat).
  • A separate plugin for debugging Kotlin/Native code in IntelliJ IDEA Ultimate.
  • Java compilation support in multiplatform projects.

You can find the complete list of changes in the change log. As always, we’d like to thank our external contributors. Now let’s dive into the details!

Null-check optimizations planned for Kotlin 1.4

As you probably know, Kotlin decreases the possibility of NullPointerExceptions by providing support for nullable types. However, because of interoperability with Java code, it’s impossible to avoid NPEs completely. To help developers better understand the source of a nullability problem if it occurs, Kotlin compiler throws different types of runtime exceptions with clear error messages instead of pure NPEs. It turned out that this approach has its disadvantages: it reduces possible null check optimizations that can be performed either by the Kotlin compiler or by various kinds of bytecode processing tools, such as the Android R8 optimizer.

To solve this, starting from Kotlin 1.4, all runtime null checks will throw a java.lang.NullPointerException instead of a KotlinNullPointerException, IllegalStateException, IllegalArgumentException, and TypeCastException. This applies to: the !! operator, parameter null checks in the method preamble, platform-typed expression null checks, and the as operator with a non-null type. This doesn’t apply to lateinit null checks and explicit library function calls like checkNotNull or requireNotNull.

Note that from a developer’s perspective, things won’t change that much: the Kotlin code will throw exceptions with the same error messages as before. The type of exception changes, but the information passed stays the same. For instance, the following code currently throws an IllegalStateException with the error message “JavaCode.getNull() must not be null”:

Right before the duplicate function call at line 1, a special check is generated which throws this exception if the expression JavaCode.getNull() stores null. Starting with Kotlin 1.4, this code will throw a NullPointerException instead with the same message, “JavaCode.getNull() must not be null”.

After this change of behavior, the optimizers will be able to decrease the total number of null-checks present in the bytecode by removing repetitive null-checks when possible: since all checks throw the same NPE exception, only one can remain. During such optimizations, the specific helpful messages of NPEs can be lost, but that’s the price to be paid for the gained performance benefits. Note that these optimizations are still to be implemented in the corresponding tools, and when implemented, there will be more details about that, but the change of the exception type makes it possible in the future.

Standard library changes

Note that all new functions are added to the standard library in the “experimental” state.

Duration and time measurement API

A new duration and time measurement API is available for preview. Duration can be measured in a variety of units: seconds, milliseconds, nanoseconds, etc. The confusion between different units is a known source of bugs: if the API expects the duration stored as primitive value like Long, one can erroneously pass the value in the wrong unit, and unfortunately the type system doesn’t help prevent that. Creating a regular class to store duration solves this problem, but brings another one: additional allocations.

Inline classes provide a very elegant solution to that: they bring both type system guarantees and an allocation-free approach. Now the API can use the Duration type, and all the clients will need to specify the time in the desired units explicitly. Since Duration is declared as an inline class, no extra allocations are happening under the hood:

This release brings support for MonoClock which represents the monotonic clock. The recommended approach to measuring time duration from a given point in your program is to use the monotonic clock, which doesn’t depend on the system time. System time might be changed outside, and that might lead to erroneous behavior. The monotonic clock can only measure time difference between given time points, but doesn’t know the “current time.”

The Clock interface provides a general API for measuring time intervals. MonoClock is an object implementing Clock; it provides the default source of monotonic time on different platforms.

When using the Clock interface, you explicitly mark the time of action start, and later the time elapsed from the start point. It is especially convenient if you want to start and finish measuring time from different functions:

The measureTimedValue function allows you to measure the duration of a given action and get its result together with the duration of the elapsed time interval. It measures the elapsed time with MonoClock.

For more details about the implementation of the Duration class and the details of the Clock interface and MonoClock implementations for different platforms, please refer to the corresponding KEEP. Note that this API is experimental and is subject to change based on your feedback. You will need to explicitly give your consent to use it by applying the corresponding annotations.

We’re looking forward to your feedback!

Functions for bit manipulation

The standard library now contains an API for bit manipulation (as usual, in the experimental state initially):

Note that similar extension functions for Int, Long, Short, Byte, and their unsigned counterparts have been added.

IntelliJ IDEA support

Improved Java to Kotlin converter

We plan to improve the Java-to-Kotlin converter to minimize the amount of “red code” one has to fix manually after the conversion. As the current converter almost always generates non-nullable types, you need to fix the nullability issues by hand afterward. It can often lead to runtime errors from nullability mismatch later.

The new, improved version of the Java-to-Kotlin converter tries to infer nullability more correctly based on the Java type usages in the code. Note that there’s no goal to produce 100% error-free code. The goal is to decrease the number of compilation errors and to make the produced Kotlin code more convenient to work with. The new converter fixes many other known bugs, too; for instance, it now correctly handles implicit Java type casts.

In the future, the new converter is going to become the default one. In this release, it’s available for preview. To turn it on, specify the Use New J2K (experimental) flag in settings.

Please give it a try and share your feedback with us!

Debugging improvements

We’ve improved how the Kotlin “Variables” view chooses the variables to display. As there’s a lot of additional technical information in the bytecode, the Kotlin “Variables” view highlights only the relevant variables. Now it works better when you set a breakpoint inside a lambda (either inlined or non-inlined). Local variables inside the lambda, as well as captured variables from the outer context and parameters of the outer function, are correctly displayed:

debug_lambda_variables

You can now set a breakpoint at the end of the function, if needed:

end_of_function_breakpoint

Support for the “Evaluate expression” functionality in the debugger was improved for many non-trivial language features, such as local extension functions or accessors of member extension properties. Also, you can now modify variables via “Evaluate expression”:

Note that, alternatively, you can modify variables in the “Variables” view directly.

New intentions and inspections

New intentions and inspections have been added. One of the goals of intentions is to help you learn how to write idiomatic Kotlin code. The following intention, for instance, suggests using the indices property rather than building a range of indices manually:

If the index isn’t used, the loop can be automatically replaced with a for loop over elements.

IntelliJ IDEA now:

  • Can automatically replace the lateinit property of a primitive type with the by Delegates.notNull() syntax.
  • Can convert a regular property to a lazy one and back.
  • Detects usages of Java methods for array comparison (like Arrays.equals() or Array.deepEquals()) and suggest replacing them with their Kotlin counterparts (like contentEquals and contentDeepEquals).
  • Highlights the deprecated import in the completion list.

deprecated_imports

The general performance of IDE actions has been improved, and several known situations that were causing the UI to freeze (such as calling the “Move” refactoring on a file with a huge number of usages) have been fixed.

Kotlin/JS

This update adds support for building and running Kotlin/JS Gradle projects using the org.jetbrains.kotlin.js plugin on Windows. Just like on other platforms, you can build and run your projects using Gradle tasks, dependencies from NPM required in your Gradle configuration are resolved and included, you can try out your applications using webpack-dev-server (e.g. by invoking the browserRun Gradle task), and more. As with the other platforms, all of this can be used without having to manually install and manage a node, npm, or yarn distribution.

Under the hood, there have also been a series of performance improvements for Kotlin/JS, improving the incremental compilation time for projects. This means that you can expect speedups of up to 30% when compared to 1.3.41.

Our improved integration with NPM means that projects are now resolved lazily and in parallel, and support for projects with transitive dependencies between compilations in the same project has been added.

The new version also brings with it changes in the structure and naming of generated artifacts. Generated artifacts are now bundled in the distributions folder, and they include the version number of the project and archiveBaseName (which defaults to the project name), e.g. projectName-1.0-SNAPSHOT.js.

Dukat

Dukat allows the automatic conversion of TypeScript declaration files (.d.ts) into Kotlin external declarations (and thus replaces the ts2kt command-line tool). This makes it more comfortable to use libraries from the JavaScript ecosystem in a type-safe manner in Kotlin, by drastically reducing the need for manually writing wrappers for JS libraries.

Kotlin/JS now ships with experimental support for dukat integration for Gradle projects. With this integration, by running the build task in Gradle, typesafe wrappers are automatically generated for npm dependencies and can be used from Kotlin.

kotlin-dukat-preview

Because dukat is still in a very early stage, its integration is disabled by default. Add the kotlin.js.experimental.generateKotlinExternals=true line into the gradle.properties file in a project root directory to turn on dukat for your project. We’ve prepared an example project for it too, which demonstrates the use of dukat in Kotlin/JS projects. Try it out and share your feedback with us.

Kotlin/Native

It was not easy but possible to notice that the version of Kotlin/Native differed from the version of Kotlin. Not anymore! The version schemes for Kotlin and Kotlin/Native are now aligned. This release uses version 1.3.50 for both Kotlin and Kotlin/Native binaries, reducing the complexity.

This release brings more pre-imported Apple frameworks for all platforms, including macOS and iOS. The Kotlin/Native compiler now includes actual bitcode in produced frameworks.

Several improvements have been made for interop. We now support the kotlin.Deprecated annotation when producing a framework, and the generated Objective-C headers code will not have warnings. The getOriginalKotlinClass() function is added into the standard library to get a KClass from an Objective-C class or protocols.

The standard library has been updated to support the kotlin.reflect.typeOf() function for Kotlin/Native types. The new function executeAfter() is added to the Worker type to execute actions after a delay. In addition, you can call the processQueue() function on the Worker to process the tasks queue explicitly.

The older functions ByteArray.stringFromUtf8() and ByteArray.stringFromUtf8OrThrow() are now deprecated. In the previous release, we added the ByteArray.decodeToString() function (in the kotlin.text package) to convert a UTF-8 string to a Kotlin string. That function does not support NULL-terminated strings, so to fix that, in 1.3.50 we’ve added a new function to deal with NULL-terminated UTF-8 strings easily. The ByteArray.toKString() function (from the kotlinx.cinterop package) can be used to turn a NULL-terminated UTF-8 string into a Kotlin string. You can pass start and end indices to the function if needed.

We’ve deprecated and removed the kotlin-platform-native Gradle plugin in favor of the kotlin-multiplatform Gradle plugin, so now you can easily benefit from all multiplatform project features. Check out the documentation for the migration guide and more info

Finally, we are happy to share that the Kotlin/Native compiler and the interop tool performance has been improved in this release.

Multiplatform Projects

Java compilation can now be included in Kotlin/JVM targets of a multiplatform project by calling the newly added withJava() function of the DSL. It will configure Java plugin to use the src/<targetName>Main/java and src/<targetName>Test/java paths by default. Here is a full example to create a Kotlin/JVM target with enabled Java compilation:

Kotlin’s New Project wizard now generates Gradle Kotlin DSL for new projects.

Debugging Kotlin/Native code in IntelliJ IDEA Ultimate is now supported too! Try installing the new Native Debug for IntelliJ IDEA Ultimate plugin. It should detect Kotlin/Native run configurations and the debug action is supported:

debugging-kotlin-native-1.3.50

Scripting

This release adds multiple features and improvements in scripting and REPL support. Using Kotlin as a scripting language for your application is even easier! Now the scripting support works out of the box: we’ve published a default JSR-223 implementation library, so to add Kotlin scripting support for your application, you only need to add kotlin-scripting-jsr223 as a dependency and use the javax.script API with Kotlin.

Properties that are set via the JSR-223 API are now accessible from scripts as regular Kotlin properties (before, that you had to use the bindings map):

The kotlin-main-kts artifact, which was introduced in Kotlin 1.3 to simplify the creation and usage of the basic utility scripts, can now be used as a JSR-223 host as well. In addition to the annotations like Repository and DependsOn for resolving dependencies, it now supports the @Import annotation instructing the scripting compiler to “import” another script into the current one:

Read more about scripting in KEEP-75. You can find examples in the Kotlin repository. Please share your feedback in the #scripting channel on the Kotlin Slack!

How to update

As always, you can try Kotlin online at play.kotl.in.

  • In Maven, Gradle, and npm: Use 1.3.50 as the version for the compiler and the standard library. See the docs here.
  • In IntelliJ IDEA and Android Studio: Update the Kotlin plugin to version 1.3.50. Use Tools | Kotlin | Configure Kotlin Plugin Updates and click the “Check for updates now” button.
  • In Eclipse: Install the plugin using the Marketplace.
  • The command-line compiler can be downloaded from the Github release page.

If you run into any problems with the new release, you’re welcome to ask for help on the forums, on Slack (get an invite here), or to report issues in the issue tracker.

Let’s Kotlin!

External Contributions

We want to especially thank Toshiaki Kameyama for his ongoing work on providing many useful intentions and inspections for IntelliJ IDEA.

We’d like to thank all our external contributors whose pull requests were included in this release:
* Steven Schäfer
* pyos
* Ivan Gavrilovic
* Mads Ager
* Ting-Yuan Huang
* ilgonmic
* Jiaxiang Chen
* Mark Punzalan
* Jake Wharton
* Jeffrey van Gogh
* Peter Xu
* Amaury
* Benjamin Orsini
* Dereck Bridie
* Eduard Wolf
* George Gastaldi
* Juan Chen
* Kevin Peek
* KilianCallebaut
* Louis CAD
* Martin Petrov
* Matthew Runo
* AJ Alt
* Ty Smith
* ghedeon
* technoir
* Dat Trieu

This entry was posted in Releases and tagged . Bookmark the permalink.

27 Responses to Kotlin 1.3.50 released

  1. Scott says:

    Why did you remove the kotlin-platform-native plugin, when kotlin-multiplatform plugin still has pretty severe bugs that have stopped teams (like mine) from migrating to it? I understand it’s annoying to maintain it, but it kind of leaves teams that are still using the kotlin-platform-native plugin in an unsupported state.

    • Ilya says:

      You still can use the new K/N compiler with the kotlin-platform-native plugin. Just specify the following property in your gradle.properties:
      org.jetbrains.kotlin.native.version=1.3.50

    • Dmitry Savvinov says:

      Hi!

      We’re very sorry to hear that. Could you please point us to issues that block you from migration? If they are not in the development already, we’ll review their priority and try to resolve them as soon as possible.

  2. Eric Pabst says:

    I am SOOO excited that Dukat support is built-in and having Windows supported for Multiplatform Kotlin/JS. Thank you so much!

  3. Marcel says:

    For duration it would be cool to have something like: 100ms, 5sc, 10hr, 12dy, 1mt instead of having to write: 100.milliseconds, 5.seconds, 10.hours, 12.days, 1.minutes. I don’t like the concept of polluting Int class with such a dumb and long-naming extension properties.

    • Roman Elizarov says:

      Current version of Kotlin language does not support things like 100ms. However, there are other possible solutions beyond 100.milliseconds which, indeed, has downsides you’ve indicated. Please, submit your feedback and follow the discussion on Duration APIs in this Kotlin evolution issue: https://github.com/Kotlin/KEEP/issues/190

    • Mikhail says:

      On the contrary, units attached to numbers are quite clear. Even if names are longish, they are unambiguous.

      Doing things like “100ms, 5sc, 10hr, 12dy, 1mt” would require introduction of a new primitive Kotlin type and support it in the language itself and compiler rather than standard library.

  4. Roman says:

    Constantly getting “Mirror element should never be calculated for light classes generated from a single file” error reports.

    Had to go back to version 1.3.41.

  5. Henrik says:

    Will there be a command line compiler compiled with Excelsior JET in this release? I’m especially interested in a compiled Kotlin/Native compiler.

  6. Bakkiaraj says:

    How to use the kotlin native debugger with Idea IDE ultimate?

    I have a sample project with Idea IDE Ultimate + gradle multi platform + id ‘org.jetbrains.kotlin.multiplatform’ version ‘1.3.41’
    I installed Kotlin native debugger plugin
    Press the “Debug” button
    Did not hit the breakpoint , Just executed fully.

  7. Benjamin Hill says:

    I’m unsure what the right choice is: I moved my main pom.xml properties – kotlin.version to 1.3.50, but then it borked on

    <dependency>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-maven-serialization</artifactId>
    <version>{kotlin.version}</version>
    </dependency>

    Are these other dependencies usually released in sync, or do they follow their own schedule and I should keep them on 1.3.41 until .50 is released? Thanks!

  8. Cristan says:

    Things like number.countOneBits() seems relevant to so few devs that it makes me quite scared of the future of Kotlin. You have a huge number of developers working on Kotlin, and I’m afraid that now the basics are working quite well, you’re just adding functions for rarer and rarer use cases.

    You could say: “if you don’t need it, don’t use it! It doesn’t matter if functionality is added that very few people use.” The problem is, that it does. More functions mean more noise when doing code completion. They are added to Kotlin’s documentation which becomes bigger and therefore more daunting. They are added to Kotlin’s stdlib which therefore gets bigger.

    It’s also not needed. Because Kotlin’s extension methods are so awesome, you can simply create a method like this yourself if you are one of the few who actually need it.

    • Ilya Gorbunov says:

      Thanks for your feedback on these functions.

      I agree that while these functions have their use cases, they are not among the top demanded ones of the integer types. However, we don’t have an option to leave them for implementing outside of the standard library because they require compiler intrinsics on some platforms to be implemented efficiently.

      On the other hand, their form, namely, being extension functions, is not finalized in stone while they are experimental. We’ll continue monitoring feedback on them and make the final decision near to one of the future incremental releases of Kotlin.

      If you have other suggestions on this, let’s continue the discussion in our forum https://discuss.kotlinlang.org/ or slack.

    • Chris Hatton says:

      Sorry but you’re projecting your own requirements too hard there – I develop communication protocols over the wire with Java and now Kotlin, and these kinds of functions are very nice to have in stdlib – how is their presence harming you?

      • I don’t think Christian wanted to state that the presence is harming him. But I agree that these type of functions are probably really rarely needed if you look at the complete Kotlin community. And more functions in the stdlib means a greater size of the lib, as well (as he mentioned) a increase in noise for autocompletion.

        Kotlin provides a really nice System with Extensions functions that could give any programmer (like you, Chris) to develop these type of functions.

        But i also understand that in favor of optimizations these function got added.

  9. In the post it says “Kotlin’s New Project wizard now generates Gradle Kotlin DSL for new projects.”
    I might be misunderstanding, but when I do new project -> Kotlin Multiplatform Library, the gradle scripts are in groovy dsl.

    • Anton Yalyshev says:

      It refers to a new project template called “Kotlin/Multiplatform” that locates in “Gradle” group.
      Indeed, current structure of new project templates may seem a bit misleading, due to the gradual increase in their number. We work with IntelliJ team on its redesign.

  10. Max says:

    Excited about Dukat, but can we get a build.gradle example? I’m not using .kts Gradle yet.

    • Shagen says:

      Hi Max!
      Here’s more or less minimal example of build.gradle file:

      Feel free to reach with any feature request / feedback / bug reports by posting an issue here – https://github.com/Kotlin/dukat/issues

  11. Chris Hatton says:

    This release adds multiple features and improvements in scripting and REPL support.

    Also, script execution from the command line completely broke. (Whoops!)

    Getting java.lang.NoClassDefFoundError: kotlin/script/templates/standard/ScriptTemplateWithArgs, upon any attempted script execution with kotlinc - script <scripName.kts>

    …having to go back to 1.3.41. Will check it’s reported on YouTrack.

  12. Pablo says:

    Thanks for this update! But we are having an issue when using the R8 optimizer in our Android application.

    We have DTOs classes with fields that are never accessed, because these classes are being serialized with gson and are used for the POST requests bodies. We have a proguard rule to keep them using -keepnames, though it should only keep names, not unused fields, it is working. When updating to Kotlin 1.3.50, these fields are removed when shrinking, so the requests have an incomplete body.
    If we disable R8 and use proguard instead, this issue doesn’t happen.

    We can change our proguard rule to -keep to make it work, but as this is not mentioned as a feature for this release, I don’t know if it was an intended feature.

    Thanks!

    • Alexey Belkov says:

      Hello, can you please submit an issue at http://kotl.in/issue with a sample project to reproduce the problem? Thanks!

      • Pablo says:

        Hi Alexey! Creating the sample project I could check that this issue wasn’t introduced with Kotlin version 1.3.50, but with Android Gradle plugin version 3.5.0. I will talk to them about this.

        Thanks!

  13. Cyparu says:

    It look like the “Native Debug for IntelliJ IDEA Ultimate” plugin does not (yet) supports IDEA Ultimate 2019.3 EAP.
    Please provide a compatible build for plugin to start playing with it.

Comments are closed.