Skip to content

Kotlin 2.2.20 の新機能

リリース日: 2025年9月10日

Kotlinについてのご意見をお聞かせください! Kotlin開発者アンケートにご協力ください。 わずか10分ほどで完了し、皆様からのフィードバックは言語、ツール、エコシステムの改善に役立てられます。

Kotlin 2.2.20 がリリースされ、Web開発に重要な変更が加えられました。 Kotlin/Wasm は現在ベータ版であり、JavaScript相互運用における例外処理の改善npm依存関係管理組み込みのブラウザデバッグサポート、 およびjsおよびwasmJsターゲット用の新しい共有ソースセットが含まれています。

さらに、主なハイライトは次のとおりです。

IDEサポート

Kotlin 2.2.20をサポートするKotlinプラグインは、IntelliJ IDEAおよびAndroid Studioの最新バージョンにバンドルされています。 更新するには、ビルドスクリプトでKotlinのバージョンを2.2.20に変更するだけです。

詳細は新しいリリースへの更新をご覧ください。

言語

Kotlin 2.2.20では、Kotlin 2.3.0で計画されている今後の言語機能を試すことができます。これには、 suspend関数型を持つオーバーロードにラムダを渡す際のオーバーロード解決の改善明示的な戻り値型を持つ式本体でのreturn文のサポートが含まれます。このリリースには、 when`式のデータフローに基づく網羅性チェック](#data-flow-based-exhaustiveness-checks-for-when-expressions)、 [reified `Throwable`キャッチ、およびKotlinコントラクトの改善も含まれています。

suspend関数型を持つラムダのオーバーロード解決の改善

これまで、通常の関数型とsuspend関数型の両方で関数をオーバーロードすると、ラムダを渡す際にオーバーロード解決の曖昧性エラーが発生していました。明示的な型キャストでこのエラーを回避できましたが、コンパイラはNo cast neededという警告を誤って報告していました。

kotlin
// Defines two overloads
fun transform(block: () -> Int) {}
fun transform(block: suspend () -> Int) {}

fun test() {
    // Fails with overload resolution ambiguity
    transform({ 42 })

    // Uses an explicit cast, but the compiler incorrectly reports 
    // a "No cast needed" warning
    transform({ 42 } as () -> Int)
}

この変更により、通常の関数型とsuspend関数型の両方のオーバーロードを定義した場合、キャストなしのラムダは通常のオーバーロードに解決されます。suspendキーワードを使用して、明示的にsuspendオーバーロードに解決してください。

kotlin
// Resolves to transform(() -> Int)
transform({ 42 })

// Resolves to transform(suspend () -> Int)
transform(suspend { 42 })

この挙動はKotlin 2.3.0でデフォルトで有効になります。今すぐテストするには、以下のコンパイラオプションを使用して言語バージョンを2.3に設定してください。

kotlin
-language-version 2.3

または、build.gradle(.kts)ファイルで設定してください。

kotlin
kotlin {
    compilerOptions {
        languageVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_3)
    }
}

課題トラッカーYouTrackでフィードバックをお寄せいただけると幸いです。

明示的な戻り値型を持つ式本体でのreturn文のサポート

これまで、式本体でreturnを使用すると、関数の戻り値型がNothingと推論される可能性があったため、コンパイラエラーが発生していました。

kotlin
fun example() = return 42
// Error: Returns are prohibited for functions with an expression body

この変更により、戻り値型が明示的に記述されている限り、式本体でreturnを使用できるようになりました。

kotlin
// Specifies the return type explicitly
fun getDisplayNameOrDefault(userId: String?): String = getDisplayName(userId ?: return "default")

// Fails because it doesn't specify the return type explicitly
fun getDisplayNameOrDefault(userId: String?) = getDisplayName(userId ?: return "default")

同様に、式本体を持つ関数内のラムダおよびネストされた式内のreturn文は、意図せずにコンパイルされていました。Kotlinは、戻り値型が明示的に指定されている限り、これらのケースをサポートするようになりました。明示的な戻り値型がないケースはKotlin 2.3.0で非推奨になります。

kotlin
// Return type isn't explicitly specified, and the return statement is inside a lambda
// which will be deprecated
fun returnInsideLambda() = run { return 42 }

// Return type isn't explicitly specified, and the return statement is inside the initializer
// of a local variable, which will be deprecated
fun returnInsideIf() = when {
    else -> {
        val result = if (someCondition()) return "" else "value"
        result
    }
}

この挙動はKotlin 2.3.0でデフォルトで有効になります。今すぐテストするには、以下のコンパイラオプションを使用して言語バージョンを2.3に設定してください。

kotlin
-language-version 2.3

または、build.gradle(.kts)ファイルで設定してください。

kotlin
kotlin {
    compilerOptions {
        languageVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_3)
    }
}

課題トラッカーYouTrackでフィードバックをお寄せいただけると幸いです。

Experimental

when式のデータフローに基づく網羅性チェック

Kotlin 2.2.20では、when式のデータフローに基づく網羅性チェックが導入されました。 これまで、コンパイラのチェックはwhen式自体に限定されており、冗長なelseブランチを追加せざるを得ないことがよくありました。 このアップデートにより、コンパイラは以前の条件チェックと早期リターンを追跡するようになり、冗長なelseブランチを削除できるようになりました。

たとえば、コンパイラはif条件が満たされたときに関数がリターンすることを認識するため、when式は残りのケースを処理するだけで済みます。

kotlin
enum class UserRole { ADMIN, MEMBER, GUEST }

fun getPermissionLevel(role: UserRole): Int {
    // Covers the Admin case outside of the when expression
    if (role == UserRole.ADMIN) return 99

    return when (role) {
        UserRole.MEMBER -> 10
        UserRole.GUEST -> 1
        // このelseブランチを含める必要はなくなりました 
        // else -> throw IllegalStateException()
    }
}

この機能はExperimentalです。 これを有効にするには、build.gradle(.kts)ファイルに以下のコンパイラオプションを追加してください。

kotlin
kotlin {
    compilerOptions {
        freeCompilerArgs.add("-Xdata-flow-based-exhaustiveness")
    }
}
Experimental

catch句におけるreified型のサポート

Kotlin 2.2.20では、コンパイラはinline関数のcatch句でreifiedジェネリック型パラメータの使用を許可するようになりました。

例を示します。

kotlin
inline fun <reified ExceptionType : Throwable> handleException(block: () -> Unit) {
    try {
        block()
        // この変更により、これが許可されるようになりました
    } catch (e: ExceptionType) {
        println("Caught specific exception: ${e::class.simpleName}")
    }
}

fun main() {
    // Tries to perform an action that might throw an IOException
    handleException<java.io.IOException> {
        throw java.io.IOException("File not found")
    }
    // Caught specific exception: IOException
}

これまで、inline関数でreified Throwable型をキャッチしようとするとエラーが発生していました。

この挙動はKotlin 2.4.0でデフォルトで有効になります。 今すぐ使用するには、build.gradle(.kts)ファイルに以下のコンパイラオプションを追加してください。

kotlin
kotlin {
    compilerOptions {
        freeCompilerArgs.add("-Xallow-reified-type-in-catch")
    }
}

Kotlinチームは、外部コントリビューターのIven Krall氏の貢献に感謝いたします。

Experimental

Kotlinコントラクトの改善

Kotlin 2.2.20では、Kotlinコントラクトにいくつかの改善が導入されました。これには以下が含まれます。

これらの改善はExperimentalです。オプトインするには、コントラクトを宣言する際に@OptIn(ExperimentalContracts::class)アノテーションを使用する必要があります。holdsInキーワードとreturnsNotNull()関数も@OptIn(ExperimentalExtendedContracts::class)アノテーションを必要とします。

これらの改善を使用するには、以下の各セクションで説明されているコンパイラオプションも追加する必要があります。

弊社の課題トラッカーでフィードバックをお寄せいただけると幸いです。

コントラクト型アサーションにおけるジェネリクスのサポート

ジェネリック型に対して型アサーションを実行するコントラクトを記述できるようになりました。

kotlin
import kotlin.contracts.*

sealed class Failure {
    class HttpError(val code: Int) : Failure()
    // Insert other failure types here
}

sealed class Result<out T, out F : Failure> {
    class Success<T>(val data: T) : Result<T, Nothing>()
    class Failed<F : Failure>(val failure: F) : Result<Nothing, F>()
}

@OptIn(ExperimentalContracts::class)
// コントラクトを使用してジェネリック型をアサート
fun <T, F : Failure> Result<T, F>.isHttpError(): Boolean {
    contract {
        returns(true) implies (this@isHttpError is Result.Failed<Failure.HttpError>)
    }
    return this is Result.Failed && this.failure is Failure.HttpError
}

この例では、コントラクトがResultオブジェクトに対して型アサーションを実行し、コンパイラが安全にスマートキャストしてアサートされたジェネリック型にすることを可能にします。

この機能はExperimentalです。オプトインするには、build.gradle(.kts)ファイルに以下のコンパイラオプションを追加してください。

kotlin
kotlin {
    compilerOptions {
        freeCompilerArgs.add("-Xallow-contracts-on-more-functions")
    }
}

プロパティアクセサーおよび特定の演算子関数内でのコントラクトのサポート

プロパティアクセサーと特定の演算子関数内でコントラクトを定義できるようになりました。 これにより、より多くの種類の宣言でコントラクトを使用できるようになり、柔軟性が向上します。

たとえば、ゲッター内でコントラクトを使用して、レシーバーオブジェクトのスマートキャストを有効にできます。

kotlin
import kotlin.contracts.*

val Any.isHelloString: Boolean
    get() {
        @OptIn(ExperimentalContracts::class)
        // ゲッターがtrueを返したときにレシーバーをStringにスマートキャストできるようにする
        contract { returns(true) implies (this@isHelloString is String) }
        return "hello" == this
    }

fun printIfHelloString(x: Any) {
    if (x.isHelloString) {
        // レシーバーをStringにスマートキャストした後に長さを出力
        println(x.length)
        // 5
    }
}

さらに、以下の演算子関数でコントラクトを使用できます。

  • invoke
  • contains
  • rangeTorangeUntil
  • componentN
  • iterator
  • unaryPlusunaryMinusnot
  • incdec

ここでは、演算子関数でコントラクトを使用してラムダ内の変数の初期化を保証する例を示します。

kotlin
import kotlin.contracts.*

class Runner {
    @OptIn(ExperimentalContracts::class)
    // ラムダ内で割り当てられた変数の初期化を有効にする
    operator fun invoke(block: () -> Unit) {
        contract {
            callsInPlace(block, InvocationKind.EXACTLY_ONCE)
        }
        block()
    }
}

fun testOperator(runner: Runner) {
    val number: Int
    runner {
        number = 1
    }
    // コントラクトによって保証された確実な初期化後に値を出力
    println(number)
    // 1
}

この機能はExperimentalです。オプトインするには、build.gradle(.kts)ファイルに以下のコンパイラオプションを追加してください。

kotlin
kotlin {
    compilerOptions {
        freeCompilerArgs.add("-Xallow-contracts-on-more-functions")
    }
}

コントラクトにおけるreturnsNotNull()関数のサポート

Kotlin 2.2.20では、コントラクト用のreturnsNotNull()関数が導入されました。 この関数を使用して、特定の条件が満たされたときに、関数が非null値を返すことを保証できます。 これにより、nullableとnon-nullableの関数オーバーロードを個別に用意する代わりに、単一の簡潔な関数でコードを簡素化できます。

kotlin
import kotlin.contracts.*

@OptIn(ExperimentalContracts::class, ExperimentalExtendedContracts::class)
fun decode(encoded: String?): String? {
    contract {
        // 入力が非nullの場合に非nullの戻り値を保証
        (encoded != null) implies (returnsNotNull())
    }
    if (encoded == null) return null
    return java.net.URLDecoder.decode(encoded, "UTF-8")
}

fun useDecodedValue(s: String?) {
    // 戻り値がnullの場合があるため、セーフコールを使用
    decode(s)?.length
    if (s != null) {
        // スマートキャスト後、戻り値を非nullとして扱う
        decode(s).length
    }
}

この例では、decode()関数内のコントラクトにより、入力が非nullの場合にコンパイラが戻り値をスマートキャストできるようになり、余分なnullチェックや複数のオーバーロードの必要がなくなります。

この機能はExperimentalです。オプトインするには、build.gradle(.kts)ファイルに以下のコンパイラオプションを追加してください。

kotlin
kotlin {
    compilerOptions {
        freeCompilerArgs.add("-Xallow-condition-implies-returns-contracts")
    }
}

新しいholdsInキーワード

Kotlin 2.2.20では、コントラクト用の新しいholdsInキーワードが導入されました。 これを使用して、特定のラムダ内でブール条件がtrueであると仮定されることを保証できます。これにより、コントラクトを使用して条件付きスマートキャストを持つDSLを構築できます。

例を示します。

kotlin
import kotlin.contracts.*

@OptIn(ExperimentalContracts::class, ExperimentalExtendedContracts::class)
fun <T> T.alsoIf(condition: Boolean, block: (T) -> Unit): T {
    contract {
        // ラムダが最大1回実行されることを宣言
        callsInPlace(block, InvocationKind.AT_MOST_ONCE)
        // ラムダ内で条件がtrueであると仮定されることを宣言
        condition holdsIn block
    }
    if (condition) block(this)
    return this
}

fun useApplyIf(input: Any) {
    val result = listOf(1, 2, 3)
        .first()
        .alsoIf(input is Int) {
            // ラムダ内でinputパラメータがIntにスマートキャストされる
            // inputとリストの最初の要素の合計を出力
            println(input + it)
            // 2
        }
        .toString()
}

この機能はExperimentalです。オプトインするには、build.gradle(.kts)ファイルに以下のコンパイラオプションを追加してください。

kotlin
kotlin {
    compilerOptions {
        freeCompilerArgs.add("-Xallow-holdsin-contract")
    }
}
Experimental

Kotlin/JVM: when式でのinvokedynamicのサポート

Kotlin 2.2.20では、when式をinvokedynamicでコンパイルできるようになりました。これまで、複数の型チェックを含むwhen式は、バイトコードで長いinstanceofチェックの連鎖にコンパイルされていました。

現在では、以下の条件が満たされた場合、Javaのswitchステートメントによって生成されるバイトコードと同様に、invokedynamicwhen式で使用してより小さなバイトコードを生成できます。

  • elseを除くすべての条件がisまたはnullチェックであること。
  • 式にガード条件 (if)が含まれていないこと。
  • 条件に、変更可能なKotlinコレクション (MutableList) や関数型 (kotlin.Function1kotlin.Function2など) のように直接型チェックできない型が含まれていないこと。
  • else以外に少なくとも2つの条件があること。
  • すべてのブランチがwhen式の同じ主題をチェックしていること。

たとえば、以下のようになります。

kotlin
open class Example

class A : Example()
class B : Example()
class C : Example()

fun test(e: Example) = when (e) {
    // SwitchBootstraps.typeSwitchとinvokedynamicを使用
    is A -> 1
    is B -> 2
    is C -> 3
    else -> 0
}

この新機能が有効になると、この例のwhen式は、複数のinstanceofチェックの代わりに単一のinvokedynamic型スイッチにコンパイルされます。

この機能を有効にするには、JVMターゲット21以上でKotlinコードをコンパイルし、以下のコンパイラオプションを追加してください。

bash
-Xwhen-expressions=indy

または、build.gradle(.kts)ファイルのcompilerOptions {}ブロックに追加してください。

kotlin
kotlin {
    compilerOptions {
        freeCompilerArgs.add("-Xwhen-expressions=indy")
    }
}

この機能はExperimentalです。課題トラッカーYouTrackでフィードバックをお寄せいただけると幸いです。

Kotlin Multiplatform

Kotlin 2.2.20では、Kotlin Multiplatformに重要な変更が導入されました。Swiftエクスポートがデフォルトで利用可能になり、新しい共有ソースセットが追加され、共通依存関係を管理する新しいアプローチを試すことができます。

Experimental

Swiftエクスポートがデフォルトで利用可能に

Kotlin 2.2.20では、Swiftエクスポートの実験的なサポートが導入されました。 これにより、Kotlinソースを直接エクスポートし、Objective-Cヘッダーが不要になるため、SwiftからKotlinコードを慣用的に呼び出すことができます。

これにより、Appleターゲットのマルチプラットフォーム開発が大幅に改善されるはずです。たとえば、トップレベル関数を持つKotlinモジュールがある場合、Swiftエクスポートにより、Objective-Cのアンダースコアやマングルされた名前を削除し、クリーンでモジュール固有のインポートが可能になります。

主な機能は次のとおりです。

  • マルチモジュールサポート。各Kotlinモジュールは個別のSwiftモジュールとしてエクスポートされ、関数呼び出しを簡素化します。
  • パッケージサポート。Kotlinパッケージはエクスポート中に明示的に保持され、生成されたSwiftコードでの命名衝突を回避します。
  • 型エイリアス。Kotlinの型エイリアスはSwiftにエクスポートされ、保持されるため、可読性が向上します。
  • プリミティブのnull許容性の強化。null許容性を保持するためにInt?のような型をKotlinIntのようなラッパークラスにボックス化する必要があったObjective-C相互運用とは異なり、Swiftエクスポートはnull許容性情報を直接変換します。
  • オーバーロード。Kotlinのオーバーロードされた関数をSwiftで曖昧さなく呼び出すことができます。
  • フラット化されたパッケージ構造。KotlinパッケージをSwiftのenumに変換し、生成されたSwiftコードからパッケージプレフィックスを削除できます。
  • モジュール名のカスタマイズ。KotlinプロジェクトのGradle設定で、結果のSwiftモジュール名をカスタマイズできます。

Swiftエクスポートを有効にする方法

この機能は現在Experimentalであり、iOSフレームワークをXcodeプロジェクトに接続するために直接統合を使用するプロジェクトでのみ機能します。 これは、IntelliJ IDEAのKotlin MultiplatformプラグインまたはWebウィザードで作成されたマルチプラットフォームプロジェクトの標準的な設定です。

Swiftエクスポートを試すには、Xcodeプロジェクトを設定します。

  1. Xcodeで、プロジェクト設定を開きます。
  2. Build Phasesタブで、embedAndSignAppleFrameworkForXcodeタスクを含むRun Scriptフェーズを見つけます。
  3. Run Scriptフェーズで、embedSwiftExportForXcodeタスクを特徴とするようにスクリプトを調整します。
bash
./gradlew :<Shared module name>:embedSwiftExportForXcode

Swiftエクスポートスクリプトを追加

  1. プロジェクトをビルドします。Swiftモジュールはビルド出力ディレクトリに生成されます。

この機能はデフォルトで利用可能です。以前のリリースで既に有効にしている場合は、gradle.propertiesファイルからkotlin.experimental.swift-export.enabledを削除できます。

時間を節約するには、Swiftエクスポートがすでに設定されている弊社の公開サンプルをクローンしてください。

Swiftエクスポートの詳細については、弊社のドキュメントをご覧ください。

フィードバックを送る

今後のKotlinリリースでは、Swiftエクスポートのサポートを拡大し、段階的に安定させる予定です。 Kotlin 2.2.20以降は、特にコルーチンとフロー周りのKotlinとSwift間の相互運用性の向上に注力します。

Swiftエクスポートのサポートは、Kotlin Multiplatformにとって大きな変更です。皆様からのフィードバックをお待ちしております。

  • Kotlin Slackで開発チームに直接連絡してください – 招待を取得して#swift-exportチャンネルに参加してください。
  • Swiftエクスポートで直面する問題をYouTrackで報告してください。

jsおよびwasmJsターゲット用の共有ソースセット

これまで、Kotlin MultiplatformはJavaScript (js) とWebAssembly (wasmJs) のWebターゲット用の共有ソースセットをデフォルトで含んでいませんでした。 jswasmJsの間でコードを共有するには、カスタムソースセットを手動で設定するか、js用とwasmJs用で2箇所にコードを記述する必要がありました。例:

kotlin
// commonMain
expect suspend fun readCopiedText(): String

// jsMain
external interface Navigator { val clipboard: Clipboard }
// JSとWasmで異なる相互運用
external interface Clipboard { fun readText(): Promise<String> }
external val navigator: Navigator

suspend fun readCopiedText(): String {
    // JSとWasmで異なる相互運用
    return navigator.clipboard.readText().await()
}

// wasmJsMain
external interface Navigator { val clipboard: Clipboard }
external interface Clipboard { fun readText(): Promise<JsString> }
external val navigator: Navigator

suspend fun readCopiedText(): String {
    return navigator.clipboard.readText().await().toString()
}

このリリースから、デフォルト階層テンプレートを使用すると、Kotlin GradleプラグインがWeb用の新しい共有ソースセット (webMainwebTestで構成) を追加します。

この変更により、webソースセットはjswasmJsの両方のソースセットの親となります。更新されたソースセット階層は次のようになります。

Webを使用したデフォルト階層テンプレートの使用例

新しいソースセットにより、jswasmJsの両方のターゲットに対して1つのコードを記述できます。共有コードをwebMainに配置すると、両方で自動的に機能します。

kotlin
// commonMain
expect suspend fun readCopiedText(): String

// webMain
external interface Navigator { val clipboard: Clipboard }
external interface Clipboard { fun readText(): Promise<JsString> }
external val navigator: Navigator

actual suspend fun readCopiedText(): String {
    return navigator.clipboard.readText().await().toString()
}

このアップデートにより、jswasmJsターゲット間のコード共有が簡素化されます。特に以下の2つのケースで役立ちます。

  • ライブラリ作者で、コードを重複させることなくjswasmJsの両方のターゲットをサポートしたい場合。
  • WebをターゲットとするCompose Multiplatformアプリケーションを開発している場合、より広範なブラウザ互換性のためにjswasmJsの両方のターゲットのクロスコンパイルを有効にします。このフォールバックモードにより、Webサイトを作成すると、現代のブラウザはwasmJsを使用し、古いブラウザはjsを使用するため、すべてのブラウザでそのまま動作します。

この機能を試すには、build.gradle(.kts)ファイルのkotlin {}ブロックでデフォルト階層テンプレートを使用してください。

kotlin
kotlin {
    js()
    wasmJs()

    // webMainとwebTestを含むデフォルトのソースセット階層を有効にする
    applyDefaultHierarchyTemplate()
}

デフォルト階層を使用する前に、カスタム共有ソースセットを持つプロジェクトがある場合や、js("web")ターゲットの名前を変更している場合は、潜在的な競合がないか慎重に検討してください。これらの競合を解決するには、競合するソースセットまたはターゲットの名前を変更するか、デフォルト階層を使用しないでください。

Kotlinライブラリの安定したクロスプラットフォームコンパイル

Kotlin 2.2.20では、重要なロードマップ項目が完了し、Kotlinライブラリのクロスプラットフォームコンパイルが安定化されました。

Kotlinライブラリを公開するための.klibアーティファクトを、どのホストでも生成できるようになりました。これにより、特にこれまでMacマシンが必要だったAppleターゲットの公開プロセスが大幅に合理化されます。

この機能はデフォルトで利用可能です。既にkotlin.native.enableKlibsCrossCompilation=trueでクロスコンパイルを有効にしている場合は、gradle.propertiesファイルからこれを削除できます。

残念ながら、いくつかの制限はまだ存在します。以下の場合は、引き続きMacマシンを使用する必要があります。

マルチプラットフォームライブラリの公開に関する詳細については、弊社のドキュメントをご覧ください。

Experimental

共通依存関係を宣言するための新しいアプローチ

Gradleでマルチプラットフォームプロジェクトを設定するのを簡素化するため、Kotlin 2.2.20では、プロジェクトがGradle 8.8以降を使用している場合、トップレベルのdependencies {}ブロックを使用してkotlin {}ブロック内で共通依存関係を宣言できるようになりました。 これらの依存関係は、commonMainソースセットで宣言されたかのように動作します。この機能は、Kotlin/JVMおよびAndroid専用プロジェクトで使用するdependenciesブロックと同様に機能し、Kotlin Multiplatformでは現在Experimentalです。

プロジェクトレベルで共通依存関係を宣言することで、ソースセット間の繰り返しの設定が減り、ビルド設定の合理化に役立ちます。必要に応じて、各ソースセットにプラットフォーム固有の依存関係を追加することもできます。

この機能を試すには、トップレベルのdependencies {}ブロックの前に@OptIn(ExperimentalKotlinGradlePluginApi::class)アノテーションを追加してオプトインしてください。例:

kotlin
kotlin {
    @OptIn(ExperimentalKotlinGradlePluginApi::class)
    dependencies {
        implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2")
    }
}

この機能に関するフィードバックをYouTrackでお寄せいただけると幸いです。

依存関係におけるターゲットサポートの新しい診断

Kotlin 2.2.20以前は、ビルドスクリプト内の依存関係がソースセットで必要なすべてのターゲットをサポートしていない場合、Gradleによって生成されるエラーメッセージでは問題を理解することが困難でした。

Kotlin 2.2.20では、各依存関係がどのターゲットをサポートし、どのターゲットをサポートしないかを明確に示す新しい診断が導入されました。

この診断はデフォルトで有効になっています。何らかの理由で無効にする必要がある場合は、このYouTrack課題にコメントでお知らせください。 gradle.propertiesファイルで診断を無効にするには、以下のGradleプロパティを使用できます。

プロパティ説明
kotlin.kmp.eagerUnresolvedDependenciesDiagnostic=falseメタデータコンパイルとインポートのみで診断を実行
kotlin.kmp.unresolvedDependenciesDiagnostic=false診断を完全に無効にする

Kotlin/Native

Kotlin 2.2.20では、Objective-C/Swiftとの相互運用性、デバッグ、新しいバイナリオプションに改善が加えられました。

バイナリにおけるスタックカナリアのサポート

Kotlin 2.2.20から、Kotlinは生成されるKotlin/Nativeバイナリでのスタックカナリアのサポートを追加しました。スタック保護の一部として、このセキュリティ機能はスタック破壊から保護し、一般的なアプリケーションの脆弱性の一部を軽減します。SwiftとObjective-Cでは既に利用可能でしたが、Kotlinでもサポートされるようになりました。

Kotlin/Nativeでのスタック保護の実装は、Clangのスタックプロテクターの挙動に従います。

スタックカナリアを有効にするには、以下のバイナリオプションgradle.propertiesファイルに追加してください。

none
kotlin.native.binary.stackProtector=yes

このプロパティは、スタック破壊に対して脆弱なすべてのKotlin関数に対してこの機能を有効にします。代替モードは次のとおりです。

  • kotlin.native.binary.stackProtector=strong。これは、スタック破壊に対して脆弱な関数に対してより強力なヒューリスティックを使用します。
  • kotlin.native.binary.stackProtector=all。これは、すべての関数に対してスタックプロテクターを有効にします。

場合によっては、スタック保護がパフォーマンスコストを伴う可能性があることに注意してください。

Experimental

リリースバイナリのバイナリサイズの縮小

Kotlin 2.2.20では、リリースバイナリのバイナリサイズを削減できるsmallBinaryオプションが導入されました。 この新しいオプションは、LLVMコンパイルフェーズ中のコンパイラのデフォルトの最適化引数として、事実上-Ozを設定します。

smallBinaryオプションを有効にすると、リリースバイナリをより小さくし、ビルド時間を短縮できます。ただし、場合によってはランタイムパフォーマンスに影響を与える可能性があります。

この新機能は現在Experimentalです。プロジェクトでこれを試すには、以下のバイナリオプションgradle.propertiesファイルに追加してください。

none
kotlin.native.binary.smallBinary=true

Kotlinチームは、この機能の実装にご協力いただいたTroels Lund氏に感謝いたします。

デバッガーのオブジェクト概要の改善

Kotlin/Nativeは、LLDBやGDBなどのデバッガーツール向けに、より明確なオブジェクト概要を生成するようになりました。これにより、生成されるデバッグ情報の可読性が向上し、デバッグエクスペリエンスが合理化されます。

たとえば、以下のオブジェクトを考えてみましょう。

kotlin
class Point(val x: Int, val y: Int)
val point = Point(1, 2)

これまで、検査ではオブジェクトのメモリアドレスへのポインタを含む限られた情報しか表示されませんでした。

none
(lldb) v point
(ObjHeader *) point = [x: ..., y: ...]
(lldb) v point->x
(int32_t *) x = 0x0000000100274048

Kotlin 2.2.20では、デバッガーが実際の値を含むより豊富な詳細を表示するようになりました。

none
(lldb) v point
(ObjHeader *) point = Point(x=1, y=2)
(lldb) v point->x
(int32_t) point->x = 1

Kotlinチームは、この機能の実装にご協力いただいたNikita Nazarov氏に感謝いたします。

Kotlin/Nativeでのデバッグの詳細については、ドキュメントをご覧ください。

Objective-Cヘッダーのブロック型における明示的な名前

Kotlin 2.2.20では、Kotlin/NativeプロジェクトからエクスポートされるObjective-CヘッダーのKotlinの関数型に明示的なパラメータ名を追加するオプションが導入されました。パラメータ名により、Xcodeのオートコンプリート候補が改善され、Clangの警告を回避するのに役立ちます。

これまで、ブロック型におけるパラメータ名は、生成されたObjective-Cヘッダーでは省略されていました。このような場合、Xcodeのオートコンプリートは、Objective-Cブロックでパラメータ名なしで関数を呼び出すことを提案していました。生成されたブロックはClangの警告を引き起こしました。

たとえば、以下のKotlinコードの場合:

kotlin
// Kotlin:
fun greetUser(block: (name: String) -> Unit) = block("John")

生成されたObjective-Cヘッダーにはパラメータ名がありませんでした。

objc
// Objective-C:
+ (void)greetUserBlock:(void (^)(NSString *))block __attribute__((swift_name("greetUser(block:)")));

そのため、XcodeでObjective-CからgreetUserBlock()関数を呼び出すと、IDEは次のように提案しました。

objc
// Objective-C:
greetUserBlock:^(NSString *) {
    // ...
};

提案中の不足しているパラメータ名(NSString *)がClangの警告を引き起こしました。

新しいオプションを使用すると、KotlinはKotlin関数型からのパラメータ名をObjective-Cブロック型に転送するため、Xcodeは提案でそれらを使用します。

objc
// Objective-C:
greetUserBlock:^(NSString *name) {
    // ...
};

明示的なパラメータ名を有効にするには、以下のバイナリオプションgradle.propertiesファイルに追加してください。

none
kotlin.native.binary.objcExportBlockExplicitParameterNames=true

Kotlinチームは、この機能の実装にご協力いただいたYijie Jiang氏に感謝いたします。

Kotlin/Nativeディストリビューションのサイズ縮小

Kotlin/Nativeディストリビューションには、コンパイラコードを含む2つのJARファイルが含まれていました。

  • konan/lib/kotlin-native.jar
  • konan/lib/kotlin-native-compiler-embeddable.jar

Kotlin 2.2.20から、kotlin-native.jarは公開されなくなりました。

削除されたJARファイルは、不要になった組み込みコンパイラのレガシーバージョンです。この変更により、ディストリビューションのサイズが大幅に縮小されます。

その結果、以下のオプションは非推奨となり、削除されました。

  • kotlin.native.useEmbeddableCompilerJar=false Gradleプロパティ。代わりに、組み込みコンパイラJARファイルは常にKotlin/Nativeプロジェクトで使用されます。
  • KotlinCompilerPluginSupportPlugin.getPluginArtifactForNative()関数。代わりに、getPluginArtifact()関数が常に使用されます。

詳細については、YouTrack課題をご覧ください。

Objective-CヘッダーへのKDocのエクスポートがデフォルトに

Kotlin/Nativeの最終バイナリのコンパイル中にObjective-Cヘッダーを生成する際、KDocコメントがデフォルトでエクスポートされるようになりました。

これまで、-Xexport-kdocオプションはビルドファイルに手動で追加する必要がありました。現在では、コンパイルタスクに自動的に渡されます。

このオプションはKDocコメントをklibsに埋め込み、Appleフレームワークを生成する際にklibsからコメントを抽出します。その結果、Xcodeなどでオートコンプリート時にクラスやメソッドのコメントが表示されるようになります。

build.gradle(.kts)ファイルのbinaries {}ブロックで、klibsから生成されるAppleフレームワークへのKDocコメントのエクスポートを無効にできます。

kotlin
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi

kotlin {
    iosArm64 {
        binaries {
            framework { 
                baseName = "sdk"
                @OptIn(ExperimentalKotlinGradlePluginApi::class)
                exportKdoc.set(false)
            }
        }
    }
}

詳細については、弊社のドキュメントをご覧ください。

x86_64 Appleターゲットの非推奨化

Appleは数年前にIntelチップ搭載デバイスの生産を終了し、最近、macOS Tahoe 26がIntelベースのアーキテクチャをサポートする最後のOSバージョンになると発表しました

これにより、特にmacOS 26に付属するサポート対象のXcodeバージョンを更新する将来のKotlinリリースでは、ビルドエージェントでこれらのターゲットを適切にテストすることがますます困難になります。

Kotlin 2.2.20から、macosX64およびiosX64ターゲットはサポートティア2に降格されました。これは、ターゲットがコンパイルされることを確認するためにCIで定期的にテストされることを意味しますが、実行されることを確認するために自動的にテストされない場合があります。

Kotlin 2.2.20−2.4.0リリースサイクル中に、すべてのx86_64 Appleターゲットを段階的に非推奨にし、最終的にサポートを削除する予定です。これには以下のターゲットが含まれます。

  • macosX64
  • iosX64
  • tvosX64
  • watchosX64

サポートティアの詳細については、Kotlin/Nativeターゲットサポートをご覧ください。

Kotlin/Wasm

Kotlin/Wasmは現在ベータ版であり、npm依存関係の分離、JavaScript相互運用における例外処理の改善組み込みのブラウザデバッグサポートなどの改善とともに、より高い安定性を提供します。

npm依存関係の分離

これまで、Kotlin/Wasmプロジェクトでは、npmのすべての依存関係が、Kotlinツーリングの依存関係とプロジェクトの依存関係の両方を含めて、プロジェクトフォルダにまとめてインストールされていました。 それらはまた、プロジェクトのロックファイル (package-lock.jsonまたはyarn.lock) にも一緒に記録されていました。

その結果、Kotlinツーリングの依存関係が更新されるたびに、何も追加または変更していなくてもロックファイルを更新する必要がありました。

Kotlin 2.2.20から、Kotlinツーリングのnpm依存関係はプロジェクトの外にインストールされるようになりました。現在、ツーリングとユーザーの依存関係は別々のディレクトリにあります。

  • ツーリングの依存関係のディレクトリ:

    <kotlin-user-home>/kotlin-npm-tooling/<yarn|npm>/hash/node_modules

  • ユーザーの依存関係のディレクトリ:

    build/wasm/node_modules

さらに、プロジェクトディレクトリ内のロックファイルには、ユーザー定義の依存関係のみが含まれます。

この改善により、ロックファイルが自身の依存関係のみに集中し、プロジェクトをよりクリーンに保ち、ファイルの不要な変更を減らすのに役立ちます。

この変更はwasm-jsターゲットに対してデフォルトで有効になっています。jsターゲットに対してはまだこの変更は実装されていません。将来のリリースで実装する予定はありますが、Kotlin 2.2.20ではjsターゲットのnpm依存関係の挙動は以前と同じままです。

Kotlin/WasmおよびJavaScript相互運用における例外処理の改善

これまで、KotlinはJavaScript (JS) でスローされ、Kotlin/Wasmコードに渡される例外 (エラー) を理解するのが困難でした。

場合によっては、例外がWasmコードからJSにスローまたは渡され、詳細なしにWebAssembly.Exceptionにラップされるという逆方向の問題も発生しました。これらのKotlinの例外処理の問題はデバッグを困難にしていました。

Kotlin 2.2.20から、例外に関する開発者のエクスペリエンスが両方向で改善されました。

  • JSから例外がスローされた場合、Kotlin側でより多くの情報を確認できます。 そのような例外がKotlinを介してJSに戻る際に、WebAssemblyにラップされなくなりました。
  • Kotlinから例外がスローされた場合、JS側でJSエラーとしてキャッチできるようになりました。

新しい例外処理は、WebAssembly.JSTag機能をサポートするモダンなブラウザで自動的に機能します。

  • Chrome 115+
  • Firefox 129+
  • Safari 18.4+

古いブラウザでは、例外処理の挙動は変更されません。

設定なしでのブラウザデバッグのサポート

これまで、ブラウザはデバッグに必要なKotlin/Wasmプロジェクトのソースに自動的にアクセスできませんでした。 ブラウザでKotlin/Wasmアプリケーションをデバッグするには、build.gradle(.kts)ファイルに以下のスニペットを追加して、これらのソースをサービスするようにビルドを手動で設定する必要がありました。

kotlin
devServer = (devServer ?: KotlinWebpackConfig.DevServer()).apply {
    static = (static ?: mutableListOf()).apply {
        add(project.rootDir.path)
    }
}

Kotlin 2.2.20から、モダンなブラウザでのアプリケーションのデバッグはすぐに機能します。 Gradle開発タスク (*DevRun) を実行すると、Kotlinはソースファイルをブラウザに自動的に提供し、ブレークポイントの設定、変数の検査、Kotlinコードのステップ実行を追加設定なしで可能にします。

この変更により、手動設定の必要がなくなり、デバッグが簡素化されます。必要な設定はKotlin Gradleプラグインに含まれるようになりました。以前にこの設定をbuild.gradle(.kts)ファイルに追加していた場合、競合を避けるために削除する必要があります。

ブラウザでのデバッグは、すべてのGradle *DevRunタスクに対してデフォルトで有効になっています。これらのタスクはアプリケーションだけでなくそのソースファイルも提供するため、ローカル開発のみに使用し、ソースが公開されてしまう可能性のあるクラウド環境や本番環境での実行は避けてください。

デバッグ中の繰り返しの再読み込みを処理する

デフォルトでソースをサービスすると、Kotlinのコンパイルとバンドルが完了する前に、ブラウザでアプリケーションが繰り返し再読み込みされる可能性があります。 回避策として、webpackの設定を調整してKotlinソースファイルを無視し、サービスされる静的ファイルの監視を無効にしてください。 プロジェクトのルートにあるwebpack.config.dディレクトリに、以下の内容を持つ.jsファイルを追加してください。

kotlin
config.watchOptions = config.watchOptions || {
    ignored: ["**/*.kt", "**/node_modules"]
}

if (config.devServer) {
    config.devServer.static = config.devServer.static.map(file => {
        if (typeof file === "string") {
        return { directory: file,
                 watch: false,
        }
    } else {
        return file
    }
    })
}

空のyarn.lockファイルの排除

これまで、Kotlin Gradleプラグイン (KGP) は、Kotlinツールチェーンで必要とされるnpmパッケージに関する情報と、プロジェクトまたは使用されるライブラリからの既存のnpm依存関係を含むyarn.lockファイルを自動的に生成していました。

現在、KGPはツールチェーンの依存関係を個別に管理し、プロジェクトにnpm依存関係がない限り、プロジェクトレベルのyarn.lockファイルは生成されなくなりました。

KGPは、npm依存関係が追加されると自動的にyarn.lockファイルを作成し、npm依存関係が削除されるとyarn.lockファイルを削除します。

この変更により、プロジェクト構造がクリーンになり、実際のnpm依存関係がいつ導入されたかを追跡しやすくなります。

この挙動を設定するために追加のステップは不要です。Kotlin 2.2.20以降、Kotlin/Wasmプロジェクトではデフォルトで適用されます。

完全修飾クラス名における新しいコンパイラエラー

Kotlin/Wasmでは、コンパイラはデフォルトで生成されたバイナリにクラスの完全修飾名 (FQN) を格納しません。 このアプローチにより、アプリケーションサイズの増加を回避します。

その結果、以前のKotlinリリースでは、KClass::qualifiedNameプロパティを呼び出すと、クラスの修飾名の代わりに空の文字列が返されていました。

Kotlin 2.2.20から、Kotlin/WasmプロジェクトでKClass::qualifiedNameプロパティを使用すると、完全修飾名機能を明示的に有効にしない限り、コンパイラはエラーを報告します。

この変更により、qualifiedNameプロパティを呼び出す際の予期しない空の文字列を防ぎ、コンパイル時に問題を捕捉することで開発者のエクスペリエンスを向上させます。

診断はデフォルトで有効になっており、エラーは自動的に報告されます。診断を無効にし、Kotlin/WasmでFQNの保存を許可するには、build.gradle(.kts)ファイルに以下のオプションを追加して、すべてのクラスの完全修飾名を格納するようにコンパイラに指示してください。

kotlin
kotlin {
    wasmJs {
        ...
        compilerOptions {
            freeCompilerArgs.add("-Xwasm-kclass-fqn")
        }
    }
}

このオプションを有効にすると、アプリケーションサイズが増加することに注意してください。

Kotlin/JS

Kotlin 2.2.20では、BigInt型を使用してKotlinのLong型を表現するのをサポートし、エクスポートされた宣言でLongを使用できるようにします。さらに、このリリースではNode.js引数をクリーンアップするためのDSL関数が追加されました。

Experimental

KotlinのLong型を表現するためのBigInt型の使用

ES2020標準以前、JavaScript (JS) は53ビットを超える正確な整数に対するプリミティブ型をサポートしていませんでした。

このため、Kotlin/JSはLong値 (64ビット幅) を、2つのnumberプロパティを含むJavaScriptオブジェクトとして表現していました。このカスタム実装により、KotlinとJavaScript間の相互運用性がより複雑になっていました。

Kotlin 2.2.20から、Kotlin/JSは、モダンなJavaScript (ES2020) にコンパイルする際、KotlinのLong値を表現するためにJavaScriptに組み込みのBigInt型を使用するようになりました。

この変更により、Kotlin 2.2.20で導入された機能であるJavaScriptへのLong型のエクスポートが可能になります。結果として、この変更はKotlinとJavaScript間の相互運用性を簡素化します。

これを有効にするには、build.gradle(.kts)ファイルに以下のコンパイラオプションを追加する必要があります。

kotlin
kotlin {
    js {
        ...
        compilerOptions {
            freeCompilerArgs.add("-Xes-long-as-bigint")
        }
    }
}

この機能はExperimentalです。課題トラッカーYouTrackでフィードバックをお寄せいただけると幸いです。

エクスポートされた宣言でのLongの使用

Kotlin/JSはカスタムのLong表現を使用していたため、JavaScriptからKotlinのLongと対話する直接的な方法を提供することは困難でした。その結果、Long型を使用するKotlinコードをJavaScriptにエクスポートすることはできませんでした。この問題は、関数パラメータ、クラスプロパティ、コンストラクタなど、Longを使用するすべてのコードに影響しました。

KotlinのLong型がJavaScriptのBigInt型にコンパイルできるようになったため、Kotlin/JSはLong値をJavaScriptにエクスポートするのをサポートし、KotlinコードとJavaScriptコード間の相互運用性を簡素化します。

この機能を有効にするには:

  1. build.gradle(.kts)ファイルのfreeCompilerArgs属性に以下のコンパイラオプションを追加して、Kotlin/JSでLongのエクスポートを許可してください。

    kotlin
    kotlin {
        js {
            ...
            compilerOptions {                   
                freeCompilerArgs.add("-XXLanguage:+JsAllowLongInExportedDeclarations")
            }
        }
    }
  2. BigInt型を有効にしてください。KotlinのLong型を表現するためのBigInt型の使用で有効にする方法をご覧ください。

よりクリーンな引数のための新しいDSL関数

Node.jsでKotlin/JSアプリケーションを実行する際、プログラムに渡される引数 (args) には、これまで以下が含まれていました。

  • 実行可能ファイルNodeへのパス。
  • スクリプトへのパス。
  • 指定した実際のコマンドライン引数。

しかし、argsの期待される挙動は、コマンドライン引数のみを含むことでした。これを実現するには、build.gradle(.kts)ファイル内またはKotlinコードでdrop()関数を使用して最初の2つの引数を手動でスキップする必要がありました。

kotlin
fun main(args: Array<String>) {
    println(args.drop(2).joinToString(", "))
}

この回避策は繰り返しの手間がかかり、エラーが発生しやすく、プラットフォーム間でコードを共有する際にはうまく機能しませんでした。

この問題を解決するため、Kotlin 2.2.20ではpassCliArgumentsToMainFunction()という新しいDSL関数が導入されました。

この関数を使用すると、コマンドライン引数のみが含まれ、Nodeとスクリプトのパスは除外されます。

kotlin
fun main(args: Array<String>) {
    // drop()は不要になり、カスタム引数のみが含まれる 
    println(args.joinToString(", "))
}

この変更により、ボイラープレートコードが削減され、手動で引数を削除することによる間違いが防止され、クロスプラットフォームの互換性が向上します。

この機能を有効にするには、build.gradle(.kts)ファイル内に以下のDSL関数を追加してください。

kotlin
kotlin {
    js {
        nodejs {
            passCliArgumentsToMainFunction()
        }
    }
}

Gradle

Kotlin 2.2.20では、GradleビルドレポートにKotlin/Nativeタスク用の新しいコンパイラパフォーマンスメトリクスが追加され、インクリメンタルコンパイルの使い勝手が向上しました。

Kotlin/Nativeタスクのビルドレポートにおける新しいコンパイラパフォーマンスメトリクス

Kotlin 1.7.0では、コンパイラのパフォーマンス追跡を支援するビルドレポートを導入しました。それ以来、これらのレポートをさらに詳細でパフォーマンス問題の調査に役立つものにするために、より多くのメトリクスを追加してきました。

Kotlin 2.2.20では、ビルドレポートにKotlin/Nativeタスクのコンパイラパフォーマンスメトリクスが含まれるようになりました。

ビルドレポートとその設定方法の詳細については、ビルドレポートの有効化をご覧ください。

Experimental

Kotlin/JVMにおけるインクリメンタルコンパイルの改善のプレビュー

Kotlin 2.0.0では、最適化されたフロントエンドを持つ新しいK2コンパイラが導入されました。Kotlin 2.2.20では、新しいフロントエンドを使用してKotlin/JVMの特定の複雑なインクリメンタルコンパイルシナリオでパフォーマンスを向上させることで、これをさらに発展させています。

これらの改善は、挙動の安定化に取り組んでいる間、デフォルトでは無効になっています。これらを有効にするには、gradle.propertiesファイルに以下のプロパティを追加してください。

none
kotlin.incremental.jvm.fir=true

現在、kaptコンパイラプラグインはこの新しい挙動と互換性がありません。今後のKotlinリリースでサポートを追加する予定です。

この機能に関するフィードバックをYouTrackでお寄せいただけると幸いです。

インクリメンタルコンパイルがインライン関数のラムダの変更を検出

Kotlin 2.2.20以前は、インクリメンタルコンパイルを有効にしてインライン関数内のラムダのロジックを変更した場合、コンパイラは他のモジュール内のそのインライン関数の呼び出しサイトを再コンパイルしませんでした。その結果、それらの呼び出しサイトはラムダの以前のバージョンを使用し、予期しない挙動を引き起こす可能性がありました。

Kotlin 2.2.20では、コンパイラはインライン関数のラムダの変更を検出し、その呼び出しサイトを自動的に再コンパイルするようになりました。

Maven: kotlin-maven-pluginにおけるKotlinデーモンのサポート

Kotlin 2.2.20では、Kotlin 2.2.0で導入されたビルドツールAPIをさらに一歩進め、kotlin-maven-pluginKotlinデーモンのサポートを追加しました。Kotlinデーモンを使用すると、Kotlinコンパイラは独立した別のプロセスで実行され、他のMavenプラグインがシステムプロパティを上書きするのを防ぎます。このYouTrack課題で例を見ることができます。

Kotlin 2.2.20から、Kotlinデーモンはデフォルトで使用されます。以前の挙動に戻したい場合は、pom.xmlファイルで以下のプロパティをfalseに設定してオプトアウトしてください。

xml
<properties>
    <kotlin.compiler.daemon>false</kotlin.compiler.daemon>
</properties>

Kotlin 2.2.20では、KotlinデーモンのデフォルトJVM引数をカスタマイズするために使用できる新しいjvmArgsプロパティも導入されました。たとえば、-Xmxおよび-Xmsオプションを上書きするには、pom.xmlファイルに以下を追加してください。

xml
<properties>
    <kotlin.compiler.daemon.jvmArgs>Xmx1500m,Xms500m</kotlin.compiler.daemon.jvmArgs>
</properties>

Kotlinコンパイラオプションの新しい共通スキーマ

Kotlin 2.2.20では、org.jetbrains.kotlin:kotlin-compiler-arguments-descriptionの下で公開されているすべてのコンパイラオプションの共通スキーマが導入されました。 このアーティファクトには、すべてのコンパイラオプション、それらの説明、および各オプションが導入または安定化されたバージョンなどのメタデータの、コード表現とJSON相当 (非JVMコンシューマ向け) の両方が含まれています。このスキーマを使用して、オプションのカスタムビューを生成したり、必要に応じて分析したりできます。

Kotlin標準ライブラリ

このリリースでは、標準ライブラリに新しい実験的な機能が導入されました。Kotlin/JSでのインターフェース型識別のためのリフレクションサポート、共通アトミック型用の更新関数、および配列サイズ変更のためのcopyOf()オーバーロードです。

Experimental

Kotlin/JSにおけるリフレクションによるインターフェース型識別のサポート

Kotlin 2.2.20では、ExperimentalKClass.isInterfaceプロパティがKotlin/JS標準ライブラリに追加されました。

このプロパティを使用すると、クラス参照がKotlinインターフェースを表しているかどうかをチェックできます。これにより、Kotlin/JSはKotlin/JVMとのパリティに近づき、Kotlin/JVMではKClass.java.isInterfaceを使用してクラスがインターフェースを表しているかどうかをチェックできます。

オプトインするには、@OptIn(ExperimentalStdlibApi::class)アノテーションを使用してください。

kotlin
@OptIn(ExperimentalStdlibApi::class)
fun inspect(klass: KClass<*>) {
    // インターフェースの場合trueを出力
    println(klass.isInterface)
}

課題トラッカーYouTrackでフィードバックをお寄せいただけると幸いです。

Experimental

共通アトミック型のための新しい更新関数

Kotlin 2.2.20では、共通アトミック型およびそれらの配列対応要素を更新するための新しい実験的な関数が導入されました。 各関数は、これらの更新関数のいずれかを使用して新しい値をアトミックに計算し、現在の値を置き換えます。戻り値は使用する関数によって異なります。

これらの関数を使用して、乗算やビット演算など、すぐにサポートされていないアトミックな変換を実装できます。 この変更以前は、共通アトミック型をインクリメントし、以前の値を読み取るには、compareAndSet()関数を使ったループが必要でした。

共通アトミック型のすべてのAPIと同様に、これらの関数はExperimentalです。 オプトインするには、@OptIn(ExperimentalAtomicApi::class)アノテーションを使用してください。

様々な種類の更新を実行し、以前の値または更新された値のいずれかを返すコードの例を以下に示します。

kotlin
import kotlin.concurrent.atomics.*
import kotlin.random.Random

@OptIn(ExperimentalAtomicApi::class)
fun main() {
    val counter = AtomicLong(Random.nextLong())
    val minSetBitsThreshold = 20

    // 結果を使用せずに新しい値を設定
    counter.update { if (it < 0xDECAF) 0xCACA0 else 0xC0FFEE }

    // 現在の値を取得し、更新
    val previousValue = counter.fetchAndUpdate { 0x1CEDL.shl(Long.SIZE_BITS - it.countLeadingZeroBits()) or it }

    // 値を更新し、結果を取得
    val current = counter.updateAndFetch {
        if (it.countOneBits() < minSetBitsThreshold) it.shl(20) or 0x15BADL else it
    }

    val hexFormat = HexFormat {
        upperCase = true
        number {
            removeLeadingZeros = true
        }
    }
    println("Previous value: ${previousValue.toHexString(hexFormat)}")
    println("Current value: ${current.toHexString(hexFormat)}")
    println("Expected status flag set: ${current and 0xBAD != 0xBADL}")
}

課題トラッカーYouTrackでフィードバックをお寄せいただけると幸いです。

Experimental

配列のcopyOf()オーバーロードのサポート

Kotlin 2.2.20では、copyOf()関数の実験的なオーバーロードが導入されました。 ジェネリック型Array<T>の配列およびすべてのプリミティブ配列型で利用できます。

この関数を使用して、配列を大きくし、イニシャライザラムダからの値を使用して新しい要素を埋めることができます。 これにより、カスタムのボイラープレートコードを削減し、ジェネリックなArray<T>をリサイズするとnullableな結果 (Array<T?>) が生成されるという一般的な問題点を解決できます。

例を示します。

kotlin
@OptIn(ExperimentalStdlibApi::class)
fun main() {
    val row1: Array<String> = arrayOf("one", "two")
    // 配列のサイズを変更し、ラムダを使用して新しい要素を埋める
    val row2: Array<String> = row1.copyOf(4) { "default" }
    println(row2.contentToString())
    // [one, two, default, default]
}

このAPIはExperimentalです。オプトインするには、@OptIn(ExperimentalStdlibApi::class)アノテーションを使用してください。

弊社の課題トラッカーでフィードバックをお寄せいただけると幸いです。

Composeコンパイラ

このリリースでは、Composeコンパイラは新しい警告の追加と、ビルドメトリクスの出力を読みやすく改善することで、使い勝手の向上をもたらします。

デフォルトパラメータの言語バージョン制限

このリリースでは、コンパイルで指定された言語バージョンが、抽象またはオープンなコンポーザブル関数におけるデフォルトパラメータをサポートするために必要なバージョンよりも低い場合、Composeコンパイラはエラーを報告します。

デフォルトパラメータは、Composeコンパイラにおいて、抽象関数ではKotlin 2.1.0から、オープン関数ではKotlin 2.2.0からサポートされています。古いKotlin言語バージョンをターゲットにしながら新しいバージョンのComposeコンパイラを使用する場合、ライブラリ開発者は、言語バージョンがサポートしていなくても、抽象またはオープン関数におけるデフォルトパラメータが引き続き公開APIに表示される可能性があることに注意する必要があります。

K2コンパイラ向けのComposableターゲット警告

このリリースでは、K2コンパイラを使用する際に@ComposableTargetの不一致に関する警告が追加されました。

例:

text
@Composable fun App() {
  Box { // <-- Boxは@UiComposableです
    Path(...) // <-- Pathは@VectorComposableです
    ^^^^^^^^^
    warning: UIコンポーザブルが期待される場所でVectorコンポーザブル関数を呼び出しています
  }
}

ビルドメトリクスにおける完全修飾名

ビルドメトリクスで報告されるクラス名と関数名は完全修飾されるようになり、異なるパッケージで同じ名前を持つ宣言を区別しやすくなりました。

さらに、ビルドメトリクスにはデフォルトパラメータからの複雑な式のダンプが含まれなくなり、読みやすくなりました。

破壊的変更と非推奨化

このセクションでは、注目すべき重要な破壊的変更と非推奨化について説明します。

  • kaptコンパイラプラグインは、デフォルトでK2コンパイラを使用するようになりました。その結果、プラグインがK2コンパイラを使用するかどうかを制御するkapt.use.k2プロパティは非推奨になりました。このプロパティをfalseに設定してK2コンパイラの使用をオプトアウトすると、Gradleは警告を表示します。

ドキュメントの更新

Kotlinのドキュメントにいくつかの注目すべき変更が加えられました。

Kotlin 2.2.20へのアップデート方法

Kotlinプラグインは、IntelliJ IDEAおよびAndroid Studioにバンドルされたプラグインとして配布されています。

新しいKotlinバージョンにアップデートするには、ビルドスクリプトでKotlinバージョンを2.2.20に変更してください。