CINXE.COM
What's new in Kotlin 1.5.30 | Kotlin Documentation
<!DOCTYPE html SYSTEM "about:legacy-compat"> <html lang="en-US" data-preset="contrast" data-primary-color="#307FFF"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta charset="UTF-8"><meta name="built-on" content="2024-11-28T16:03:53.083628193"><meta name="build-number" content="3304"><script> (function (w, d, s, l, i) { w[l] = w[l] || []; w[l].push({'gtm.start': new Date().getTime(), event: 'gtm.js'}); var f = d.getElementsByTagName(s)[0], j = d.createElement(s), dl = l != 'dataLayer' ? '&l=' + l : ''; j.async = true; j.src = '//www.googletagmanager.com/gtm.js?id=' + i + dl; f.parentNode.insertBefore(j, f); })(window, document, 'script', 'dataLayer', 'GTM-5P98'); </script> <script src="static/v3/analytics.js"></script> <title>What's new in Kotlin 1.5.30 | Kotlin Documentation</title><script type="application/json" id="virtual-toc-data">[{"id":"language-features","level":0,"title":"Language features","anchor":"#language-features"},{"id":"exhaustive-when-statements-for-sealed-and-boolean-subjects","level":1,"title":"Exhaustive when statements for sealed and Boolean subjects","anchor":"#exhaustive-when-statements-for-sealed-and-boolean-subjects"},{"id":"suspending-functions-as-supertypes","level":1,"title":"Suspending functions as supertypes","anchor":"#suspending-functions-as-supertypes"},{"id":"requiring-opt-in-on-implicit-usages-of-experimental-apis","level":1,"title":"Requiring opt-in on implicit usages of experimental APIs","anchor":"#requiring-opt-in-on-implicit-usages-of-experimental-apis"},{"id":"changes-to-using-opt-in-requirement-annotations-with-different-targets","level":1,"title":"Changes to using opt-in requirement annotations with different targets","anchor":"#changes-to-using-opt-in-requirement-annotations-with-different-targets"},{"id":"improvements-to-type-inference-for-recursive-generic-types","level":1,"title":"Improvements to type inference for recursive generic types","anchor":"#improvements-to-type-inference-for-recursive-generic-types"},{"id":"eliminating-builder-inference-restrictions","level":1,"title":"Eliminating builder inference restrictions","anchor":"#eliminating-builder-inference-restrictions"},{"id":"kotlin-jvm","level":0,"title":"Kotlin/JVM","anchor":"#kotlin-jvm"},{"id":"instantiation-of-annotation-classes","level":1,"title":"Instantiation of annotation classes","anchor":"#instantiation-of-annotation-classes"},{"id":"improved-nullability-annotation-support-configuration","level":1,"title":"Improved nullability annotation support configuration","anchor":"#improved-nullability-annotation-support-configuration"},{"id":"kotlin-native","level":0,"title":"Kotlin/Native","anchor":"#kotlin-native"},{"id":"apple-silicon-support","level":1,"title":"Apple silicon support","anchor":"#apple-silicon-support"},{"id":"improved-kotlin-dsl-for-the-cocoapods-gradle-plugin","level":1,"title":"Improved Kotlin DSL for the CocoaPods Gradle plugin","anchor":"#improved-kotlin-dsl-for-the-cocoapods-gradle-plugin"},{"id":"experimental-interoperability-with-swift-5-5-async-await","level":1,"title":"Experimental interoperability with Swift 5.5 async/await","anchor":"#experimental-interoperability-with-swift-5-5-async-await"},{"id":"improved-swift-objective-c-mapping-for-objects-and-companion-objects","level":1,"title":"Improved Swift/Objective-C mapping for objects and companion objects","anchor":"#improved-swift-objective-c-mapping-for-objects-and-companion-objects"},{"id":"deprecation-of-linkage-against-dlls-without-import-libraries-for-mingw-targets","level":1,"title":"Deprecation of linkage against DLLs without import libraries for MinGW targets","anchor":"#deprecation-of-linkage-against-dlls-without-import-libraries-for-mingw-targets"},{"id":"kotlin-multiplatform","level":0,"title":"Kotlin Multiplatform","anchor":"#kotlin-multiplatform"},{"id":"ability-to-use-custom-cinterop-libraries-in-shared-native-code","level":1,"title":"Ability to use custom cinterop libraries in shared native code","anchor":"#ability-to-use-custom-cinterop-libraries-in-shared-native-code"},{"id":"support-for-xcframeworks","level":1,"title":"Support for XCFrameworks","anchor":"#support-for-xcframeworks"},{"id":"new-default-publishing-setup-for-android-artifacts","level":1,"title":"New default publishing setup for Android artifacts","anchor":"#new-default-publishing-setup-for-android-artifacts"},{"id":"kotlin-js","level":0,"title":"Kotlin/JS","anchor":"#kotlin-js"},{"id":"js-ir-compiler-backend-reaches-beta","level":1,"title":"JS IR compiler backend reaches Beta","anchor":"#js-ir-compiler-backend-reaches-beta"},{"id":"better-debugging-experience-for-applications-with-the-kotlin-js-ir-backend","level":1,"title":"Better debugging experience for applications with the Kotlin/JS IR backend","anchor":"#better-debugging-experience-for-applications-with-the-kotlin-js-ir-backend"},{"id":"gradle","level":0,"title":"Gradle","anchor":"#gradle"},{"id":"support-for-java-toolchains","level":1,"title":"Support for Java toolchains","anchor":"#support-for-java-toolchains"},{"id":"ability-to-specify-jdk-home-with-useskotlinjavatoolchain-interface","level":1,"title":"Ability to specify JDK home with UsesKotlinJavaToolchain interface","anchor":"#ability-to-specify-jdk-home-with-useskotlinjavatoolchain-interface"},{"id":"easier-way-to-explicitly-specify-kotlin-daemon-jvm-arguments","level":1,"title":"Easier way to explicitly specify Kotlin daemon JVM arguments","anchor":"#easier-way-to-explicitly-specify-kotlin-daemon-jvm-arguments"},{"id":"standard-library","level":0,"title":"Standard library","anchor":"#standard-library"},{"id":"changing-duration-tostring-output","level":1,"title":"Changing Duration.toString() output","anchor":"#changing-duration-tostring-output"},{"id":"parsing-duration-from-string","level":1,"title":"Parsing Duration from String","anchor":"#parsing-duration-from-string"},{"id":"matching-with-regex-at-a-particular-position","level":1,"title":"Matching with Regex at a particular position","anchor":"#matching-with-regex-at-a-particular-position"},{"id":"splitting-regex-to-a-sequence","level":1,"title":"Splitting Regex to a sequence","anchor":"#splitting-regex-to-a-sequence"},{"id":"serialization-1-3-0-rc","level":0,"title":"Serialization 1.3.0-RC","anchor":"#serialization-1-3-0-rc"}]</script><script type="application/json" id="topic-shortcuts"></script><link href="static/v3/app.css?v=6.11.0-footer" rel="stylesheet"><link rel="icon" type="image/svg" sizes="16x16" href="https://kotlinlang.org/assets/images/favicon.svg?v2"><link rel="icon" type="image/x-icon" sizes="32x32" href="https://kotlinlang.org/assets/images/favicon.ico?v2"><link rel="icon" type="image/png" sizes="96x96" href="https://kotlinlang.org/assets/images/apple-touch-icon.png?v2"><link rel="icon" type="image/png" sizes="300x300" href="https://kotlinlang.org/assets/images/apple-touch-icon-72x72.png?v2"><link rel="icon" type="image/png" sizes="500x500" href="https://kotlinlang.org/assets/images/apple-touch-icon-114x114.png?v2"><meta name="image" content="https://kotlinlang.org/assets/images/open-graph/docs.png"><!-- Open Graph --><meta property="og:title" content="What's new in Kotlin 1.5.30 | Kotlin"><meta property="og:description" content=""><meta property="og:image" content="https://kotlinlang.org/assets/images/open-graph/docs.png"><meta property="og:site_name" content="Kotlin Help"><meta property="og:type" content="website"><meta property="og:locale" content="en_US"><meta property="og:url" content="https://kotlinlang.org/docs/whatsnew1530.html"><!-- End Open Graph --><!-- Twitter Card --><meta name="twitter:card" content="summary_large_image"><meta name="twitter:site" content="@kotlin"><meta name="twitter:title" content="What's new in Kotlin 1.5.30 | Kotlin"><meta name="twitter:description" content=""><meta name="twitter:creator" content="@kotlin"><meta name="twitter:image:src" content="https://kotlinlang.org/assets/images/open-graph/docs.png"><!-- End Twitter Card --><!-- Schema.org WebPage --><script type="application/ld+json">{ "@context": "http://schema.org", "@type": "WebPage", "@id": "https://kotlinlang.org/docs/whatsnew1530.html#webpage", "url": "https://kotlinlang.org/docs/whatsnew1530.html", "name": "What's new in Kotlin 1.5.30 | Kotlin", "description": "", "image": "https://kotlinlang.org/assets/images/open-graph/docs.png", "inLanguage":"en-US" }</script><!-- End Schema.org --><!-- Schema.org WebSite --><script type="application/ld+json">{ "@type": "WebSite", "@id": "https://kotlinlang.org/docs/#website", "url": "https://kotlinlang.org/docs/", "name": "Kotlin Help" }</script><!-- End Schema.org --><style>a[href="test-page.html"] { visibility: hidden; }</style></head><body data-id="whatsnew1530" data-main-title="What's new in Kotlin 1.5.30" data-article-props="{"seeAlsoStyle":"links"}" data-template="article" data-breadcrumbs="What's new in Kotlin///Earlier versions" data-edit-url="https://github.com/JetBrains/kotlin-web-site/edit/master/docs/topics/whatsnew1530.md"><div class="wrapper"><main class="panel _main"><header class="panel__header"><div class="container"><h3>Kotlin Help</h3><div class="panel-trigger"></div></div></header><section class="panel__content"><div class="container"><article class="article" data-shortcut-switcher="inactive"><h1 data-toc="whatsnew1530" id="whatsnew1530.md">What's new in Kotlin 1.5.30</h1><p id="jc6ksd_2"><span class="emphasis" id="jc6ksd_16"><a href="releases.html#release-details" id="jc6ksd_17">Released: 24 August 2021</a></span></p><p id="jc6ksd_3">Kotlin 1.5.30 offers language updates including previews of future changes, various improvements in platform support and tooling, and new standard library functions.</p><p id="jc6ksd_4">Here are some major improvements:</p><ul class="list _bullet" id="jc6ksd_5"><li class="list__item" id="jc6ksd_18"><p>Language features, including experimental sealed <code class="code" id="jc6ksd_22">when</code> statements, changes in using opt-in requirement, and others</p></li><li class="list__item" id="jc6ksd_19"><p>Native support for Apple silicon</p></li><li class="list__item" id="jc6ksd_20"><p>Kotlin/JS IR backend reaches Beta</p></li><li class="list__item" id="jc6ksd_21"><p>Improved Gradle plugin experience</p></li></ul><p id="jc6ksd_6">You can also find a short overview of the changes in the <a href="https://blog.jetbrains.com/kotlin/2021/08/kotlin-1-5-30-released/" id="jc6ksd_23" data-external="true" rel="noopener noreferrer">release blog post</a> and this video:</p><div class="video-player" id="jc6ksd_7"><object class="article__bordered-element" width="560" height="315" data-theme="light" type="application/x-shockwave-flash" data="https://www.youtube.com/v/rNbb3A9IdOo?color2=FBE9EC&rel=0&hd=1&autoplay=0&version=3&modestbranding=1&fs=1"></object></div><section class="chapter"><h2 id="language-features" data-toc="language-features">Language features</h2><p id="jc6ksd_24">Kotlin 1.5.30 is presenting previews of future language changes and bringing improvements to the opt-in requirement mechanism and type inference:</p><ul class="list _bullet" id="jc6ksd_25"><li class="list__item" id="jc6ksd_32"><p><a href="#exhaustive-when-statements-for-sealed-and-boolean-subjects" id="jc6ksd_38">Exhaustive when statements for sealed and Boolean subjects</a></p></li><li class="list__item" id="jc6ksd_33"><p><a href="#suspending-functions-as-supertypes" id="jc6ksd_39">Suspending functions as supertypes</a></p></li><li class="list__item" id="jc6ksd_34"><p><a href="#requiring-opt-in-on-implicit-usages-of-experimental-apis" id="jc6ksd_40">Requiring opt-in on implicit usages of experimental APIs</a></p></li><li class="list__item" id="jc6ksd_35"><p><a href="#changes-to-using-opt-in-requirement-annotations-with-different-targets" id="jc6ksd_41">Changes to using opt-in requirement annotations with different targets</a></p></li><li class="list__item" id="jc6ksd_36"><p><a href="#improvements-to-type-inference-for-recursive-generic-types" id="jc6ksd_42">Improvements to type inference for recursive generic types</a></p></li><li class="list__item" id="jc6ksd_37"><p><a href="#eliminating-builder-inference-restrictions" id="jc6ksd_43">Eliminating builder inference restrictions</a></p></li></ul><section class="chapter"><h3 id="exhaustive-when-statements-for-sealed-and-boolean-subjects" data-toc="exhaustive-when-statements-for-sealed-and-boolean-subjects">Exhaustive when statements for sealed and Boolean subjects</h3><aside class="prompt" data-type="warning" data-title="" id="jc6ksd_44"><p id="jc6ksd_51">Support for sealed (exhaustive) when statements is <a href="components-stability.html" id="jc6ksd_52">Experimental</a>. It may be dropped or changed at any time. Opt-in is required (see the details below), and you should use it only for evaluation purposes. We would appreciate your feedback on it in <a href="https://youtrack.jetbrains.com/issue/KT-12380" id="jc6ksd_53" data-external="true" rel="noopener noreferrer">YouTrack</a>.</p></aside><p id="jc6ksd_45">An <span class="emphasis" id="jc6ksd_54">exhaustive</span> <a href="control-flow.html#when-expressions-and-statements" id="jc6ksd_55"><code class="code" id="jc6ksd_57">when</code></a> statement contains branches for either all possible types or values of its subject, or for certain types and includes an <code class="code" id="jc6ksd_56">else</code> branch to cover any remaining cases.</p><p id="jc6ksd_46">We're planning to prohibit non-exhaustive <code class="code" id="jc6ksd_58">when</code> statements soon to make the behavior consistent with <code class="code" id="jc6ksd_59">when</code> expressions. To ensure smooth migration, you can configure the compiler to report warnings about non-exhaustive <code class="code" id="jc6ksd_60">when</code> statements with a sealed class or a Boolean. Such warnings will appear by default in Kotlin 1.6 and will become errors later.</p><aside class="prompt" data-type="note" data-title="" id="jc6ksd_47"><p id="jc6ksd_61">Enums already get a warning.</p></aside><div class="code-block" data-lang="kotlin"> sealed class Mode { object ON : Mode() object OFF : Mode() } fun main() { val x: Mode = Mode.ON when (x) { Mode.ON -> println("ON") } // WARNING: Non exhaustive 'when' statements on sealed classes/interfaces // will be prohibited in 1.7, add an 'OFF' or 'else' branch instead val y: Boolean = true when (y) { true -> println("true") } // WARNING: Non exhaustive 'when' statements on Booleans will be prohibited // in 1.7, add a 'false' or 'else' branch instead } </div><p id="jc6ksd_49">To enable this feature in Kotlin 1.5.30, use language version <code class="code" id="jc6ksd_62">1.6</code>. You can also change the warnings to errors by enabling <a href="whatsnew13.html#progressive-mode" id="jc6ksd_63">progressive mode</a>.</p><div class="tabs" id="jc6ksd_50" data-group="build-script" data-anchors="[jc6ksd_64,jc6ksd_65]"><div class="tabs__content" data-gtm="tab" id="jc6ksd_64" data-sync-tabs="kotlin" data-title="Kotlin"><div class="code-block" data-lang="kotlin" data-title="Kotlin"> kotlin { sourceSets.all { languageSettings.apply { languageVersion = "1.6" //progressiveMode = true // false by default } } } </div></div><div class="tabs__content" data-gtm="tab" id="jc6ksd_65" data-sync-tabs="groovy" data-title="Groovy"><div class="code-block" data-lang="groovy" data-title="Groovy"> kotlin { sourceSets.all { languageSettings { languageVersion = '1.6' //progressiveMode = true // false by default } } } </div></div></div></section><section class="chapter"><h3 id="suspending-functions-as-supertypes" data-toc="suspending-functions-as-supertypes">Suspending functions as supertypes</h3><aside class="prompt" data-type="warning" data-title="" id="jc6ksd_68"><p id="jc6ksd_75">Support for suspending functions as supertypes is <a href="components-stability.html" id="jc6ksd_76">Experimental</a>. It may be dropped or changed at any time. Opt-in is required (see the details below), and you should use it only for evaluation purposes. We would appreciate your feedback on it in <a href="https://youtrack.jetbrains.com/issue/KT-18707" id="jc6ksd_77" data-external="true" rel="noopener noreferrer">YouTrack</a>.</p></aside><p id="jc6ksd_69">Kotlin 1.5.30 provides a preview of the ability to use a <code class="code" id="jc6ksd_78">suspend</code> functional type as a supertype with some limitations.</p><div class="code-block" data-lang="kotlin"> class MyClass: suspend () -> Unit { override suspend fun invoke() { TODO() } } </div><p id="jc6ksd_71">Use the <code class="code" id="jc6ksd_79">-language-version 1.6</code> compiler option to enable the feature:</p><div class="tabs" id="jc6ksd_72" data-group="build-script" data-anchors="[jc6ksd_80,jc6ksd_81]"><div class="tabs__content" data-gtm="tab" id="jc6ksd_80" data-sync-tabs="kotlin" data-title="Kotlin"><div class="code-block" data-lang="kotlin" data-title="Kotlin"> kotlin { sourceSets.all { languageSettings.apply { languageVersion = "1.6" } } } </div></div><div class="tabs__content" data-gtm="tab" id="jc6ksd_81" data-sync-tabs="groovy" data-title="Groovy"><div class="code-block" data-lang="groovy" data-title="Groovy"> kotlin { sourceSets.all { languageSettings { languageVersion = '1.6' } } } </div></div></div><p id="jc6ksd_73">The feature has the following restrictions:</p><ul class="list _bullet" id="jc6ksd_74"><li class="list__item" id="jc6ksd_84"><p>You can't mix an ordinary functional type and a <code class="code" id="jc6ksd_86">suspend</code> functional type as supertype. This is because of the implementation details of <code class="code" id="jc6ksd_87">suspend</code> functional types in the JVM backend. They are represented in it as ordinary functional types with a marker interface. Because of the marker interface, there is no way to tell which of the superinterfaces are suspended and which are ordinary.</p></li><li class="list__item" id="jc6ksd_85"><p>You can't use multiple <code class="code" id="jc6ksd_88">suspend</code> functional supertypes. If there are type checks, you also can't use multiple ordinary functional supertypes.</p></li></ul></section><section class="chapter"><h3 id="requiring-opt-in-on-implicit-usages-of-experimental-apis" data-toc="requiring-opt-in-on-implicit-usages-of-experimental-apis">Requiring opt-in on implicit usages of experimental APIs</h3><aside class="prompt" data-type="warning" data-title="" id="jc6ksd_89"><p id="jc6ksd_94">The opt-in requirement mechanism is <a href="components-stability.html" id="jc6ksd_95">Experimental</a>. It may change at any time. <a href="opt-in-requirements.html" id="jc6ksd_96">See how to opt-in</a>. Use it only for evaluation purposes. We would appreciate your feedback on it in <a href="https://youtrack.jetbrains.com/issues/KT" id="jc6ksd_97" data-external="true" rel="noopener noreferrer">YouTrack</a>.</p></aside><p id="jc6ksd_90">The author of a library can mark an experimental API as <a href="opt-in-requirements.html#create-opt-in-requirement-annotations" id="jc6ksd_98">requiring opt-in</a> to inform users about its experimental state. The compiler raises a warning or error when the API is used and requires <a href="opt-in-requirements.html#opt-in-to-api" id="jc6ksd_99">explicit consent</a> to suppress it.</p><p id="jc6ksd_91">In Kotlin 1.5.30, the compiler treats any declaration that has an experimental type in the signature as experimental. Namely, it requires opt-in even for implicit usages of an experimental API. For example, if the function's return type is marked as an experimental API element, a usage of the function requires you to opt-in even if the declaration is not marked as requiring an opt-in explicitly.</p><div class="code-block" data-lang="kotlin"> // Library code @RequiresOptIn(message = "This API is experimental.") @Retention(AnnotationRetention.BINARY) @Target(AnnotationTarget.CLASS) annotation class MyDateTime // Opt-in requirement annotation @MyDateTime class DateProvider // A class requiring opt-in // Client code // Warning: experimental API usage fun createDateSource(): DateProvider { /* ... */ } fun getDate(): Date { val dateSource = createDateSource() // Also warning: experimental API usage // ... } </div><p id="jc6ksd_93">Learn more about <a href="opt-in-requirements.html" id="jc6ksd_100">opt-in requirements</a>.</p></section><section class="chapter"><h3 id="changes-to-using-opt-in-requirement-annotations-with-different-targets" data-toc="changes-to-using-opt-in-requirement-annotations-with-different-targets">Changes to using opt-in requirement annotations with different targets</h3><aside class="prompt" data-type="warning" data-title="" id="jc6ksd_101"><p id="jc6ksd_105">The opt-in requirement mechanism is <a href="components-stability.html" id="jc6ksd_106">Experimental</a>. It may change at any time. <a href="opt-in-requirements.html" id="jc6ksd_107">See how to opt-in</a>. Use it only for evaluation purposes. We would appreciate your feedback on it in <a href="https://youtrack.jetbrains.com/issues/KT" id="jc6ksd_108" data-external="true" rel="noopener noreferrer">YouTrack</a>.</p></aside><p id="jc6ksd_102">Kotlin 1.5.30 presents new rules for using and declaring opt-in requirement annotations on different <a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.annotation/-target/" id="jc6ksd_109" data-external="true" rel="noopener noreferrer">targets</a>. The compiler now reports an error for use cases that are impractical to handle at compile time. In Kotlin 1.5.30:</p><ul class="list _bullet" id="jc6ksd_103"><li class="list__item" id="jc6ksd_110"><p>Marking local variables and value parameters with opt-in requirement annotations is forbidden at the use site.</p></li><li class="list__item" id="jc6ksd_111"><p>Marking override is allowed only if its basic declaration is also marked.</p></li><li class="list__item" id="jc6ksd_112"><p>Marking backing fields and getters is forbidden. You can mark the basic property instead.</p></li><li class="list__item" id="jc6ksd_113"><p>Setting <code class="code" id="jc6ksd_114">TYPE</code> and <code class="code" id="jc6ksd_115">TYPE_PARAMETER</code> annotation targets is forbidden at the opt-in requirement annotation declaration site.</p></li></ul><p id="jc6ksd_104">Learn more about <a href="opt-in-requirements.html" id="jc6ksd_116">opt-in requirements</a>.</p></section><section class="chapter"><h3 id="improvements-to-type-inference-for-recursive-generic-types" data-toc="improvements-to-type-inference-for-recursive-generic-types">Improvements to type inference for recursive generic types</h3><p id="jc6ksd_117">In Kotlin and Java, you can define a recursive generic type, which references itself in its type parameters. In Kotlin 1.5.30, the Kotlin compiler can infer a type argument based only on upper bounds of the corresponding type parameter if it is a recursive generic. This makes it possible to create various patterns with recursive generic types that are often used in Java to make builder APIs.</p><div class="code-block" data-lang="kotlin"> // Kotlin 1.5.20 val containerA = PostgreSQLContainer<Nothing>(DockerImageName.parse("postgres:13-alpine")).apply { withDatabaseName("db") withUsername("user") withPassword("password") withInitScript("sql/schema.sql") } // Kotlin 1.5.30 val containerB = PostgreSQLContainer(DockerImageName.parse("postgres:13-alpine")) .withDatabaseName("db") .withUsername("user") .withPassword("password") .withInitScript("sql/schema.sql") </div><p id="jc6ksd_119">You can enable the improvements by passing the <code class="code" id="jc6ksd_120">-Xself-upper-bound-inference</code> or the <code class="code" id="jc6ksd_121">-language-version 1.6</code> compiler options. See other examples of newly supported use cases in <a href="https://youtrack.jetbrains.com/issue/KT-40804" id="jc6ksd_122" data-external="true" rel="noopener noreferrer">this YouTrack ticket</a>.</p></section><section class="chapter"><h3 id="eliminating-builder-inference-restrictions" data-toc="eliminating-builder-inference-restrictions">Eliminating builder inference restrictions</h3><p id="jc6ksd_123">Builder inference is a special kind of type inference that allows you to infer the type arguments of a call based on type information from other calls inside its lambda argument. This can be useful when calling generic builder functions such as <a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/build-list.html" id="jc6ksd_128" data-external="true" rel="noopener noreferrer"><code class="code" id="jc6ksd_131">buildList()</code></a> or <a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.sequences/sequence.html" id="jc6ksd_129" data-external="true" rel="noopener noreferrer"><code class="code" id="jc6ksd_132">sequence()</code></a>: <code class="code" id="jc6ksd_130">buildList { add("string") }</code>.</p><p id="jc6ksd_124">Inside such a lambda argument, there was previously a limitation on using the type information that the builder inference tries to infer. This means you can only specify it and cannot get it. For example, you cannot call <a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/get.html" id="jc6ksd_133" data-external="true" rel="noopener noreferrer"><code class="code" id="jc6ksd_135">get()</code></a> inside a lambda argument of <code class="code" id="jc6ksd_134">buildList()</code> without explicitly specified type arguments.</p><p id="jc6ksd_125">Kotlin 1.5.30 removes these limitations with the <code class="code" id="jc6ksd_136">-Xunrestricted-builder-inference</code> compiler option. Add this option to enable previously prohibited calls inside a lambda argument of generic builder functions:</p><div class="code-block" data-lang="kotlin"> @kotlin.ExperimentalStdlibApi val list = buildList { add("a") add("b") set(1, null) val x = get(1) if (x != null) { removeAt(1) } } @kotlin.ExperimentalStdlibApi val map = buildMap { put("a", 1) put("b", 1.1) put("c", 2f) } </div><p id="jc6ksd_127">Also, you can enable this feature with the <code class="code" id="jc6ksd_137">-language-version 1.6</code> compiler option.</p></section></section><section class="chapter"><h2 id="kotlin-jvm" data-toc="kotlin-jvm">Kotlin/JVM</h2><p id="jc6ksd_138">With Kotlin 1.5.30, Kotlin/JVM receives the following features:</p><ul class="list _bullet" id="jc6ksd_139"><li class="list__item" id="jc6ksd_143"><p><a href="#instantiation-of-annotation-classes" id="jc6ksd_145">Instantiation of annotation classes</a></p></li><li class="list__item" id="jc6ksd_144"><p><a href="#improved-nullability-annotation-support-configuration" id="jc6ksd_146">Improved nullability annotation support configuration</a></p></li></ul><p id="jc6ksd_140">See the <a href="#gradle" id="jc6ksd_147">Gradle</a> section for Kotlin Gradle plugin updates on the JVM platform.</p><section class="chapter"><h3 id="instantiation-of-annotation-classes" data-toc="instantiation-of-annotation-classes">Instantiation of annotation classes</h3><aside class="prompt" data-type="warning" data-title="" id="jc6ksd_148"><p id="jc6ksd_153">Instantiation of annotation classes is <a href="components-stability.html" id="jc6ksd_154">Experimental</a>. It may be dropped or changed at any time. Opt-in is required (see the details below), and you should use it only for evaluation purposes. We would appreciate your feedback on it in <a href="https://youtrack.jetbrains.com/issue/KT-45395" id="jc6ksd_155" data-external="true" rel="noopener noreferrer">YouTrack</a>.</p></aside><p id="jc6ksd_149">With Kotlin 1.5.30 you can now call constructors of <a href="annotations.html" id="jc6ksd_156">annotation classes</a> in arbitrary code to obtain a resulting instance. This feature covers the same use cases as the Java convention that allows the implementation of an annotation interface.</p><div class="code-block" data-lang="kotlin"> annotation class InfoMarker(val info: String) fun processInfo(marker: InfoMarker) = ... fun main(args: Array<String>) { if (args.size != 0) processInfo(getAnnotationReflective(args)) else processInfo(InfoMarker("default")) } </div><p id="jc6ksd_151">Use the <code class="code" id="jc6ksd_157">-language-version 1.6</code> compiler option to enable this feature. Note that all current annotation class limitations, such as restrictions to define non-<code class="code" id="jc6ksd_158">val</code> parameters or members different from secondary constructors, remain intact.</p><p id="jc6ksd_152">Learn more about instantiation of annotation classes in <a href="https://github.com/Kotlin/KEEP/blob/master/proposals/annotation-instantiation.md" id="jc6ksd_159" data-external="true" rel="noopener noreferrer">this KEEP</a></p></section><section class="chapter"><h3 id="improved-nullability-annotation-support-configuration" data-toc="improved-nullability-annotation-support-configuration">Improved nullability annotation support configuration</h3><p id="jc6ksd_160">The Kotlin compiler can read various types of <a href="java-interop.html#nullability-annotations" id="jc6ksd_165">nullability annotations</a> to get nullability information from Java. This information allows it to report nullability mismatches in Kotlin when calling Java code.</p><p id="jc6ksd_161">In Kotlin 1.5.30, you can specify whether the compiler reports a nullability mismatch based on the information from specific types of nullability annotations. Just use the compiler option <code class="code" id="jc6ksd_166">-Xnullability-annotations=@<package-name>:<report-level></code>. In the argument, specify the fully qualified nullability annotations package and one of these report levels:</p><ul class="list _bullet" id="jc6ksd_162"><li class="list__item" id="jc6ksd_167"><p><code class="code" id="jc6ksd_170">ignore</code> to ignore nullability mismatches</p></li><li class="list__item" id="jc6ksd_168"><p><code class="code" id="jc6ksd_171">warn</code> to report warnings</p></li><li class="list__item" id="jc6ksd_169"><p><code class="code" id="jc6ksd_172">strict</code> to report errors.</p></li></ul><p id="jc6ksd_163">See the <a href="java-interop.html#nullability-annotations" id="jc6ksd_173">full list of supported nullability annotations</a> along with their fully qualified package names.</p><p id="jc6ksd_164">Here is an example showing how to enable error reporting for the newly supported <a href="https://github.com/ReactiveX/RxJava" id="jc6ksd_174" data-external="true" rel="noopener noreferrer">RxJava</a> 3 nullability annotations: <code class="code" id="jc6ksd_175">-Xnullability-annotations=@io.reactivex.rxjava3.annotations:strict</code>. Note that all such nullability mismatches are warnings by default.</p></section></section><section class="chapter"><h2 id="kotlin-native" data-toc="kotlin-native">Kotlin/Native</h2><p id="jc6ksd_176">Kotlin/Native has received various changes and improvements:</p><ul class="list _bullet" id="jc6ksd_177"><li class="list__item" id="jc6ksd_183"><p><a href="#apple-silicon-support" id="jc6ksd_188">Apple silicon support</a></p></li><li class="list__item" id="jc6ksd_184"><p><a href="#improved-kotlin-dsl-for-the-cocoapods-gradle-plugin" id="jc6ksd_189">Improved Kotlin DSL for the CocoaPods Gradle plugin</a></p></li><li class="list__item" id="jc6ksd_185"><p><a href="#experimental-interoperability-with-swift-5-5-async-await" id="jc6ksd_190">Experimental interoperability with Swift 5.5 async/await</a></p></li><li class="list__item" id="jc6ksd_186"><p><a href="#improved-swift-objective-c-mapping-for-objects-and-companion-objects" id="jc6ksd_191">Improved Swift/Objective-C mapping for objects and companion objects</a></p></li><li class="list__item" id="jc6ksd_187"><p><a href="#deprecation-of-linkage-against-dlls-without-import-libraries-for-mingw-targets" id="jc6ksd_192">Deprecation of linkage against DLLs without import libraries for MinGW targets</a></p></li></ul><section class="chapter"><h3 id="apple-silicon-support" data-toc="apple-silicon-support">Apple silicon support</h3><p id="jc6ksd_193">Kotlin 1.5.30 introduces native support for <a href="https://support.apple.com/en-us/HT211814" id="jc6ksd_199" data-external="true" rel="noopener noreferrer">Apple silicon</a>.</p><p id="jc6ksd_194">Previously, the Kotlin/Native compiler and tooling required the <a href="https://developer.apple.com/documentation/apple-silicon/about-the-rosetta-translation-environment" id="jc6ksd_200" data-external="true" rel="noopener noreferrer">Rosetta translation environment</a> for working on Apple silicon hosts. In Kotlin 1.5.30, the translation environment is no longer needed – the compiler and tooling can run on Apple silicon hardware without requiring any additional actions.</p><p id="jc6ksd_195">We've also introduced new targets that make Kotlin code run natively on Apple silicon:</p><ul class="list _bullet" id="jc6ksd_196"><li class="list__item" id="jc6ksd_201"><p><code class="code" id="jc6ksd_205">macosArm64</code></p></li><li class="list__item" id="jc6ksd_202"><p><code class="code" id="jc6ksd_206">iosSimulatorArm64</code></p></li><li class="list__item" id="jc6ksd_203"><p><code class="code" id="jc6ksd_207">watchosSimulatorArm64</code></p></li><li class="list__item" id="jc6ksd_204"><p><code class="code" id="jc6ksd_208">tvosSimulatorArm64</code></p></li></ul><p id="jc6ksd_197">They are available on both Intel-based and Apple silicon hosts. All existing targets are available on Apple silicon hosts as well.</p><p id="jc6ksd_198">Note that in 1.5.30 we provide only basic support for Apple silicon targets in the <code class="code" id="jc6ksd_209">kotlin-multiplatform</code> Gradle plugin. Particularly, the new simulator targets aren't included in the <code class="code" id="jc6ksd_210">ios</code>, <code class="code" id="jc6ksd_211">tvos</code>, and <code class="code" id="jc6ksd_212">watchos</code> target shortcuts. We will keep working to improve the user experience with the new targets.</p></section><section class="chapter"><h3 id="improved-kotlin-dsl-for-the-cocoapods-gradle-plugin" data-toc="improved-kotlin-dsl-for-the-cocoapods-gradle-plugin">Improved Kotlin DSL for the CocoaPods Gradle plugin</h3><section class="chapter"><h4 id="new-parameters-for-kotlin-native-frameworks" data-toc="new-parameters-for-kotlin-native-frameworks">New parameters for Kotlin/Native frameworks</h4><p id="jc6ksd_215">Kotlin 1.5.30 introduces the improved CocoaPods Gradle plugin DSL for Kotlin/Native frameworks. In addition to the name of the framework, you can specify other parameters in the Pod configuration:</p><ul class="list _bullet" id="jc6ksd_216"><li class="list__item" id="jc6ksd_219"><p>Specify the dynamic or static version of the framework</p></li><li class="list__item" id="jc6ksd_220"><p>Enable export dependencies explicitly</p></li><li class="list__item" id="jc6ksd_221"><p>Enable Bitcode embedding</p></li></ul><p id="jc6ksd_217">To use the new DSL, update your project to Kotlin 1.5.30, and specify the parameters in the <code class="code" id="jc6ksd_222">cocoapods</code> section of your <code class="code" id="jc6ksd_223">build.gradle(.kts)</code> file:</p><div class="code-block" data-lang="kotlin"> cocoapods { frameworkName = "MyFramework" // This property is deprecated // and will be removed in future versions // New DSL for framework configuration: framework { // All Framework properties are supported // Framework name configuration. Use this property instead of // deprecated 'frameworkName' baseName = "MyFramework" // Dynamic framework support isStatic = false // Dependency export export(project(":anotherKMMModule")) transitiveExport = false // This is default. // Bitcode embedding embedBitcode(BITCODE) } } </div></section><section class="chapter"><h4 id="support-custom-names-for-xcode-configuration" data-toc="support-custom-names-for-xcode-configuration">Support custom names for Xcode configuration</h4><p id="jc6ksd_224">The Kotlin CocoaPods Gradle plugin supports custom names in the Xcode build configuration. It will also help you if you're using special names for the build configuration in Xcode, for example <code class="code" id="jc6ksd_229">Staging</code>.</p><p id="jc6ksd_225">To specify a custom name, use the <code class="code" id="jc6ksd_230">xcodeConfigurationToNativeBuildType</code> parameter in the <code class="code" id="jc6ksd_231">cocoapods</code> section of your <code class="code" id="jc6ksd_232">build.gradle(.kts)</code> file:</p><div class="code-block" data-lang="kotlin"> cocoapods { // Maps custom Xcode configuration to NativeBuildType xcodeConfigurationToNativeBuildType["CUSTOM_DEBUG"] = NativeBuildType.DEBUG xcodeConfigurationToNativeBuildType["CUSTOM_RELEASE"] = NativeBuildType.RELEASE } </div><p id="jc6ksd_227">This parameter will not appear in the Podspec file. When Xcode runs the Gradle build process, the Kotlin CocoaPods Gradle plugin will select the necessary native build type.</p><aside class="prompt" data-type="note" data-title="" id="jc6ksd_228"><p id="jc6ksd_233">There's no need to declare the <code class="code" id="jc6ksd_234">Debug</code> and <code class="code" id="jc6ksd_235">Release</code> configurations because they are supported by default.</p></aside></section></section><section class="chapter"><h3 id="experimental-interoperability-with-swift-5-5-async-await" data-toc="experimental-interoperability-with-swift-5-5-async-await">Experimental interoperability with Swift 5.5 async/await</h3><aside class="prompt" data-type="warning" data-title="" id="jc6ksd_236"><p id="jc6ksd_240">Concurrency interoperability with Swift async/await is <a href="components-stability.html" id="jc6ksd_241">Experimental</a>. It may be dropped or changed at any time. You should use it only for evaluation purposes. We would appreciate your feedback on it in <a href="https://youtrack.jetbrains.com/issue/KT-47610" id="jc6ksd_242" data-external="true" rel="noopener noreferrer">YouTrack</a>.</p></aside><p id="jc6ksd_237">We added <a href="whatsnew14.html#support-for-kotlin-s-suspending-functions-in-swift-and-objective-c" id="jc6ksd_243">support for calling Kotlin's suspending functions from Objective-C and Swift in 1.4.0</a>, and now we're improving it to keep up with a new Swift 5.5 feature – <a href="https://github.com/apple/swift-evolution/blob/main/proposals/0296-async-await.md" id="jc6ksd_244" data-external="true" rel="noopener noreferrer">concurrency with <code class="code" id="jc6ksd_245">async</code> and <code class="code" id="jc6ksd_246">await</code> modifiers</a>.</p><p id="jc6ksd_238">The Kotlin/Native compiler now emits the <code class="code" id="jc6ksd_247">_Nullable_result</code> attribute in the generated Objective-C headers for suspending functions with nullable return types. This makes it possible to call them from Swift as <code class="code" id="jc6ksd_248">async</code> functions with the proper nullability.</p><p id="jc6ksd_239">Note that this feature is experimental and can be affected in the future by changes in both Kotlin and Swift. For now, we're offering a preview of this feature that has certain limitations, and we are eager to hear what you think. Learn more about its current state and leave your feedback in <a href="https://youtrack.jetbrains.com/issue/KT-47610" id="jc6ksd_249" data-external="true" rel="noopener noreferrer">this YouTrack issue</a>.</p></section><section class="chapter"><h3 id="improved-swift-objective-c-mapping-for-objects-and-companion-objects" data-toc="improved-swift-objective-c-mapping-for-objects-and-companion-objects">Improved Swift/Objective-C mapping for objects and companion objects</h3><p id="jc6ksd_250">Getting objects and companion objects can now be done in a way that is more intuitive for native iOS developers. For example, if you have the following objects in Kotlin:</p><div class="code-block" data-lang="kotlin"> object MyObject { val x = "Some value" } class MyClass { companion object { val x = "Some value" } } </div><p id="jc6ksd_252">To access them in Swift, you can use the <code class="code" id="jc6ksd_255">shared</code> and <code class="code" id="jc6ksd_256">companion</code> properties:</p><div class="code-block" data-lang="swift"> MyObject.shared MyObject.shared.x MyClass.companion MyClass.Companion.shared </div><p id="jc6ksd_254">Learn more about <a href="native-objc-interop.html" id="jc6ksd_257">Swift/Objective-C interoperability</a>.</p></section><section class="chapter"><h3 id="deprecation-of-linkage-against-dlls-without-import-libraries-for-mingw-targets" data-toc="deprecation-of-linkage-against-dlls-without-import-libraries-for-mingw-targets">Deprecation of linkage against DLLs without import libraries for MinGW targets</h3><p id="jc6ksd_258"><a href="https://lld.llvm.org/" id="jc6ksd_261" data-external="true" rel="noopener noreferrer">LLD</a> is a linker from the LLVM project, which we plan to start using in Kotlin/Native for MinGW targets because of its benefits over the default ld.bfd – primarily its better performance.</p><p id="jc6ksd_259">However, the latest stable version of LLD doesn't support direct linkage against DLL for MinGW (Windows) targets. Such linkage requires using <a href="https://stackoverflow.com/questions/3573475/how-does-the-import-library-work-details/3573527#3573527" id="jc6ksd_262" data-external="true" rel="noopener noreferrer">import libraries</a>. Although they aren't needed with Kotlin/Native 1.5.30, we're adding a warning to inform you that such usage is incompatible with LLD that will become the default linker for MinGW in the future.</p><p id="jc6ksd_260">Please share your thoughts and concerns about the transition to the LLD linker in <a href="https://youtrack.jetbrains.com/issue/KT-47605" id="jc6ksd_263" data-external="true" rel="noopener noreferrer">this YouTrack issue</a>.</p></section></section><section class="chapter"><h2 id="kotlin-multiplatform" data-toc="kotlin-multiplatform">Kotlin Multiplatform</h2><p id="jc6ksd_264">1.5.30 brings the following notable updates to Kotlin Multiplatform:</p><ul class="list _bullet" id="jc6ksd_265"><li class="list__item" id="jc6ksd_269"><p><a href="#ability-to-use-custom-cinterop-libraries-in-shared-native-code" id="jc6ksd_272">Ability to use custom <code class="code" id="jc6ksd_273">cinterop</code> libraries in shared native code</a></p></li><li class="list__item" id="jc6ksd_270"><p><a href="#support-for-xcframeworks" id="jc6ksd_274">Support for XCFrameworks</a></p></li><li class="list__item" id="jc6ksd_271"><p><a href="#new-default-publishing-setup-for-android-artifacts" id="jc6ksd_275">New default publishing setup for Android artifacts</a></p></li></ul><section class="chapter"><h3 id="ability-to-use-custom-cinterop-libraries-in-shared-native-code" data-toc="ability-to-use-custom-cinterop-libraries-in-shared-native-code">Ability to use custom cinterop libraries in shared native code</h3><p id="jc6ksd_276">Kotlin Multiplatform gives you an <a href="multiplatform-share-on-platforms.html#connect-platform-specific-libraries" id="jc6ksd_278">option</a> to use platform-dependent interop libraries in shared source sets. Before 1.5.30, this worked only with <a href="native-platform-libs.html" id="jc6ksd_279">platform libraries</a> shipped with Kotlin/Native distribution. Starting from 1.5.30, you can use it with your custom <code class="code" id="jc6ksd_280">cinterop</code> libraries. To enable this feature, add the <code class="code" id="jc6ksd_281">kotlin.mpp.enableCInteropCommonization=true</code> property in your <code class="code" id="jc6ksd_282">gradle.properties</code>:</p><div class="code-block" data-lang="none"> kotlin.mpp.enableGranularSourceSetsMetadata=true kotlin.native.enableDependencyPropagation=false kotlin.mpp.enableCInteropCommonization=true </div></section><section class="chapter"><h3 id="support-for-xcframeworks" data-toc="support-for-xcframeworks">Support for XCFrameworks</h3><p id="jc6ksd_283">All Kotlin Multiplatform projects can now have XCFrameworks as an output format. Apple introduced XCFrameworks as a replacement for universal (fat) frameworks. With the help of XCFrameworks you:</p><ul class="list _bullet" id="jc6ksd_284"><li class="list__item" id="jc6ksd_291"><p>Can gather logic for all the target platforms and architectures in a single bundle.</p></li><li class="list__item" id="jc6ksd_292"><p>Don't need to remove all unnecessary architectures before publishing the application to the App Store.</p></li></ul><p id="jc6ksd_285">XCFrameworks is useful if you want to use your Kotlin framework for devices and simulators on Apple M1.</p><p id="jc6ksd_286">To use XCFrameworks, update your <code class="code" id="jc6ksd_293">build.gradle(.kts)</code> script:</p><div class="tabs" id="jc6ksd_287" data-group="build-script" data-anchors="[jc6ksd_294,jc6ksd_295]"><div class="tabs__content" data-gtm="tab" id="jc6ksd_294" data-sync-tabs="kotlin" data-title="Kotlin"><div class="code-block" data-lang="kotlin" data-title="Kotlin"> import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XCFramework plugins { kotlin("multiplatform") } kotlin { val xcf = XCFramework() ios { binaries.framework { baseName = "shared" xcf.add(this) } } watchos { binaries.framework { baseName = "shared" xcf.add(this) } } tvos { binaries.framework { baseName = "shared" xcf.add(this) } } } </div></div><div class="tabs__content" data-gtm="tab" id="jc6ksd_295" data-sync-tabs="groovy" data-title="Groovy"><div class="code-block" data-lang="groovy" data-title="Groovy"> import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XCFrameworkConfig plugins { id 'org.jetbrains.kotlin.multiplatform' } kotlin { def xcf = new XCFrameworkConfig(project) ios { binaries.framework { baseName = "shared" xcf.add(it) } } watchos { binaries.framework { baseName = "shared" xcf.add(it) } } tvos { binaries.framework { baseName = "shared" xcf.add(it) } } } </div></div></div><p id="jc6ksd_288">When you declare XCFrameworks, these new Gradle tasks will be registered:</p><ul class="list _bullet" id="jc6ksd_289"><li class="list__item" id="jc6ksd_298"><p><code class="code" id="jc6ksd_301">assembleXCFramework</code></p></li><li class="list__item" id="jc6ksd_299"><p><code class="code" id="jc6ksd_302">assembleDebugXCFramework</code> (additionally debug artifact that <a href="native-ios-symbolication.html" id="jc6ksd_303">contains dSYMs</a>)</p></li><li class="list__item" id="jc6ksd_300"><p><code class="code" id="jc6ksd_304">assembleReleaseXCFramework</code></p></li></ul><p id="jc6ksd_290">Learn more about XCFrameworks in <a href="https://developer.apple.com/videos/play/wwdc2019/416/" id="jc6ksd_305" data-external="true" rel="noopener noreferrer">this WWDC video</a>.</p></section><section class="chapter"><h3 id="new-default-publishing-setup-for-android-artifacts" data-toc="new-default-publishing-setup-for-android-artifacts">New default publishing setup for Android artifacts</h3><p id="jc6ksd_306">Using the <code class="code" id="jc6ksd_310">maven-publish</code> Gradle plugin, you can <a href="multiplatform-publish-lib.html#publish-an-android-library" id="jc6ksd_311">publish your multiplatform library for the Android target</a> by specifying <a href="https://developer.android.com/studio/build/build-variants" id="jc6ksd_312" data-external="true" rel="noopener noreferrer">Android variant</a> names in the build script. The Kotlin Gradle plugin will generate publications automatically.</p><p id="jc6ksd_307">Before 1.5.30, the generated publication <a href="https://docs.gradle.org/current/userguide/publishing_gradle_module_metadata.html" id="jc6ksd_313" data-external="true" rel="noopener noreferrer">metadata</a> included the build type attributes for every published Android variant, making it compatible only with the same build type used by the library consumer. Kotlin 1.5.30 introduces a new default publishing setup:</p><ul class="list _bullet" id="jc6ksd_308"><li class="list__item" id="jc6ksd_314"><p>If all Android variants that the project publishes have the same build type attribute, then the published variants won't have the build type attribute and will be compatible with any build type.</p></li><li class="list__item" id="jc6ksd_315"><p>If the published variants have different build type attributes, then only those with the <code class="code" id="jc6ksd_316">release</code> value will be published without the build type attribute. This makes the release variants compatible with any build type on the consumer side, while non-release variants will only be compatible with the matching consumer build types.</p></li></ul><p id="jc6ksd_309">To opt-out and keep the build type attributes for all variants, you can set this Gradle property: <code class="code" id="jc6ksd_317">kotlin.android.buildTypeAttribute.keep=true</code>.</p></section></section><section class="chapter"><h2 id="kotlin-js" data-toc="kotlin-js">Kotlin/JS</h2><p id="jc6ksd_318">Two major improvements are coming to Kotlin/JS with 1.5.30:</p><ul class="list _bullet" id="jc6ksd_319"><li class="list__item" id="jc6ksd_322"><p><a href="#js-ir-compiler-backend-reaches-beta" id="jc6ksd_324">JS IR compiler backend reaches Beta</a></p></li><li class="list__item" id="jc6ksd_323"><p><a href="#better-debugging-experience-for-applications-with-the-kotlin-js-ir-backend" id="jc6ksd_325">Better debugging experience for applications with the Kotlin/JS IR backend</a></p></li></ul><section class="chapter"><h3 id="js-ir-compiler-backend-reaches-beta" data-toc="js-ir-compiler-backend-reaches-beta">JS IR compiler backend reaches Beta</h3><p id="jc6ksd_326">The <a href="whatsnew14.html#unified-backends-and-extensibility" id="jc6ksd_328">IR-based compiler backend</a> for Kotlin/JS, which was introduced in 1.4.0 in <a href="components-stability.html" id="jc6ksd_329">Alpha</a>, has reached Beta.</p><p id="jc6ksd_327">Previously, we published the <a href="js-ir-migration.html" id="jc6ksd_330">migration guide for the JS IR backend</a> to help you migrate your projects to the new backend. Now we would like to present the <a href="https://plugins.jetbrains.com/plugin/17183-kotlin-js-inspection-pack/" id="jc6ksd_331" data-external="true" rel="noopener noreferrer">Kotlin/JS Inspection Pack</a> IDE plugin, which displays the required changes directly in IntelliJ IDEA.</p></section><section class="chapter"><h3 id="better-debugging-experience-for-applications-with-the-kotlin-js-ir-backend" data-toc="better-debugging-experience-for-applications-with-the-kotlin-js-ir-backend">Better debugging experience for applications with the Kotlin/JS IR backend</h3><p id="jc6ksd_332">Kotlin 1.5.30 brings JavaScript source map generation for the Kotlin/JS IR backend. This will improve the Kotlin/JS debugging experience when the IR backend is enabled, with full debugging support that includes breakpoints, stepping, and readable stack traces with proper source references.</p><p id="jc6ksd_333">Learn how to <a href="js-debugging.html" id="jc6ksd_334">debug Kotlin/JS in the browser or IntelliJ IDEA Ultimate</a>.</p></section></section><section class="chapter"><h2 id="gradle" data-toc="gradle">Gradle</h2><p id="jc6ksd_335">As a part of our mission to <a href="https://youtrack.jetbrains.com/issue/KT-45778" id="jc6ksd_340" data-external="true" rel="noopener noreferrer">improve the Kotlin Gradle plugin user experience</a>, we've implemented the following features:</p><ul class="list _bullet" id="jc6ksd_336"><li class="list__item" id="jc6ksd_341"><p><a href="#support-for-java-toolchains" id="jc6ksd_343">Support for Java toolchains</a>, which includes an <a href="#ability-to-specify-jdk-home-with-useskotlinjavatoolchain-interface" id="jc6ksd_344">ability to specify a JDK home with the <code class="code" id="jc6ksd_345">UsesKotlinJavaToolchain</code> interface for older Gradle versions</a></p></li><li class="list__item" id="jc6ksd_342"><p><a href="#easier-way-to-explicitly-specify-kotlin-daemon-jvm-arguments" id="jc6ksd_346">An easier way to explicitly specify the Kotlin daemon's JVM arguments</a></p></li></ul><section class="chapter"><h3 id="support-for-java-toolchains" data-toc="support-for-java-toolchains">Support for Java toolchains</h3><p id="jc6ksd_347">Gradle 6.7 introduced the <a href="https://docs.gradle.org/current/userguide/toolchains.html" id="jc6ksd_359" data-external="true" rel="noopener noreferrer">"Java toolchains support"</a> feature. Using this feature, you can:</p><ul class="list _bullet" id="jc6ksd_348"><li class="list__item" id="jc6ksd_360"><p>Run compilations, tests, and executables using JDKs and JREs that are different from the Gradle ones.</p></li><li class="list__item" id="jc6ksd_361"><p>Compile and test code with an unreleased language version.</p></li></ul><p id="jc6ksd_349">With toolchains support, Gradle can autodetect local JDKs and install missing JDKs that Gradle requires for the build. Now Gradle itself can run on any JDK and still reuse the <a href="gradle-compilation-and-caches.html#gradle-build-cache-support" id="jc6ksd_362">build cache feature</a>.</p><p id="jc6ksd_350">The Kotlin Gradle plugin supports Java toolchains for Kotlin/JVM compilation tasks. A Java toolchain:</p><ul class="list _bullet" id="jc6ksd_351"><li class="list__item" id="jc6ksd_363"><p id="jc6ksd_366">Sets the <a href="gradle-compiler-options.html#attributes-specific-to-jvm" id="jc6ksd_368"><code class="code" id="jc6ksd_369">jdkHome</code> option</a> available for JVM targets.</p><aside class="prompt" data-type="warning" data-title="" id="jc6ksd_367"><p id="jc6ksd_370"><a href="https://youtrack.jetbrains.com/issue/KT-46541" id="jc6ksd_371" data-external="true" rel="noopener noreferrer">The ability to set the <code class="code" id="jc6ksd_372">jdkHome</code> option directly has been deprecated</a>.</p></aside></li><li class="list__item" id="jc6ksd_364"><p id="jc6ksd_373">Sets the <a href="gradle-compiler-options.html#attributes-specific-to-jvm" id="jc6ksd_374"><code class="code" id="jc6ksd_378">kotlinOptions.jvmTarget</code></a> to the toolchain's JDK version if the user didn't set the <code class="code" id="jc6ksd_375">jvmTarget</code> option explicitly. If the toolchain is not configured, the <code class="code" id="jc6ksd_376">jvmTarget</code> field uses the default value. Learn more about <a href="gradle-configure-project.html#check-for-jvm-target-compatibility-of-related-compile-tasks" id="jc6ksd_377">JVM target compatibility</a>.</p></li><li class="list__item" id="jc6ksd_365"><p id="jc6ksd_379">Affects which JDK <a href="kapt.html#run-kapt-tasks-in-parallel" id="jc6ksd_380"><code class="code" id="jc6ksd_381">kapt</code> workers</a> are running on.</p></li></ul><p id="jc6ksd_352">Use the following code to set a toolchain. Replace the placeholder <code class="code" id="jc6ksd_382"><MAJOR_JDK_VERSION></code> with the JDK version you would like to use:</p><div class="tabs" id="jc6ksd_353" data-group="build-script" data-anchors="[jc6ksd_383,jc6ksd_384]"><div class="tabs__content" data-gtm="tab" id="jc6ksd_383" data-sync-tabs="kotlin" data-title="Kotlin"><div class="code-block" data-lang="kotlin" data-title="Kotlin"> kotlin { jvmToolchain { (this as JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(<MAJOR_JDK_VERSION>)) // "8" } } </div></div><div class="tabs__content" data-gtm="tab" id="jc6ksd_384" data-sync-tabs="groovy" data-title="Groovy"><div class="code-block" data-lang="groovy" data-title="Groovy"> kotlin { jvmToolchain { languageVersion.set(JavaLanguageVersion.of(<MAJOR_JDK_VERSION>)) // "8" } } </div></div></div><p id="jc6ksd_354">Note that setting a toolchain via the <code class="code" id="jc6ksd_387">kotlin</code> extension will update the toolchain for Java compile tasks as well.</p><p id="jc6ksd_355">You can set a toolchain via the <code class="code" id="jc6ksd_388">java</code> extension, and Kotlin compilation tasks will use it:</p><div class="code-block" data-lang="kotlin"> java { toolchain { languageVersion.set(JavaLanguageVersion.of(<MAJOR_JDK_VERSION>)) // "8" } } </div><p id="jc6ksd_357">For information about setting any JDK version for <code class="code" id="jc6ksd_389">KotlinCompile</code> tasks, look through the docs about <a href="gradle-configure-project.html#set-jdk-version-with-the-task-dsl" id="jc6ksd_390">setting the JDK version with the Task DSL</a>.</p><p id="jc6ksd_358">For Gradle versions from 6.1 to 6.6, <a href="#ability-to-specify-jdk-home-with-useskotlinjavatoolchain-interface" id="jc6ksd_391">use the <code class="code" id="jc6ksd_392">UsesKotlinJavaToolchain</code> interface to set the JDK home</a>.</p></section><section class="chapter"><h3 id="ability-to-specify-jdk-home-with-useskotlinjavatoolchain-interface" data-toc="ability-to-specify-jdk-home-with-useskotlinjavatoolchain-interface">Ability to specify JDK home with UsesKotlinJavaToolchain interface</h3><p id="jc6ksd_393">All Kotlin tasks that support setting the JDK via <a href="gradle-compiler-options.html" id="jc6ksd_397"><code class="code" id="jc6ksd_400">kotlinOptions</code></a> now implement the <code class="code" id="jc6ksd_398">UsesKotlinJavaToolchain</code> interface. To set the JDK home, put a path to your JDK and replace the <code class="code" id="jc6ksd_399"><JDK_VERSION></code> placeholder:</p><div class="tabs" id="jc6ksd_394" data-group="build-script" data-anchors="[jc6ksd_401,jc6ksd_402]"><div class="tabs__content" data-gtm="tab" id="jc6ksd_401" data-sync-tabs="kotlin" data-title="Kotlin"><div class="code-block" data-lang="kotlin" data-title="Kotlin"> project.tasks .withType<UsesKotlinJavaToolchain>() .configureEach { it.kotlinJavaToolchain.jdk.use( "/path/to/local/jdk", JavaVersion.<LOCAL_JDK_VERSION> ) } </div></div><div class="tabs__content" data-gtm="tab" id="jc6ksd_402" data-sync-tabs="groovy" data-title="Groovy"><div class="code-block" data-lang="groovy" data-title="Groovy"> project.tasks .withType(UsesKotlinJavaToolchain.class) .configureEach { it.kotlinJavaToolchain.jdk.use( '/path/to/local/jdk', JavaVersion.<LOCAL_JDK_VERSION> ) } </div></div></div><p id="jc6ksd_395">Use the <code class="code" id="jc6ksd_405">UsesKotlinJavaToolchain</code> interface for Gradle versions from 6.1 to 6.6. Starting from Gradle 6.7, use the <a href="#support-for-java-toolchains" id="jc6ksd_406">Java toolchains</a> instead.</p><p id="jc6ksd_396">When using this feature, note that <a href="kapt.html#run-kapt-tasks-in-parallel" id="jc6ksd_407">kapt task workers</a> will only use <a href="https://docs.gradle.org/current/userguide/worker_api.html#changing_the_isolation_mode" id="jc6ksd_408" data-external="true" rel="noopener noreferrer">process isolation mode</a>, and the <code class="code" id="jc6ksd_409">kapt.workers.isolation</code> property will be ignored.</p></section><section class="chapter"><h3 id="easier-way-to-explicitly-specify-kotlin-daemon-jvm-arguments" data-toc="easier-way-to-explicitly-specify-kotlin-daemon-jvm-arguments">Easier way to explicitly specify Kotlin daemon JVM arguments</h3><p id="jc6ksd_410">In Kotlin 1.5.30, there's a new logic for the Kotlin daemon's JVM arguments. Each of the options in the following list overrides the ones that came before it:</p><ul class="list _bullet" id="jc6ksd_411"><li class="list__item" id="jc6ksd_413"><p id="jc6ksd_418">If nothing is specified, the Kotlin daemon inherits arguments from the Gradle daemon (as before). For example, in the <code class="code" id="jc6ksd_420">gradle.properties</code> file:</p><div class="code-block" data-lang="none"> org.gradle.jvmargs=-Xmx1500m -Xms=500m </div></li><li class="list__item" id="jc6ksd_414"><p id="jc6ksd_421">If the Gradle daemon's JVM arguments have the <code class="code" id="jc6ksd_423">kotlin.daemon.jvm.options</code> system property, use it as before:</p><div class="code-block" data-lang="none"> org.gradle.jvmargs=-Dkotlin.daemon.jvm.options=-Xmx1500m -Xms=500m </div></li><li class="list__item" id="jc6ksd_415"><p id="jc6ksd_424">You can add the<code class="code" id="jc6ksd_426">kotlin.daemon.jvmargs</code> property in the <code class="code" id="jc6ksd_427">gradle.properties</code> file:</p><div class="code-block" data-lang="none"> kotlin.daemon.jvmargs=-Xmx1500m -Xms=500m </div></li><li class="list__item" id="jc6ksd_416"><p id="jc6ksd_428">You can specify arguments in the <code class="code" id="jc6ksd_430">kotlin</code> extension:</p><div class="tabs" id="jc6ksd_429" data-group="build-script" data-anchors="[jc6ksd_431,jc6ksd_432]"><div class="tabs__content" data-gtm="tab" id="jc6ksd_431" data-sync-tabs="kotlin" data-title="Kotlin"><div class="code-block" data-lang="kotlin" data-title="Kotlin"> kotlin { kotlinDaemonJvmArgs = listOf("-Xmx486m", "-Xms256m", "-XX:+UseParallelGC") } </div></div><div class="tabs__content" data-gtm="tab" id="jc6ksd_432" data-sync-tabs="groovy" data-title="Groovy"><div class="code-block" data-lang="groovy" data-title="Groovy"> kotlin { kotlinDaemonJvmArgs = ["-Xmx486m", "-Xms256m", "-XX:+UseParallelGC"] } </div></div></div></li><li class="list__item" id="jc6ksd_417"><p id="jc6ksd_435">You can specify arguments for a specific task:</p><div class="tabs" id="jc6ksd_436" data-group="build-script" data-anchors="[jc6ksd_438,jc6ksd_439]"><div class="tabs__content" data-gtm="tab" id="jc6ksd_438" data-sync-tabs="kotlin" data-title="Kotlin"><div class="code-block" data-lang="kotlin" data-title="Kotlin"> tasks .matching { it.name == "compileKotlin" && it is CompileUsingKotlinDaemon } .configureEach { (this as CompileUsingKotlinDaemon).kotlinDaemonJvmArguments.set(listOf("-Xmx486m", "-Xms256m", "-XX:+UseParallelGC")) } </div></div><div class="tabs__content" data-gtm="tab" id="jc6ksd_439" data-sync-tabs="groovy" data-title="Groovy"><div class="code-block" data-lang="groovy" data-title="Groovy"> tasks .matching { it.name == "compileKotlin" && it instanceof CompileUsingKotlinDaemon } .configureEach { kotlinDaemonJvmArguments.set(["-Xmx1g", "-Xms512m"]) } </div></div></div><aside class="prompt" data-type="note" data-title="" id="jc6ksd_437"><p id="jc6ksd_442">In this case a new Kotlin daemon instance can start on task execution. Learn more about <a href="gradle-compilation-and-caches.html#setting-kotlin-daemon-s-jvm-arguments" id="jc6ksd_443">the Kotlin daemon's interactions with JVM arguments</a>.</p></aside></li></ul><p id="jc6ksd_412">For more information about the Kotlin daemon, see <a href="gradle-compilation-and-caches.html#the-kotlin-daemon-and-how-to-use-it-with-gradle" id="jc6ksd_444">the Kotlin daemon and using it with Gradle</a>.</p></section></section><section class="chapter"><h2 id="standard-library" data-toc="standard-library">Standard library</h2><p id="jc6ksd_445">Kotlin 1.5.30 is bringing improvements to the standard library's <code class="code" id="jc6ksd_451">Duration</code> and <code class="code" id="jc6ksd_452">Regex</code> APIs:</p><ul class="list _bullet" id="jc6ksd_446"><li class="list__item" id="jc6ksd_453"><p><a href="#changing-duration-tostring-output" id="jc6ksd_457">Changing <code class="code" id="jc6ksd_458">Duration.toString()</code> output</a></p></li><li class="list__item" id="jc6ksd_454"><p><a href="#parsing-duration-from-string" id="jc6ksd_459">Parsing Duration from String</a></p></li><li class="list__item" id="jc6ksd_455"><p><a href="#matching-with-regex-at-a-particular-position" id="jc6ksd_460">Matching with Regex at a particular position</a></p></li><li class="list__item" id="jc6ksd_456"><p><a href="#splitting-regex-to-a-sequence" id="jc6ksd_461">Splitting Regex to a sequence</a></p></li></ul><section class="chapter"><h3 id="changing-duration-tostring-output" data-toc="changing-duration-tostring-output">Changing Duration.toString() output</h3><aside class="prompt" data-type="warning" data-title="" id="jc6ksd_462"><p id="jc6ksd_469">The Duration API is <a href="components-stability.html" id="jc6ksd_470">Experimental</a>. It may be dropped or changed at any time. Use it only for evaluation purposes. We would appreciate hearing your feedback on it in <a href="https://youtrack.jetbrains.com/issues/KT" id="jc6ksd_471" data-external="true" rel="noopener noreferrer">YouTrack</a>.</p></aside><p id="jc6ksd_463">Before Kotlin 1.5.30, the <a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.time/-duration/to-string.html" id="jc6ksd_472" data-external="true" rel="noopener noreferrer"><code class="code" id="jc6ksd_477">Duration.toString()</code></a> function would return a string representation of its argument expressed in the unit that yielded the most compact and readable number value. From now on, it will return a string value expressed as a combination of numeric components, each in its own unit. Each component is a number followed by the unit's abbreviated name: <code class="code" id="jc6ksd_473">d</code>, <code class="code" id="jc6ksd_474">h</code>, <code class="code" id="jc6ksd_475">m</code>, <code class="code" id="jc6ksd_476">s</code>. For example:</p><div class="table-wrapper"><table class="wide" id="jc6ksd_464"><thead><tr class="ijRowHead" id="jc6ksd_478"><th id="jc6ksd_486"><p><span class="control" id="jc6ksd_489">Example of function call</span></p></th><th id="jc6ksd_487"><p><span class="control" id="jc6ksd_490">Previous output</span></p></th><th id="jc6ksd_488"><p><span class="control" id="jc6ksd_491">Current output</span></p></th></tr></thead><tbody><tr id="jc6ksd_479"><td id="jc6ksd_492"><p>Duration.days(45).toString()</p></td><td id="jc6ksd_493"><p><code class="code" id="jc6ksd_495">45.0d</code></p></td><td id="jc6ksd_494"><p><code class="code" id="jc6ksd_496">45d</code></p></td></tr><tr id="jc6ksd_480"><td id="jc6ksd_497"><p>Duration.days(1.5).toString()</p></td><td id="jc6ksd_498"><p><code class="code" id="jc6ksd_500">36.0h</code></p></td><td id="jc6ksd_499"><p><code class="code" id="jc6ksd_501">1d 12h</code></p></td></tr><tr id="jc6ksd_481"><td id="jc6ksd_502"><p>Duration.minutes(1230).toString()</p></td><td id="jc6ksd_503"><p><code class="code" id="jc6ksd_505">20.5h</code></p></td><td id="jc6ksd_504"><p><code class="code" id="jc6ksd_506">20h 30m</code></p></td></tr><tr id="jc6ksd_482"><td id="jc6ksd_507"><p>Duration.minutes(2415).toString()</p></td><td id="jc6ksd_508"><p><code class="code" id="jc6ksd_510">40.3h</code></p></td><td id="jc6ksd_509"><p><code class="code" id="jc6ksd_511">1d 16h 15m</code></p></td></tr><tr id="jc6ksd_483"><td id="jc6ksd_512"><p>Duration.minutes(920).toString()</p></td><td id="jc6ksd_513"><p><code class="code" id="jc6ksd_515">920m</code></p></td><td id="jc6ksd_514"><p><code class="code" id="jc6ksd_516">15h 20m</code></p></td></tr><tr id="jc6ksd_484"><td id="jc6ksd_517"><p>Duration.seconds(1.546).toString()</p></td><td id="jc6ksd_518"><p><code class="code" id="jc6ksd_520">1.55s</code></p></td><td id="jc6ksd_519"><p><code class="code" id="jc6ksd_521">1.546s</code></p></td></tr><tr id="jc6ksd_485"><td id="jc6ksd_522"><p>Duration.milliseconds(25.12).toString()</p></td><td id="jc6ksd_523"><p><code class="code" id="jc6ksd_525">25.1ms</code></p></td><td id="jc6ksd_524"><p><code class="code" id="jc6ksd_526">25.12ms</code></p></td></tr></tbody></table></div><p id="jc6ksd_465">The way negative durations are represented has also been changed. A negative duration is prefixed with a minus sign (<code class="code" id="jc6ksd_527">-</code>), and if it consists of multiple components, it is surrounded with parentheses: <code class="code" id="jc6ksd_528">-12m</code> and <code class="code" id="jc6ksd_529">-(1h 30m)</code>.</p><p id="jc6ksd_466">Note that small durations of less than one second are represented as a single number with one of the subsecond units. For example, <code class="code" id="jc6ksd_530">ms</code> (milliseconds), <code class="code" id="jc6ksd_531">us</code> (microseconds), or <code class="code" id="jc6ksd_532">ns</code> (nanoseconds): <code class="code" id="jc6ksd_533">140.884ms</code>, <code class="code" id="jc6ksd_534">500us</code>, <code class="code" id="jc6ksd_535">24ns</code>. Scientific notation is no longer used to represent them.</p><p id="jc6ksd_467">If you want to express duration in a single unit, use the overloaded <code class="code" id="jc6ksd_536">Duration.toString(unit, decimals)</code> function.</p><aside class="prompt" data-type="note" data-title="" id="jc6ksd_468"><p id="jc6ksd_537">We recommend using <a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.time/-duration/to-iso-string.html" id="jc6ksd_538" data-external="true" rel="noopener noreferrer"><code class="code" id="jc6ksd_542">Duration.toIsoString()</code></a> in certain cases, including serialization and interchange. <code class="code" id="jc6ksd_539">Duration.toIsoString()</code> uses the stricter <a href="https://www.iso.org/iso-8601-date-and-time-format.html" id="jc6ksd_540" data-external="true" rel="noopener noreferrer">ISO-8601</a> format instead of <code class="code" id="jc6ksd_541">Duration.toString()</code>.</p></aside></section><section class="chapter"><h3 id="parsing-duration-from-string" data-toc="parsing-duration-from-string">Parsing Duration from String</h3><aside class="prompt" data-type="warning" data-title="" id="jc6ksd_543"><p id="jc6ksd_550">The Duration API is <a href="components-stability.html" id="jc6ksd_551">Experimental</a>. It may be dropped or changed at any time. Use it only for evaluation purposes. We would appreciate hearing your feedback on it in <a href="https://github.com/Kotlin/KEEP/issues/190" id="jc6ksd_552" data-external="true" rel="noopener noreferrer">this issue</a>.</p></aside><p id="jc6ksd_544">In Kotlin 1.5.30, there are new functions in the Duration API:</p><ul class="list _bullet" id="jc6ksd_545"><li class="list__item" id="jc6ksd_553"><p><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.time/-duration/parse.html" id="jc6ksd_556" data-external="true" rel="noopener noreferrer"><code class="code" id="jc6ksd_558">parse()</code></a>, which supports parsing the outputs of: </p><ul class="list _bullet" id="jc6ksd_557"><li class="list__item" id="jc6ksd_559"><p><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.time/-duration/to-string.html" id="jc6ksd_562" data-external="true" rel="noopener noreferrer"><code class="code" id="jc6ksd_563">toString()</code></a>.</p></li><li class="list__item" id="jc6ksd_560"><p><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.time/-duration/to-string.html" id="jc6ksd_564" data-external="true" rel="noopener noreferrer"><code class="code" id="jc6ksd_565">toString(unit, decimals)</code></a>.</p></li><li class="list__item" id="jc6ksd_561"><p><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.time/-duration/to-iso-string.html" id="jc6ksd_566" data-external="true" rel="noopener noreferrer"><code class="code" id="jc6ksd_567">toIsoString()</code></a>.</p></li></ul></li><li class="list__item" id="jc6ksd_554"><p><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.time/-duration/parse-iso-string.html" id="jc6ksd_568" data-external="true" rel="noopener noreferrer"><code class="code" id="jc6ksd_570">parseIsoString()</code></a>, which only parses from the format produced by <code class="code" id="jc6ksd_569">toIsoString()</code>.</p></li><li class="list__item" id="jc6ksd_555"><p><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.time/-duration/parse-or-null.html" id="jc6ksd_571" data-external="true" rel="noopener noreferrer"><code class="code" id="jc6ksd_575">parseOrNull()</code></a> and <a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.time/-duration/parse-iso-string-or-null.html" id="jc6ksd_572" data-external="true" rel="noopener noreferrer"><code class="code" id="jc6ksd_576">parseIsoStringOrNull()</code></a>, which behave like the functions above but return <code class="code" id="jc6ksd_573">null</code> instead of throwing <code class="code" id="jc6ksd_574">IllegalArgumentException</code> on invalid duration formats.</p></li></ul><p id="jc6ksd_546">Here are some examples of <code class="code" id="jc6ksd_577">parse()</code> and <code class="code" id="jc6ksd_578">parseOrNull()</code> usages:</p><div class="code-block" data-lang="kotlin" data-runnable="true" data-min-compiler-version="1.5"> import kotlin.time.Duration import kotlin.time.ExperimentalTime @ExperimentalTime fun main() { //sampleStart val isoFormatString = "PT1H30M" val defaultFormatString = "1h 30m" val singleUnitFormatString = "1.5h" val invalidFormatString = "1 hour 30 minutes" println(Duration.parse(isoFormatString)) // "1h 30m" println(Duration.parse(defaultFormatString)) // "1h 30m" println(Duration.parse(singleUnitFormatString)) // "1h 30m" //println(Duration.parse(invalidFormatString)) // throws exception println(Duration.parseOrNull(invalidFormatString)) // "null" //sampleEnd } </div><p id="jc6ksd_548">And here are some examples of <code class="code" id="jc6ksd_579">parseIsoString()</code> and <code class="code" id="jc6ksd_580">parseIsoStringOrNull()</code> usages:</p><div class="code-block" data-lang="kotlin" data-runnable="true" data-min-compiler-version="1.5"> import kotlin.time.Duration import kotlin.time.ExperimentalTime @ExperimentalTime fun main() { //sampleStart val isoFormatString = "PT1H30M" val defaultFormatString = "1h 30m" println(Duration.parseIsoString(isoFormatString)) // "1h 30m" //println(Duration.parseIsoString(defaultFormatString)) // throws exception println(Duration.parseIsoStringOrNull(defaultFormatString)) // "null" //sampleEnd } </div></section><section class="chapter"><h3 id="matching-with-regex-at-a-particular-position" data-toc="matching-with-regex-at-a-particular-position">Matching with Regex at a particular position</h3><aside class="prompt" data-type="warning" data-title="" id="jc6ksd_581"><p id="jc6ksd_587"><code class="code" id="jc6ksd_588">Regex.matchAt()</code> and <code class="code" id="jc6ksd_589">Regex.matchesAt()</code> functions are <a href="components-stability.html" id="jc6ksd_590">Experimental</a>. They may be dropped or changed at any time. Use them only for evaluation purposes. We would appreciate hearing your feedback on them in <a href="https://youtrack.jetbrains.com/issue/KT-34021" id="jc6ksd_591" data-external="true" rel="noopener noreferrer">YouTrack</a>.</p></aside><p id="jc6ksd_582">The new <code class="code" id="jc6ksd_592">Regex.matchAt()</code> and <code class="code" id="jc6ksd_593">Regex.matchesAt()</code> functions provide a way to check whether a regex has an exact match at a particular position in a <code class="code" id="jc6ksd_594">String</code> or <code class="code" id="jc6ksd_595">CharSequence</code>.</p><p id="jc6ksd_583"><code class="code" id="jc6ksd_596">matchesAt()</code> returns a boolean result:</p><div class="code-block" data-lang="kotlin" data-runnable="true" data-min-compiler-version="1.5"> fun main(){ //sampleStart val releaseText = "Kotlin 1.5.30 is released!" // regular expression: one digit, dot, one digit, dot, one or more digits val versionRegex = "\\d[.]\\d[.]\\d+".toRegex() println(versionRegex.matchesAt(releaseText, 0)) // "false" println(versionRegex.matchesAt(releaseText, 7)) // "true" //sampleEnd } </div><p id="jc6ksd_585"><code class="code" id="jc6ksd_597">matchAt()</code> returns the match if one is found or <code class="code" id="jc6ksd_598">null</code> if one isn't:</p><div class="code-block" data-lang="kotlin" data-runnable="true" data-min-compiler-version="1.5"> fun main(){ //sampleStart val releaseText = "Kotlin 1.5.30 is released!" val versionRegex = "\\d[.]\\d[.]\\d+".toRegex() println(versionRegex.matchAt(releaseText, 0)) // "null" println(versionRegex.matchAt(releaseText, 7)?.value) // "1.5.30" //sampleEnd } </div></section><section class="chapter"><h3 id="splitting-regex-to-a-sequence" data-toc="splitting-regex-to-a-sequence">Splitting Regex to a sequence</h3><aside class="prompt" data-type="warning" data-title="" id="jc6ksd_599"><p id="jc6ksd_604"><code class="code" id="jc6ksd_605">Regex.splitToSequence()</code> and <code class="code" id="jc6ksd_606">CharSequence.splitToSequence(Regex)</code> functions are <a href="components-stability.html" id="jc6ksd_607">Experimental</a>. They may be dropped or changed at any time. Use them only for evaluation purposes. We would appreciate hearing your feedback on them in <a href="https://youtrack.jetbrains.com/issue/KT-23351" id="jc6ksd_608" data-external="true" rel="noopener noreferrer">YouTrack</a>.</p></aside><p id="jc6ksd_600">The new <code class="code" id="jc6ksd_609">Regex.splitToSequence()</code> function is a lazy counterpart of <a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/-regex/split.html" id="jc6ksd_610" data-external="true" rel="noopener noreferrer"><code class="code" id="jc6ksd_612">split()</code></a>. It splits the string around matches of the given regex, but it returns the result as a <a href="sequences.html" id="jc6ksd_611">Sequence</a> so that all operations on this result are executed lazily.</p><div class="code-block" data-lang="kotlin" data-runnable="true" data-min-compiler-version="1.5"> fun main(){ //sampleStart val colorsText = "green, red , brown&blue, orange, pink&green" val regex = "[,\\s]+".toRegex() val mixedColor = regex.splitToSequence(colorsText) .onEach { println(it) } .firstOrNull { it.contains('&') } println(mixedColor) // "brown&blue" //sampleEnd } </div><p id="jc6ksd_602">A similar function was also added to <code class="code" id="jc6ksd_613">CharSequence</code>:</p><div class="code-block" data-lang="kotlin"> val mixedColor = colorsText.splitToSequence(regex) </div></section></section><section class="chapter"><h2 id="serialization-1-3-0-rc" data-toc="serialization-1-3-0-rc">Serialization 1.3.0-RC</h2><p id="jc6ksd_614"><code class="code" id="jc6ksd_617">kotlinx.serialization</code> <a href="https://github.com/Kotlin/kotlinx.serialization/releases/tag/v1.3.0-RC" id="jc6ksd_618" data-external="true" rel="noopener noreferrer">1.3.0-RC</a> is here with new JSON serialization capabilities:</p><ul class="list _bullet" id="jc6ksd_615"><li class="list__item" id="jc6ksd_619"><p>Java IO streams serialization</p></li><li class="list__item" id="jc6ksd_620"><p>Property-level control over default values</p></li><li class="list__item" id="jc6ksd_621"><p>An option to exclude null values from serialization</p></li><li class="list__item" id="jc6ksd_622"><p>Custom class discriminators in polymorphic serialization</p></li></ul><p id="jc6ksd_616">Learn more in the <a href="https://github.com/Kotlin/kotlinx.serialization/releases/tag/v1.3.0-RC" id="jc6ksd_623" data-external="true" rel="noopener noreferrer">changelog</a>.</p></section><div class="last-modified">Last modified: 27 November 2024</div><div data-feedback-placeholder="true"></div><div class="navigation-links _bottom"><a href="whatsnew16.html" class="navigation-links__prev">What's new in Kotlin 1.6.0</a><a href="whatsnew1520.html" class="navigation-links__next">What's new in Kotlin 1.5.20</a></div></article><div id="disqus_thread"></div></div></section></main></div><script src="static/v3/app.js"></script></body></html>