Releases

Kotlin 1.6.20 がリリースされました

Read this post in other languages:
English, Français, 한국어, Deutsch, 简体中文

このブログ記事では、以下の改善点に関する概要とそれ以外のすべての漸進的な変更をご紹介します。


アップデート方法

IntelliJ IDEA または Android Studio を使用している場合、新しい Kotlin がリリースされたら自動的にアップデートするオプションがあります。

Kotlin 1.6.20 へのアップデート

メジャーアップデート

Kotlin / JVM におけるコンテキストレシーバーのプロトタイプ

Kotlin 1.6.20 からはレシーバーの数が 1 つに制限されなくなりました。 複数個必要であれば、関数、プロパティ、クラスの宣言にコンテキストレシーバーを追加することにより、それぞれをコンテキスト依存 (コンテキスト対応) の宣言にできます。 以下は、コンテキスト対応宣言の挙動です。

  • 宣言されているすべてのコンテキストレシーバーを呼び出し側のスコープ内に暗黙的なレシーバーとして記述することを要求する。
  • 宣言されているコンテキストレシーバーをその本体のスコープに黙示的なレシーバーとして取り入れる。

プロジェクトでコンテキストレシーバーを有効にするには、コンパイラーオプション -Xcontext-receivers を使用します。 機能と構文の詳細は、KEEP を参照してください。

ただし、プロトタイプ実装であることに注意してください。

  • -Xcontext-receivers を有効にすると、プロダクションコードでは使用できないリリース前のバイナリがコンパイラーによって生成されます。
  • 現在、IDE ではコンテキストレシーバーを最低限のレベルでしかサポートしていません。

確実に非 nullable な型

Java のジェネリッククラスとジェネリックインターフェースを拡張する際の相互運用性を改善するため、Kotlin 1.6.20 では T & Any という新しい構造を使用してジェネリック型パラメーターをその使用箇所で確実に非 nullable に指定できるようにしています。 この構文は交差型の表記法が基になっており、現時点では & の左側に nullable の上限、右側に非 nullable の Any を記述した型パラメーターに限定されています。

この機能を有効にするには、以下のようなコードで言語バージョンを 1.7 に設定します。

確実に非 nullable な型の詳細は、KEEP を参照してください。

ただし、確実に非 nullable な型はベータ版の機能です。 ほぼ安定している機能ですが、将来的には移行手続きが必要になるかもしれません。 ユーザーの皆さんに加えていただく変更の量は、最小限に抑えるよう努力していきます。

JMV バックエンドにおける単一モジュールの並列コンパイルに対するサポート

Kotlin 1.6.20 では、モジュール内のすべてのファイルを並列コンパイルする実験的な JVM IR バックエンドモードを追加しました。 並列コンパイルを実行すると、コンパイルの所要時間を最大で 15% も削減できます。

実験的な並列バックエンドモードを有効にするには、コンパイラーオプション -Xbackend-threads を使用します。 このオプションには、以下の引数を使用します。

  • N は使用するスレッドの数です。 この値が CPU コアの数を超えるとスレッド間でコンテキスト切り替えが発生するため、並列処理の効果が失われるので注意が必要です。
  • 各 CPU コアに 1 つのスレッドを使う場合は、0 を使用します。

Gradle では複数のタスクを並列処理できますが、Gradle の視点から見たプロジェクト(またはプロジェクトの主要な部分)が 1 つの大きなタスクである場合、この種の並列処理はあまり効果を発揮しません。 巨大なモジュールがある場合は、並列コンパイルを利用するとコンパイル速度が向上します。 プロジェクトが数多くの小さなモジュールで構成されており、かつ Gradle によって並列処理されるビルドがある場合に並列処理のレイヤーをさらに追加すると、コンテキストの切り替えが原因でパフォーマンスが損なわれる場合があります。

並列コンパイルには以下のような制限があります。

  • kapt では機能しない。IR バックエンドが無効化されるためです。
  • 設計上、より多くの JVM ヒープが必要です。 ヒープの量はスレッドの数に比例します。

Kotlin/JS の IR コンパイラーを使った開発用バイナリのインクリメンタルコンパイル

IR コンパイラーを使った Kotlin / JS 開発の効率アップを狙って、新たにインクリメンタルコンパイルモードを導入しています。

このモードで Gradle タスク compileDevelopmentExecutableKotlinJs を使って開発用バイナリをビルドすると、コンパイラーが前のコンパイルの結果をモジュールレベルでキャッシュします。 コンパイラーが後続のコンパイルでキャッシュされているコンパイル結果を未変更のソースファイルに対して使用するため、コンパイルの完了速度が(小さな変更では特に)向上します。 この改善は、開発プロセスにおいて編集・ビルド・デバッグのサイクルを短縮するためのものであり、プロダクションのアーティファクトをビルドすることには影響しません。

開発用バイナリのインクリメンタルコンパイルを有効にするには、プロジェクトの gradle.properties に次の行を追加します。

当社のテストプロジェクトでは、この新しいモードを使うことにより、インクリメンタルコンパイルの速度が 30% も向上しました。 しかし、このモードでクリーンなビルドを実行する場合はキャッシュの作成と書き込みが必要になるため、速度が低下してしまいました。

Kotlin / Native のパフォーマンス改善

Kotlin 1.6.20 ではパフォーマンスを改善したほか、Kotlin が生成する LLVM IR に影響を及ぼすバグを修正しています。 当社の社内プロジェクトに対するベンチマークを実施した結果、概して以下のパフォーマンス改善を達成しています。

  • 実行時間を 15% 削減
  • リリース版とデバッグ版のバイナリの両方でコードサイズを 20% 削減
  • リリース版バイナリのコンパイル時間を 26% 削減

このような改善により、大規模な社内プロジェクトにおけるデバッグ版バイナリのコンパイル時間も 10% 削減できました。

これを達成するため、コンパイラーが生成する合成オブジェクトの一部を静的に初期化し、各関数の LLVM IR を構造化する方法を改善し、さらにコンパイラーキャッシュを最適化しました。

マルチプラットフォームプロジェクトにおける階層構造のサポート

Kotlin 1.6.20 は、デフォルトで階層構造のサポートが有効になっています。 Kotlin 1.4.0 で階層構造を導入して以来、フロントエンドを大幅に改善し、IDE のインポートを安定させました。

従来、マルチプラットフォームプロジェクトでコードを追加する方法は 2 つありました。 1 つ目は、プラットフォーム固有のソースセットに挿入するという方法です。1 つのターゲットに限定されるほか、他のプラットフォームによる再利用はできませんでした。 2 つ目は、現在 Kotlin が対応しているすべてのプラットフォームで共有されている共通のソースセットを使用するという方法です。

今回、数多くの共通ロジックとサードパーティ API を再利用する複数の類似したネイティブターゲットでソースコードを共有できるようになりました。 階層的なプロジェクト構造のサポートにより、正しいデフォルトの依存関係を提供し、共有コードで利用可能な API を検出します。 これにより、複雑なビルド構成と回避策の使用を回避し、IDE の支援の下でネイティブターゲット間でソースセットを共有することができます。 また、別のターゲットを対象とする安全でない API の使用も避けられます。

階層的なプロジェクト構造はライブラリの作成者にも重宝します。ターゲットのサブセットに対して一般的な API を持つライブラリを公開、使用できるためです。
デフォルトでは、階層的なプロジェクト構造を持つ公開対象のライブラリは、階層的な構造を持つプロジェクトとのみ互換性を持ちます。 詳細は、プロジェクトライブラリの互換性を参照してください。

プロジェクトでのコード共有を改善

階層構造がサポートされていない場合、コードをすべてKotlin ターゲットではなく一部でのみ簡単に共有する手段はありません。 よくある例として、すべての iOS ターゲットでコードを共有すると同時に、Foundation のような iOS 特有の依存関係にアクセスする場合が挙げられます。

階層的なプロジェクト構造がサポートされることで、これを簡単に達成できるようになりました。 新しい構造では、ソースセットにより階層が作られます。 特定ソースセットのコンパイル先となる各ターゲットで利用可能なプラットフォーム特有の言語機能と依存関係を使用できます。

たとえば、iOS デバイスとシミュレーターの iosArm64iosX64 の 2 つをターゲットとした一般的なマルチプラットフォームプロジェクトについて考えてみましょう。 Kotlin のツーリングは、この 2 つのターゲットが同じ関数を持っていると理解するため、ユーザーは中間ソースセット、つまり iosMain からその関数にアクセスすることができます。

Kotlin のツールチェーンは、Kotlin / Native stdlib やネイティブライブラリといったデフォルトの正しい依存関係を提供します。 さらに、Kotlin のツーリングは、共有コード内で利用できる API サーフェスエリアを正確に検出しようと試みます。 これにより、Windows に共有されるコードで macOS 特有の関数を使用してしまう事態などを避けられます。

ライブラリ作成者の可能性向上

マルチプラットフォームライブラリが公開されると、その中間ソースセットの API も一緒に公開されてコンシューマーで利用できるようになります。 さらに、Kotlin のツールチェーンはコンシューマーのソースセットで利用可能な API を自動検出すると同時に、安全でない使用方法(JVM を対象とする API を JS コードで使用する等)を注意深く監視します。 詳細は、ライブラリのコード共有を参照してください。

構成とセットアップ

Kotlin 1.6.20 より、すべての新規マルチプラットフォームプロジェクトに階層的なプロジェクト構造が用いられます。 追加のセットアップは不要です。

  • Kotlin 1.6.20 で最高の使用体験を得るには、Android Studio 2021.1.1(Bumblebee)以降のバージョンを使用することをお勧めします。
  • 階層構造を使用しないという選択肢も用意されています。 階層構造のサポートを無効にするには、gradle.properties で以下のオプションを設定してください。

すべての改善点

言語

Kotlin/JVM

Kotlin/Native

Kotlin Multiplatform

Kotlin/JS

セキュリティ

Gradle

Kotlin 1.6.20 のインストール方法

すでに IntelliJ IDEAAndroid Studio をお使いの場合は、IDE で Kotlin 1.6.20 への自動アップデートが提案されます。 また、指定の手順に従って手動でアップデートすることもできます。

Kotlin の最大限の機能サポートを得るには、以下の最新バージョンをダウンロードしてください。

  • IntelliJ IDEA – さまざまなプラットフォームを対象とする Kotlin アプリケーションの開発に適しています。
  • Android Studio – Android とクロスプラットフォームモバイルアプリケーションの開発に適しています。

kotlinx ライブラリを互換性のあるバージョンにアップデートし、既存プロジェクトのビルドスクリプトで Kotlin のバージョン 1.6.20 を指定していることも確認してください。

コマンドラインコンパイラーが必要な場合は、GitHub のリリースページからダウンロードできます。

問題発生時は以下の対応をお願いします

最新の Kotlin 機能に関する情報を入手しましょう! この記事の右側にあるフォームにご入力いただくと、Kotlin の最新情報をお届けします。

その他の記事と動画

オリジナル(英語)ブログ投稿の作者:

Elizaveta Semakova

Andrey Polyakov

Discover more