Kotlin Help

What's new in Kotlin 2.3.0-Beta1

Released: October 7, 2025

The Kotlin 2.3.0-Beta1 release is out! Here are some details of this EAP release:

IDE support

The Kotlin plugins that support 2.3.0-Beta1 are bundled in the latest versions of IntelliJ IDEA and Android Studio. You don't need to update the Kotlin plugin in your IDE. All you need to do is change the Kotlin version to 2.3.0-Beta1 in your build scripts.

See Update to a new release for details.

Stable features

In previous Kotlin releases, several new language and standard library features were introduced as Experimental and Beta. We're happy to announce that in this release, the following features become Stable:

See the full list of Kotlin language design features and proposals.

Language

Kotlin 2.3.0-Beta1 introduces a new check mechanism for unused return values and focuses on improving context-sensitive resolution.

Unused return value checker

Kotlin 2.3.0-Beta1 introduces a new feature, the unused return value checker. This feature warns you when an expression returns a value other than Unit or Nothing and isn't passed to a function, checked in a condition, or used otherwise.

You can use it to catch bugs where a function call produces a meaningful result, but the result is silently dropped, which can lead to unexpected behavior or hard-to-trace issues.

Consider the following example:

fun formatGreeting(name: String): String { if (name.isBlank()) return "Hello, anonymous user!" if (!name.contains(' ')) { // The checker reports a warning that this result is ignored "Hello, " + name.replaceFirstChar(Char::titlecase) + "!" } val (first, last) = name.split(' ') return "Hello, $first! Or should I call you Dr. $last?" }

In this example, a string is created but never used, so the checker reports it as an ignored result.

This feature is Experimental. To opt in, add the following compiler option to your build.gradle.kts file:

kotlin { compilerOptions { freeCompilerArgs.add("-Xreturn-value-checker=check") } }

With this option, the checker only reports ignored results from expressions that are marked, like most functions in the Kotlin standard library.

To mark your functions, use the @MustUseReturnValues annotation to mark the scope on which you want the checker to report ignored return values.

For example, you can mark an entire file:

// Marks all functions and classes in this file so the checker reports unused return values @file:MustUseReturnValues package my.project fun someFunction(): String

Or a specific class:

// Marks all functions in this class so the checker reports unused return values @MustUseReturnValues class Greeter { fun greet(name: String): String = "Hello, $name" } fun someFunction(): Int = ...

You can also mark your entire project using the full mode. To do so, add the following compiler option to your build.gradle.kts file:

kotlin { compilerOptions { freeCompilerArgs.add("-Xreturn-value-checker=full") } }

In this mode, Kotlin automatically treats your compiled files as if they are annotated with @MustUseReturnValues, so the checker applies to all return values from your project's functions.

You can suppress warnings on specific functions by marking them with the @IgnorableReturnValue annotation. Annotate functions where ignoring the result is common and expected, such as MutableList.add:

@IgnorableReturnValue fun <T> MutableList<T>.addAndIgnoreResult(element: T): Boolean { return add(element) }

You can suppress a warning without marking the function itself as ignorable. To do this, assign the result to a special unnamed variable with an underscore syntax (_):

// Non-ignorable function fun computeValue(): Int = 42 fun main() { // Reports a warning: result is ignored computeValue() // Suppresses the warning only at this call site with a special unused variable val _ = computeValue() }

We would appreciate your feedback in YouTrack. For more information, see the feature's KEEP.

Changes to context-sensitive resolution

Context-sensitive resolution is still Experimental, but we continue improving the feature based on user feedback:

  • The sealed and enclosing supertypes of the current type are now considered as part of the contextual scope of the search. No other supertype scopes are considered.

  • In cases with type operators and equalities, the compiler now reports a warning if using context-sensitive resolution makes the resolution ambiguous. This can happen, for example, when a clashing declaration of a class is imported.

For details, see the full text of the current proposal in KEEP.

Kotlin/Native: type checks on generic type boundaries in debug mode

Starting with Kotlin 2.3.0-Beta1, type checks on generic type boundaries are enabled by default in debug mode, helping you find errors related to unchecked casts earlier. This change improves safety and makes debugging of invalid generic casts more predictable across platforms.

Previously, unchecked casts that led to heap pollution and violation of memory safety could go unnoticed in Kotlin/Native. Now, such cases consistently fail with a runtime cast error, similar to Kotlin/JVM or Kotlin/JS. For example:

fun main() { val list = listOf("hello") val x = (list as List<Int>)[0] println(x) // Now throws a ClassCastException error }

This code used to print 6; now it throws a ClassCastException error in debug mode, as expected.

For more information, see Type checks and casts.

Gradle: Kotlin/JVM compilation uses Build tools API by default

In Kotlin 2.3.0-Beta1, Kotlin/JVM compilation in the Kotlin Gradle plugin uses the Build tools API (BTA) by default. This is a significant change in the internal compilation infrastructure.

We've made BTA the default in this release to allow time for testing. We expect everything to continue working as it did before. If you notice any issues, share your feedback in our issue tracker.

We plan to disable BTA again for Kotlin/JVM compilation in 2.3.0-Beta2 and fully enable it for all users starting with Kotlin 2.3.20.

07 October 2025