See what’s coming in Kotlin 1.3-M1

Today, after a long chain of incremental 1.2.X updates, it’s time to see what’s coming in Kotlin 1.3. We are happy to announce the first preview version of the new major release: Kotlin 1.3-M1.

Kotlin 1.3 brings many advancements including graduation of coroutines, new experimental unsigned arithmetic, and much more. Please read on for the details.

We’d like to thank our external contributors whose pull requests and commits were included in this release: Raluca Sauciuc, Toshiaki Kameyama, Leonardo Lopes, Jake Wharton, Jeff Wright, Lucas Smaira, Mon_chi, Nico Mandery, Oskar Drozda.

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

Coroutines are graduating to stable

Finally, coroutines will not be experimental anymore in 1.3. Both the syntax and the Standard Library APIs are stabilized and will remain backwards-compatible in the future.

Coroutines have been improved significantly since their introduction in 1.1. Notable features include:

  • KT-16908 Support callable references to suspending functions
  • KT-18559 Serializability of all coroutine-related classes

The core APIs have been simplified and moved out of the experimental packages.

We are also working on a multiplatform version of the coroutine APIs, including iOS support through Kotlin/Native.

Migration to new coroutines

As we’ve said earlier, all the packages with coroutine-related functions in Kotlin have dropped experimental from their package names, and buildSequence and buildIterator functions have moved to their permanent place in the kotlin.sequences package.
On the language level, there is still a suspend modifier to support coroutines, and all the rules for working with coroutines remain mostly the same as they were in the experimental version.

The graduated Continuation<T> interface is simplified. It has only one resumeWith(result: SuccessOrFailure<T>) member function (for details see the SuccessOrFailure section below). The resume(value: T) and resumeWithException(exception: Throwable) are now defined as extensions. This affects only a small minority of code that defines its own coroutine builders and leaves classic examples of wrapping callbacks into suspending functions mostly unchanged. For example, a definition of the suspending function await() for the class CompletableFuture<T> would still look like this:

Graduated coroutines use a different binary interface (the major difference being the change of package names) and are not binary-compatible with experimental coroutines. To ensure a smooth migration, we’ll add a compatibility layer in 1.3 and the classes for experimental coroutines will still remain in the standard library. The compiled Kotlin/JVM code that uses experimental coroutines from 1.1 or 1.2 would still continue to work in Kotlin 1.3.

However, the Kotlin 1.3-M1 release does not provide any support for invoking experimental suspending functions from code that is compiled with the language version 1.3. In order to try graduated coroutines in Kotlin 1.3-M1 with libraries that expose suspending functions in their APIs, you will need to use versions of these libraries that are compiled for Kotlin 1.3. This is a temporary inconvenience that we’ll fix soon.

We will be providing a version of kotlinx.coroutines library with x.x.x-eap13 version that is built with Kotlin 1.3 and drops experimental from its package names for every x.x.x version that we release while Kotlin 1.3 is in the preview phase.

The IDE will assist you in migrating to new coroutines. We’ll improve the range of supported migration scenarios before 1.3.

New features

While the bigger new capabilities of 1.3 will be experimental (see below), we are releasing a number of smaller features for your convenience now.

Capturing when subject in a variable

The common case of capturing the subject expression of when in a variable is now supported in the language:

This small addition makes the response variable properly scoped within when, and makes the logic flow in a more expression-like fashion.

This was one of the most popular feature requests in our issue tracker. Thanks to all voters for your feedback!

@JvmStatic and @JvmField in companions of interfaces

Your Kotlin interfaces can now expose static members (fields and methods) to Java clients. The syntax is similar to that for classes; a companion object of an interface can now have @JvmStatic or @JvmField inside:

Note that @JvmField is an all-or-nothing annotation here: to use it on interface companion properties, all of them must be public final vals and all of them must be annotated.

To use the @JvmStatic annotation on interface companion members, the -jvm-target compiler option must be at least 1.8.

Nested declarations in annotation classes

Before 1.3, annotation classes could not have bodies in Kotlin. This release relaxes this limitation, allowing them to have nested classes, interfaces, and objects including a companion object. So, for example, it becomes possible to nest one annotation into another:

Since @JvmField and @JvmStatic are supported in interfaces, it is now possible to declare such members in annotation companion objects:

Functional types of higher arity

A function type can now have more than 22 parameters! We have pushed that limit to 255 parameters, which is the practical maximum number of parameters a method can have on the JVM. To find out how we’ve managed to do that without introducing another 233 classes, see the corresponding KEEP.

Experimental language features

As coroutines have demonstrated, providing early access to bigger features through making them experimental helps us gather invaluable feedback from the community. We’ll keep using this technique to make sure that Kotlin gets only battle-tested design choices that will last.

Kotlin 1.3 brings three exciting new features that will remain experimental for now. An explicit opt-in is required in your project in order to use them. Without an opt-in, usages of a feature will be marked as warnings or errors.

Inline classes

Inline classes allow wrapping a value of some type without creating an actual wrapper object.

When such a class is used, the compiler inlines its content and operations are performed on the wrapped value itself. Hence, this

results in the same compiled code as this:

Inline classes are similar to type aliases, but they are not assignment-compatible with the underlying value type, so you cannot assign a String to a variable of type Name, and vice versa.

Since inline classes have no identity, the === operator cannot be used on them.

There are still places where inline classes result in wrappers being created, similar to how Int can be primitive in some usages and boxed in others (“auto-boxing”):

This feature can be enabled with the compiler option -XXLanguage:+InlineClasses.

See this KEEP for details. Be sure to read the “Limitations” section.

Unsigned integer types

The most obvious application of inline classes is unsigned integer types. The Standard Library now has UInt, ULong, UByte, and UShort defined as inline classes wrapping the corresponding signed counterparts. They define their own arithmetic operations that interpret the storage value as an unsigned integer.

In addition to the new types, there are new language features to support them, which makes these types special.

  • Varargs of unsigned types are allowed, unlike other inline classes

  • Unsigned number literals are provided to simplify initializing variables of unsigned types

  • Constant values of unsigned types are allowed

Note that 1.3-M1 does not yet allow complex const expressions of unsigned types:

Such expressions will be supported a bit later.

Unsigned types are provided as an experimental API: you need to opt in for them, otherwise a warning will be issued at the use site. To opt in:

  • either annotate the code element that uses unsigned types with the @UseExperimental(ExperimentalUnsignedTypes::class) annotation
  • or specify the -Xuse-experimental=kotlin.ExperimentalUnsignedTypes compiler option.

Additionally, if you are a library author and are going to use experimental unsigned types, we recommend that you annotate parts of your API with the @ExperimentalUnsignedTypes annotation. This will propagate the experimentality of unsigned types to your library’s users.

More details about unsigned types can be found in this KEEP.

Annotations for marking an experimental API and opting-in for it

The mechanism of experimental unsigned types opt-in described above is also available in a generic way to library authors. It allows you to provide an experimental API (i.e. one that is subject to future changes), which may break at any moment and require any usages to be fixed and recompiled.

Users of experimental APIs may opt in by agreeing essentially to the following: “I understand that I’m using an experimental declaration that may break at any time”. Without such explicit consent from the user, a warning or error will be reported on usages of experimental APIs.

The ultimate goal is to allow library authors to release APIs earlier and more frequently without a commitment to backward compatibility (source or binary).

Experimental API annotations are described in detail in this KEEP.

New Standard Library APIs

Now let’s look at what new APIs are available in the standard library in this release.

SuccessOrFailure

The inline class SuccessOrFailure is effectively a discriminated union between successful and failed outcomes of execution of a Kotlin function: Success T | Failure Throwable.

It has been introduced to allow for capturing the result of a function execution, whether successful or not, in order to process it at a later time.

The primary driver for introducing this class is the new Continuation interface, where we want to have a single resumeWith(result: SuccessOrFailure<T>) function instead of two, resume(T) and resumeWithException(Throwable).

Note that the Kotlin style guide discourages using SuccessOrFailure type as a return type of Kotlin functions. This is similar to how users are encouraged to have suspend functions return some type instead of plain functions returning a Deferred of that type.

There are a few exceptions from this rule, which are explained in more detail in the proposal KEEP-127. Scroll down to the section on style and exceptions.

Multiplatform random number generator

While there’s no problem with generating random numbers in Kotlin/JVM (aside from ThreadLocalRandom being unavailable prior to JDK 7), no uniform API is yet available to do that in Kotlin for other platforms and, more importantly, in multiplatform code.

This release introduces a new common Random abstract class, which serves as a base class for random number generator implementations.

Note that if you just need a random number, there’s no need to inherit and implement this class. The default random number generator implementation is always at hand: it is the Random companion object. So getting a number is as easy as

A repeatable random generator initialized with a particular seed can be obtained with the top-level function Random(seed)

For details please refer to this KEEP-131.

Companion object for Boolean type

Basic types in Kotlin such as Int, Char, and String have a companion with some properties like MIN_VALUE.

Until recently, the Boolean type stood aside having no companion object.

Our community members have convinced us that there are use cases for having a Boolean companion even without any properties, and Leonardo Lopes has helped implement it.

New constants in companion objects of basic types

Existing companion objects of basic types have received these new properties:

  • Byte, Short, Int, Long, Char now have SIZE_BITS and SIZE_BYTES constants, telling how many bits or bytes a value of that type takes in binary form.

  • Char now has MIN_VALUE and MAX_VALUE constants equal to '\u0000' and '\uFFFF', respectively.

isNullOrEmpty and orEmpty extensions

isNullOrEmpty and orEmpty extensions on nullable collection-like types are not new in the standard library. The first one returns true if the receiver is null or empty, and the second one falls back to an empty instance if the receiver is null.

This release improves the API’s consistency by providing an orEmpty() extension for sequences and an isNullOrEmpty extension for collections, maps, and arrays of objects.

Announcing breaking changes

Some bug fixes introduce changes that are formally breaking. To ensure smooth migration, we deprecate old behavior, report warnings and provide migration tools whenever possible, and always announce such changes in advance.

Note that this is merely an announcement, so some of the changes listed below are not implemented yet and will be implemented in the following milestones.

You can consult the changelog to find out which of these changes have made it into this release.

Compiler changes

  • KT-11567 Companion object instance field is no longer public when the companion object itself is not public
  • KT-16615 Initialization of properties without const modifier is changed so Java does not treat them like constants
  • KT-21354 An array is captured before the for-loop where it is iterated, so its reassignment inside the loop does not affect the iteration
  • KT-22275 The type of exceptions thrown from failed null checks is being unified to NullPointerException
  • KT-19532 Evaluation order of constructor arguments regarding <clinit> call is changed

Previously deprecated feature usages that are now prohibited:

  • KT-16681 val reassignment in its getter
  • KT-16310 Nested classes in enum entries
  • KT-19618 Data classes overriding copy with the generated method
  • KT-17981 Inner classes inheriting Throwable that capture generic parameters from the outer class
  • KT-21515 Accessible classes and interfaces nested in companion objects
  • KT-25333 Java static members accessible through supertypes of companion object
  • KT-23153 Non-constant vararg annotation parameters
  • KT-23277 Local annotation classes
  • KT-22517 Smart casts for local delegated properties
  • KT-24197 mod operator convention. Note that operator rem should be used instead of mod since Kotlin 1.1
  • KT-20588, KT-20589 Passing single element to vararg in named form
  • KT-13762 Annotations with target EXPRESSION cannot have retention other than SOURCE
  • KT-22379 Smart cast is removed after while loops with break
  • KT-20830 Propagation of Java types nullability enhanced by annotations
  • KT-9580 setparam annotation target for a parameter declaration

Standard library changes

  • KT-21784 The org.jetbrains.annotations package is being removed from the standard library in the compiler distribution. Note that the maven standard library artifacts are not affected.
  • KT-19489 Array.copyOfRange throws an exception when indices are out of bounds instead of enlarging the returned array
  • KT-17176 Progressions of ints and longs with a step of Int.MIN_VALUE and Long.MIN_VALUE are outlawed and won’t be allowed to be instantiated
  • KT-16097 Check for index overflow in operations on very long sequences
  • KT-21049 Unify split by an empty match regex result across the platforms

Pre-release notes

Note that the backward compatibility guarantees do not cover pre-release versions: the features and API can change in subsequent releases. When we reach a final RC, all binaries produced by pre-release versions will be outlawed by the compiler, and you will be required to recompile everything that was compiled by 1.3‑Mx.
However, all the code compiled by 1.2.x and earlier releases will be perfectly fine then without recompilation.

How to Try It

In Maven/Gradle: Add http://dl.bintray.com/kotlin/kotlin-eap as a repository for the build script and your projects; use 1.3-M1 as the version number for the compiler plugin and the standard library.

In IntelliJ IDEA: Go to Tools → Kotlin → Configure Kotlin Plugin Updates, then 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‑M1.

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

36 Responses to See what’s coming in Kotlin 1.3-M1

  1. Steven says:

    No collection literals? :(

    • Nils Breunese says:

      I think it’s already pretty concise to use listOf, mapOf, setOf, mutableListOf, mutableMapOf and mutableSetOf. I’m not sure how you’d keep the immutable/mutable distinction clear with literals.

  2. rrader says:

    SuccessOrFailure why not Result?

    • Roman Elizarov says:
      • rrader says:

        This is one of the reasons that SuccessOrFailure was not named Result. That is, to prevent its abuse as a “universal result class” and to encourage declaration of more domain-specific and more explanatory result classes.

        Well, I bet SuccessOrFailure will became “universal result class”, but with ugly name.

    • Michael says:

      Yup, should have been Result. Exceptions are stupid anyway.

      • Kotlin should take a stronger stance and help create the missing universal tasks/futures library.

        It’s fantastic that the feature was designed generically for backwards-support and maximum industry adoption – but it’s impossible to get wide adoption on it if there is no ‘de facto’ implementation which developers can get behind and adopt in their apps.

        PS: Could you guys please put out a guide on some example recommended implementations in different ecosystems (ie: Android?). Which library and abstraction should a net new Kotlin Android app adopt? Give us some guidance here… otherwise a hodge-podge of mechanisms including listener objects / continuation callbacks all down the chain it will continue to be sigh

  3. Nicolas Lepage says:

    Hi,
    Thank you for this post ! (awesome to see coroutines reach stable status !!!)
    I see no mention of discontinued support of JDK7 in the release note, yet when I tried running 1.3-M1 on JDK7…
    kotlinc yields a “java.lang.UnsupportedClassVersionError: org/jetbrains/kotlin/preloading/Preloader : Unsupported major.minor version 52.0”
    Java version is openjdk 1.7.0_181…
    With 1.2 it just worked, is there something to do with 1.3 ?
    Thanks

  4. Jakub Błaszczyk says:

    Great! I guess inline classes are early attempts to bring in real value types. Meanwhile, JDK 10 (the runtime, not Java The Language) will introduce Minimal Value Types! Are you aware of their approach and plans?

    • Roman Elizarov says:

      JDK 10 is GA and it does not have value types, nor they are on the publicly available roadmap for JDK 11. The corresponding JEP 169 does not have any specific target publicly announced. Minimal Value Type project is open only for early adopters for quite a while and does not offer any path to its integration into the language and with the rest of Java ecosystem. All in all, it is too early to form any concrete plans.

    • Henrik says:

      I guess you mean JDK11?

    • How are these inlined classes different than structs in any other language that has them (ie: Swift, C#, C++)?

      If there are semantic differences between these it would be really helpful to explain them so we can understand the rationale for a naming divergence from such an accepted, established nomenclature in existing ecosystems (ie: ‘struct’). The KEEP proposal also makes no mention of structs either, even though from a high level it seems to be exactly what it aims to achieve.

      • Bernd says:

        In C++ a struct is the same as a class except having public members by default. Instances of classes as well as instances of structs can both have by-value semantics or by-reference semantics in C++.

        The Kotlin inline class is more like a typealias, but with strict typechecks. An inline class can have one read-only property only. Also instances of inline classes can have by-reference semantics (although the only property can not be changed), when they implement an interface and are passed as a parameter of the interface type e.g.

        • Ahh gotcha, didn’t realize the single-property aspect of it.

          So they are strictly to enforce stronger type-checking / higher semanticism.

          Gotcha, thanks!

  5. Norbert Sándor says:

    Thanks for the hard work on the language itself! The new features are very useful IMHO.
    Just a tiny remark: please invest a little bit more work into Idea integration as well.
    I use the Community edition and it is insanely buggy and “difficult” to use with not trivial project setups. Especially when Kotlin/JS and/or Android is used with a multi-platform project, the IDE becomes quite unpredictable. Of course it’s possible that the problem is with Gradle and the Gradle plugins but the developer experience remains the same :\

  6. The 1.3-M1 Gradle plugin is not available yet?

    Could not find method classpath() for arguments [org.jetbrains.kotlin:kotlin-gradle-plugin:1.3-M1]

    • Ooops, my bad – seems to work fine now when I tried it on a simpler project :-). Sorry for premature comment :-D.

    • Ilya Gorbunov says:

      You need to add http://dl.bintray.com/kotlin/kotlin-eap repository to the repositories block in buildscript

      • Thanks Ilya :-),

        besides of that I did some tests with runCatching and I discovered weird behaviour when using it in a Map:

        object RunCatchingTest {
        @JvmStatic
        fun main(args: Array) {

        }

        The “Failed nums” doesn’t print out anything and I am wondering why. Am I missing something here or is it a bug?

  7. Thanos says:

    What about the SAM ambiguity thing?

    https://discuss.kotlinlang.org/t/kotlin-and-sam-interface-with-two-parameters/293
    https://youtrack.jetbrains.com/issue/KT-7770

    This is something I was waiting to be fixed in 1.3

  8. Trying to re-post the code again:

  9. Luis Trigueiros says:

    Is kotlin searilization fully supported in Intelij ?
    Is it still an experimental feature ?
    Do we still need to install this additional plugin to get code to compile in intelij ?

    • Leonid Startsev says:

      Yes, for now in M1 things remain the same – kotlinx.serialization is experimental and shipped as separate plugins for compiler and IDEA.

  10. Scott says:

    I thought something was coming in 1.3 around compiler plugins that effectively replace annotation processors on the JVM, except it would be available for all platforms. Is that not being done in 1.3?

  11. Alon Regev says:

    What about Kotlin/Javascript and Kotlin/Native?

    • Ilya Gorbunov says:

      Kotlin/Javascript has been released as 1.3-M1 too, and it has got the same features: stable coroutines, inline classes, unsigned types, etc.
      Kotlin/Native has its own release schedule, while it is in pre-release phase. Stay tuned for the further announcements.

  12. ALEXANDER MINKIN says:

    Thanks to all Kotlin team. I’m so excited to try prerelease 1.3M.

  13. Andriy Hulyk says:

    Hi, thank you for great work!

    What about implementing/fixing following issue:
    https://youtrack.jetbrains.com/issue/KT-14984

  14. Rafa says:

    Hi, probably it’s obvious for you but in order to try it out, also add this to you gradle build script

    • Ilya Gorbunov says:

      Usually this is not required. You just need to change the versions of the Kotlin Gradle plugin and Kotlin library dependencies in the Gradle build script.

      The only exception is when you had these apiVersion and languageVersion set explicitly to 1.2, in that case you need to bump them to 1.3.

Comments are closed.