この記事の要点
- Swift 6 が正式リリースされました。最大の目玉は、データ競合をコンパイルエラーとして検出する新しい言語モード(Swift 6 language mode) です。これはオプトインで、データ競合安全性を Swift の安全性保証の一部として組み込みます。
- 言語面では typed throws(
throwするエラー型をシグネチャで指定)、non-copyable 型のジェネリクス対応、C++ 相互運用の拡張、128-bit 整数型、各種の生産性向上機能が加わりました。 - 低レベル並行処理向けの Synchronization ライブラリ(アトミック操作・mutex)、組み込み開発向けの Embedded Swift(プレビュー)も導入されました。
- ライブラリ面では、すべてのプラットフォームで実装を統一した Foundation、Swift 向けに設計された新しいテストライブラリ Swift Testing が標準で利用できるようになりました。
- プラットフォーム面では Linux 向けの完全静的リンク SDK、新たな Linux ディストリビューション対応、Windows のビルド性能向上など、Linux と Windows のサポートが大きく強化されました。
主な変更点
言語と標準ライブラリ
並行処理(データ競合安全性)
Swift はこれまでも、変数が使用前に初期化されていること、解放後のメモリにアクセスしないこと、配列の添字が範囲外でないことを保証するメモリ安全性を提供してきました。Swift 6 では、これらの安全性保証を並行コードにも拡張し、潜在的なデータ競合をコンパイルエラーとして診断する、オプトインの新しい言語モードが加わりました。
データ競合安全性のチェックは、Swift 5.10 では -strict-concurrency=complete コンパイラフラグによる警告として利用できました。Swift 6 では、Sendable の推論の改善と、ミュータブルな状態をあるアクターから別のアクターへ transfer(転送)する操作に対する新しいコンパイラ解析(SE-0414)により、データ競合安全性に関する警告の偽陽性が減りました。Swift 6 language mode への移行方法は Swift.org/migration にまとまっています。
Swift 6 はデータ競合安全性を劇的に扱いやすくするための出発点であり、その使い勝手は引き続き活発に開発が進められています。
Swift 6 にはあわせて、アトミック操作や新しい mutex API などの低レベル並行処理向けの Synchronization ライブラリ(SE-0410 / SE-0433)も導入されました。
typed throws
Swift 6 では、関数が throw するエラーの型をシグネチャの一部として指定できるようになりました(SE-0413)。クライアントコードで throw されたエラーをそのまま転送するジェネリックなコードや、Embedded Swift のようにメモリ割り当てができないリソース制約の厳しい環境で役立ちます。
func parseRecord(from string: String) throws(ParseError) -> Record {
// ...
}
parseRecord(from:) を呼ぶと、Record のインスタンスを返すか、ParseError 型のエラーを throw します。do..catch では error 変数の型が ParseError と推論されます。
do {
let record = try parseRecord(from: myString)
} catch {
// 'error' has type 'ParseError'
}
typed throws は、エラーを throw する関数と throw しない関数を統一的に扱います。エラー型を指定しない throws は throws(any Error) と等価で、throw しない関数は throws(Never) と等価です。throws(Never) の関数の呼び出しはエラーを throw しないため、呼び出し側でのエラー処理は不要です。
typed throws は、rethrows よりも正確な形で、引数のエラー型をジェネリック関数に伝播させるのにも使えます。たとえば Sequence.map は、クロージャ引数が throw するエラー型をそのまま伝播でき、クロージャと同じ型のエラーしか throw しないことを表現できます。
extension Sequence {
func map<T, E>(_ body: (Element) throws(E) -> T) throws(E) -> [T] {
// ...
}
}
ParseError を throw するクロージャを渡すと map は ParseError を throw し、throw しないクロージャを渡すと E は Never と推論されて map は throw しません。
所有権(ownership)
Swift 5.9 では、唯一の所有権を持つリソースをモデル化し、コピーに伴う実行時オーバーヘッドを取り除いて性能を意識したコードを書くために、~Copyable 構文による non-copyable な型が導入されました。Swift 6 では、これらの型をジェネリクスシステムで扱えるようになり(SE-0427)、copyable な型と non-copyable な型の両方で動くジェネリックなコードを書けます。
protocol Drinkable: ~Copyable {
consuming func use()
}
struct Coffee: Drinkable, ~Copyable { /* ... */ }
struct Water: Drinkable { /* ... */ }
func drink(item: consuming some Drinkable & ~Copyable) {
item.use()
}
drink(item: Coffee())
drink(item: Water())
Drinkable プロトコルは、適合する型が Copyable であることを要求しません。そのため、non-copyable な Coffee も copyable な Water も、ジェネリックな drink 関数に渡せます。
switch 文を、enum のパターンマッチでコピーを発生させないように書けるようにもなりました(SE-0432)。これにより、non-copyable なペイロードを持つ enum でも switch を使えるほか、Array や Dictionary のような copy-on-write のコンテナに基づく copyable なペイロードでも性能上の利点が得られます。
non-copyable な型は標準ライブラリでもすでに使われています。たとえば Synchronization ライブラリの新しい Atomic 型は ~Copyable に基づいており、Optional と Result は non-copyable な型を包めるようになり、unsafe buffer pointer 系の型は non-copyable な要素を指せるようになりました(SE-0437)。C++ 相互運用でも、C++ の move-only 型を Swift に公開するために non-copyable な型を使います。
C++ 相互運用
Swift 5.9 では、既存のプロジェクトへ Swift をシームレスに導入するため、C++ との双方向の相互運用が導入されました。Swift 6 では、C++ の move-only 型、仮想メソッド、デフォルト引数、std::map や std::optional を含むより多くの標準ライブラリ型へと、相互運用のサポートが拡張されました。
コピーコンストラクタを持たない C++ 型は、Swift 6 から ~Copyable の non-copyable な型としてアクセスできます。また、性能のためにコピーコンストラクタを持つ C++ 型を Swift 側で ~Copyable として公開したい場合には、その C++ 型に SWIFT_NONCOPYABLE アノテーションを付けられます。
SWIFT_SHARED_REFERENCE や SWIFT_IMMORTAL_REFERENCE を付けた型に対する C++ の仮想メソッド呼び出しもサポートされました。一部のパラメータにデフォルト引数値を持つ C++ の関数やメソッドを呼ぶとき、Swift はそのデフォルト値を尊重し、明示的に引数を渡す必要がなくなりました。
Embedded Swift
Swift 6 には、マイクロコントローラのプログラミングのような組み込みソフトウェア開発に適した言語サブセットおよびコンパイルモードである Embedded Swift のプレビューが含まれます。ツールチェインは ARM と RISC-V のベアメタルターゲットに対応します。
Embedded Swift は、ジェネリックの特殊化(generic specialization)に頼ることで、小さく自己完結したバイナリを生成します。ランタイムや型のメタデータに依存しないため、メモリ制約の厳しいプラットフォームや、ランタイム依存の限られた低レベル環境での利用に適しています。
Embedded Swift は引き続き実験的機能であり、将来の Swift リリースで安定サポートされるまで開発が続けられます。
128-bit 整数
Swift 6 では、符号付き・符号なしの 128-bit 整数型(SE-0425)が追加され、低レベルの整数プリミティブが一通りそろいました。すべての Swift プラットフォームで利用でき、標準ライブラリの他の固定幅整数型と同じ API を提供します。
生産性向上
Swift 6 には多くの生産性向上機能が含まれます。シーケンスのうち述語を満たす要素数を簡潔に数える count(where:)(SE-0220)、value parameter pack の要素に対して自然な for ループを書ける pack iteration(SE-0408)、実装の詳細が公開 API に漏れないようにする import のアクセス制御(SE-0409)、関数の実装を合成・拡張する @attached(body) マクロ(SE-0415)、デフォルト引数としての式マクロ(SE-0422)などです。
Swift 6 で実装された言語進化のProposalの一覧は Swift Evolution dashboard で確認できます。
デバッグ
@DebugDescription による LLDB サマリのカスタマイズ
Swift 6 では、LLDB で p コマンドを使ったときや、Xcode・VSCode の変数ビューでオブジェクトがどう表示されるかを、任意のコードを実行しない書式スキームで簡単にカスタマイズできる新しいデバッグ用マクロが加わりました(SE-0440)。
CustomDebugStringConvertible に適合する型は、オブジェクトを説明する文字列を返す debugDescription プロパティを提供します。LLDB の po コマンドはこの computed property を呼び出します。一方 p コマンドは、LLDB の type summary formatter を使って、stored property の値から直接オブジェクトを整形します。
@DebugDescription は標準ライブラリの新しいマクロで、自分の型に対する LLDB の type summary をコード中で直接指定できます。このマクロは debugDescription プロパティを処理し、stored property を使った単純な文字列補間を LLDB の type summary に変換します。これにより、p コマンドや Xcode・VSCode の変数表示でも独自の書式が使われるようになります。
@DebugDescription
struct Organization: CustomDebugStringConvertible {
var id: String
var name: String
var manager: Person
// ... and more
var debugDescription: String {
"#\(id) \(name) [\(manager.name)]"
}
}
explicit module による起動性能の向上
Swift 6 では、explicit module build を使うときのデバッガの起動性能が大きく向上しました。ローカルでビルドしたコードをデバッグする際、LLDB はプロジェクトのビルド成果物から、明示的にビルドされた Swift・Clang モジュールを直接 import できるようになりました。これにより、暗黙的な Clang モジュール依存をソースから再コンパイルする必要がなくなります。再コンパイルは時間がかかるうえ、ヘッダの検索パスの問題に影響されやすいものでした。
ライブラリ
Foundation
Swift 6 では、Foundation の実装がすべてのプラットフォームで統一されました。モダンでポータブルな Swift 実装はプラットフォーム間の一貫性を高め、より堅牢で、オープンソースです。macOS と iOS は Swift 5.9 から Swift 実装の Foundation を使い始めており、Swift 6 ではこの改善が Linux と Windows にも届きます。
JSONDecoder、URL、Calendar、FileManager、ProcessInfo などのコア型は、完全に Swift で再実装されました。これらは macOS 15 / iOS 18 と実装を共有し、クロスプラットフォームでの一貫性・信頼性・性能を新たな水準に引き上げます。FormatStyle、ParseStrategy、Predicate、JSON5 といった近年の API もすべての Swift プラットフォームで利用できるようになりました。
バイナリサイズに特に敏感なアプリでは、国際化・ローカライズデータを省いた、より絞り込んだサブセットを提供する FoundationEssentials ライブラリを import できます。
Swift Testing
Swift 6 では、Swift のために一から設計された新しいテストライブラリ Swift Testing が導入されました。テストの記述と整理を容易にする表現力の高い API を備え、#expect などのマクロでテスト失敗時に詳細な出力を提供し、パラメータ化により異なる引数でテストを繰り返せます。
@Test("Continents mentioned in videos", arguments: [
"A Beach",
"By the Lake",
"Camping in the Woods"
])
func mentionedContinents(videoName: String) async throws {
let videoLibrary = try await VideoLibrary()
let video = try #require(await videoLibrary.video(named: videoName))
#expect(video.mentionedContinents.count <= 3)
}
Swift Testing はマクロを最大限に活用します。@Test / @Suite のアタッチドマクロでテスト関数とスイート型を宣言し、トレイトと呼ばれる引数で挙動をカスタマイズします。#expect / #require の式マクロは期待される挙動を検証し、式とその部分値の豊かな表現を捕捉して詳細な失敗メッセージを生成します。
Swift Testing は Swift 6 ツールチェインに直接含まれるため、パッケージ依存を宣言せずに import Testing できます。Swift 6 のパッケージマネージャは、XCTest(存在する場合)に加えて Swift Testing のテストも自動でビルド・実行します。Apple の全プラットフォーム、Linux、Windows に対応します。
プラットフォームサポート
Swift 6 では Linux と Windows のサポートが全面的に強化され、より多くの Linux ディストリビューションと Windows アーキテクチャに対応しました。
- Linux 向けの完全静的 SDK: 外部依存のない完全に静的リンクされた実行ファイルを Linux 向けにビルドできます。システムやコンテナに直接コピーして、追加のソフトウェアをインストールせずに実行したい場面に最適です。他のプラットフォームから Linux へのクロスコンパイルにも使えます。
- 新しい Linux ディストリビューション: Debian と Fedora、および Ubuntu 24.04 が公式にサポート・テストの対象になりました。
- Windows のビルド性能: arm64 アーキテクチャ向けのプリビルドツールチェインが提供され、Windows on ARM ホストでのコンパイラ性能が向上しました。Swift パッケージマネージャは Windows でもデフォルトで複数コアにわたってビルドを並列化するようになり、10 コアのマシンではビルド性能が最大 10 倍向上することもあります。
Swift 利用者への影響
- 並行コードがコンパイル時に安全になります。 Swift 6 language mode を有効にすると、データ競合がコンパイルエラーとして検出されます。オプトインのため、準備が整ってから段階的に移行できます(移行方法は Swift.org/migration)。
- エラー処理をより正確に書けます。 typed throws により、関数が
throwするエラー型をシグネチャで明示でき、ジェネリックコードでのエラー伝播やメモリ割り当てのできない環境で役立ちます。 - 低レベル・高性能なコードが書きやすくなります。 non-copyable な型をジェネリクスで扱えるようになり、
switchのコピー回避、128-bit 整数、Synchronization ライブラリのアトミック操作・mutex も利用できます。 - C++ コードベースとの連携が広がります。 move-only 型、仮想メソッド、デフォルト引数、
std::map/std::optionalなどへ相互運用が拡張されました。 - クロスプラットフォーム開発が現実的になります。 統一された Foundation、標準同梱の Swift Testing、Linux の静的 SDK や新ディストリビューション対応、Windows のビルド高速化により、1 つのコードベースをより多くの環境へ展開できます。組み込み領域には Embedded Swift のプレビューが道を開きます。
関連 Proposal・リンク
- 前のリリースについては Swift 5.10 リリース を参照してください。
- 本記事で触れた Proposal ダイジェスト:
- Swift 6 に含まれる言語進化のProposal一覧: Swift Evolution dashboard
- Swift のインストール
- The Swift Programming Language