この記事の要点
- Swift 6.2 がリリースされ、ソフトウェアスタックのあらゆる層で開発者の生産性を高めることを狙った幅広い改善が入りました。柱は approachable concurrency(親しみやすい並行処理)、安全なシステムプログラミング、ワークフローの効率化、コアライブラリの拡充、そして WebAssembly サポート です。
- 並行処理では、コードをデフォルトでメインアクターに isolate するオプション、
nonisolated async関数を呼び出し元の実行コンテキストで動かす upcoming feature、並行実行を明示する@concurrent属性が加わり、注釈を減らしながらデータ競合のないコードを書けるようになりました。 - システムプログラミングでは、スタックに置ける固定サイズ配列
InlineArray、連続メモリへ安全にアクセスするSpan、オプトインの strict memory safety が導入されました。 - ライブラリ面では
Subprocessパッケージ、型付きの新NotificationCenterAPI、Observations非同期シーケンス、Swift Testing の exit testing・attachments などが加わり、ツール面では VS Code 拡張機能の公式化、診断グループ単位の警告制御、マクロのビルド高速化が実現しました。
主な変更点
Approachable Concurrency(親しみやすい並行処理)
Swift 6.2 は、並行プログラミングの敷居を下げる一連の変更を導入します。
デフォルトでシングルスレッド
新しいオプションにより、@MainActor を明示的に書かなくても、モジュール全体のコードをデフォルトでメインアクターに isolate できます(SE-0466)。スクリプト、UI コード、その他の実行可能ターゲットに向いています。
直感的な async 関数
これまで nonisolated async のメソッドは常に並行スレッドプールを管理するグローバルエグゼキュータに切り替わっていたため、データ競合安全性のエラーを避けながらクラス型の async メソッドを書くのが難しいことがありました。Swift 6.2 では、async 関数を呼び出し元の実行コンテキストで実行する upcoming feature(nonisolated-nonsending-by-default)に移行できます。メインアクターから呼んだ場合はメインアクター上で実行されます(SE-0461)。
@concurrent による並行処理のオプトイン
新しい @concurrent 属性を使うと、明示的に並行実行されるコードを導入できます。これにより、コードをアクター上で直列のままにしたいのか、並列に実行してよいのかが明確になります。
// '-default-isolation MainActor' モードの場合
struct Image {
// この画像キャッシュはメインアクターで保護されているため安全です。
static var cachedImage: [URL: Image] = [:]
static func create(from url: URL) async throws -> Image {
if let image = cachedImage[url] {
return image
}
let image = try await fetchImage(at: url)
cachedImage[url] = image
return image
}
// 指定された URL からデータを取得してデコードします。
// 大きな画像のデコード中もメインアクターを空けておくため、
// この処理は並行スレッドプール上で実行されます。
@concurrent
static func fetchImage(at url: URL) async throws -> Image {
let (data, _) = try await URLSession.shared.data(from: url)
return await decode(data: data)
}
}
これらの改善により、注釈のオーバーヘッドを減らしてデータ競合のないコードを書きつつ、必要な箇所では並行処理を導入できます。なお、Swift 6.1 で導入された型・エクステンションへの nonisolated(SE-0449)も、この一連の取り組みの一部です。
安全なシステムプログラミング
Swift 6.2 には、安全性を損なわずに性能を引き出すための機能が含まれます。
InlineArray
InlineArray は、要素をインラインに格納する新しい固定サイズ配列です(SE-0453)。ヒープに追加で確保することなく、スタックや他の型の内部に直接格納できます。サイズを要素型の前に山括弧で書くか、of の糖衣構文(SE-0483)で書けます。
struct Game {
// InlineArray<40, Sprite> の糖衣構文
var bricks: [40 of Sprite]
init(_ brickSprite: Sprite) {
bricks = .init(repeating: brickSprite)
}
}
Span
新しい Span 型は、連続メモリへの安全で直接的なアクセスを提供します(SE-0447)。Span は、使用中はメモリが有効であり続けることを保証し、メモリ安全性を維持します。これらの保証はコンパイル時にチェックされ、実行時オーバーヘッドはありません。ポインタにつきものの use-after-free のようなメモリ安全性の問題を、設計レベルで排除します。標準ライブラリの各種型には Span を返すプロパティが追加されています(SE-0456)。Span は、Swift 6.2 で導入された non-escapable 型(SE-0446)の上に成り立っています。
低レベル・セキュリティ用途の強化
- Embedded Swift: Embedded Swift で、Swift の完全な
StringAPI、クラス制約付きプロトコルのany型、そして新しいInlineArrayとSpan型が使えるようになりました。 - 安全な C++ 相互運用: Swift と C++ を混在させるプロジェクトで、ヘッダのアノテーションを通じて C++ の API に対して
Spanのような Swift の安全な抽象を活用できます。 - オプトインの strict memory safety: Swift 6.2 は オプトインの strict memory safety を導入します(SE-0458)。unsafe ポインタなど unsafe な構文の使用箇所を検出し、安全な代替への置き換えや、ソースコード上での明示的な承認を促します。大半のプロジェクトにこのレベルの強制は不要なため、最も強いセキュリティ要件を持つプロジェクト向けのオプトインとされています。
ワークフローの効率化
VS Code 向け Swift 拡張機能
VS Code 向け Swift 拡張機能が、Swift.org によって公式に検証・配布されるようになりました。最新版には次が含まれます。
- デフォルトでの background indexing: ジャンプ先の定義表示やコード補完などの編集機能を、常に最新の状態で高速に利用できます。
- LLDB デバッグの組み込み: VS Code 内で LLDB を使い、Swift コードのステップ実行・ブレークポイント設定・状態の確認ができます。
- Swift プロジェクトパネル: Explorer ビューで、ターゲット・依存関係・タスクを辿れます。
- DocC のライブプレビュー: レンダリングされたドキュメントを、コードの横で入力に追従しながらプレビューできます。
精密な警告制御
Swift 6.2 では、警告を 診断グループ 単位で制御できるようになりました(SE-0480)。診断グループとは、名前で識別される警告のカテゴリです。パッケージのマニフェストで SwiftSetting の treatWarning メソッドを使ってグループごとの挙動を指定したり、treatAllWarnings ですべての警告をエラーに昇格させたりできます。たとえば、非推奨 API の警告だけを除いてすべての警告をエラーにできます。
.target(
name: "MyLibrary",
swiftSettings: [
.treatAllWarnings(as: .error),
.treatWarning("DeprecatedDeclaration", as: .warning),
]
)
マクロのビルド性能
Swift 6.2 では、マクロベースの API を使うプロジェクトのクリーンビルド時間が大きく改善されました。従来はマクロをビルドする前に swift-syntax パッケージをソースから取得・ビルドする必要があり、特に CI 環境でコンパイル時間が目立って長くなっていました。SwiftPM がプリビルドの swift-syntax 依存に対応し、この高価なビルド工程を完全に省けるようになりました。
非同期デバッグの強化
LLDB での並行コードのデバッグが容易になりました。
- 堅牢な
asyncステッピング: スレッドの切り替えを伴う非同期呼び出しでも、async関数へ確実にステップインできます。 - タスクコンテキストの表示: ブレークポイントで停止したときや、現在のスレッドのバックトレース表示時に、コードがどのタスク上で動いているかを確認できます。
- 名前付きタスク: タスク作成時に人間が読める名前を付けられ、デバッグやプロファイリングのツールで表示されます。
upcoming feature への移行
Swift 6.2 には、upcoming feature を導入しやすくする 移行ツール が含まれます。移行ツールの警告で、有効化するとコンパイルできなくなる・挙動が変わるコードパターンを特定し、既存の挙動を保つ fix-it を適用できます。手作業でのコード変更を省き、upcoming feature の有効化を効率化します。詳しくは Swift migration guide を参照してください。
コアライブラリ
Subprocess
Swift 6.2 は、外部プロセスの起動・管理のための、並行処理に親和性の高い新しい Subprocess パッケージを導入します。async/await ベースの API、プロセス実行のきめ細かな制御、プラットフォーム固有の設定などを備え、スクリプティング・自動化・サーバーサイドの処理に向いています。
import Subprocess
let swiftPath = FilePath("/usr/bin/swift")
let result = try await run(
.path(swiftPath),
arguments: ["--version"]
)
let swiftVersion = result.standardOutput
これはバージョン 0.1 の API です。利用からのフィードバックが 1.0 の API に反映されます(swift-subprocess リポジトリ)。
Foundation
Foundation に、文字列や型のない辞書ではなく具体的な通知型を使う、モダンな NotificationCenter API が加わりました。stored property を持つ通知の構造体を定義でき、観測側は誤りやすい添字アクセスや動的キャストなしにその型を使えます。通知型は、メインアクター上で同期的に投稿されるか非同期に投稿されるかを、MainActorMessage または AsyncMessage への適合で表現します。これにより、メインアクターの通知を扱う際の並行処理エラーがなくなります。
Observation
Swift 6.2 では、新しい Observations 非同期シーケンス型を使って、observable な型のトランザクショナルな状態変化をストリーミングできます(SE-0475)。更新は observable プロパティへの同期的な変更をすべて含み、トランザクションは次に中断する await で終わります。これにより冗長な UI 更新を避け、性能を改善し、コードが一貫したスナップショットに反応することを保証します。
Swift Testing
Swift Testing には、テストとその結果の表現力を高める API が加わりました。
- exit test: 失敗した precondition のような特定の条件下でコードが終了することを検証できます(ST-0008)。exit test は新しいプロセスで実行され、終了の挙動が期待どおりかを確かめます。
- attachments: 文字列・画像・ログなどの追加コンテキストをテスト結果に含め、レポートに表示したりディスクに書き出したりできます(ST-0009)。失敗の診断に具体的な証跡を添えられます。
-
raw identifier の表示名: SE-0451 の raw identifier により、テスト関数やスイート型の名前を少ないコードでカスタマイズできます。
-@Test("square() returns x * x") -func squareIsXTimesX() { +@Test func `square() returns x * x`() { #expect(square(4) == 4 * 4) }
WebAssembly サポート
Swift 6.2 は WebAssembly(Wasm)のサポートを獲得しました。Wasm は、ポータビリティ・セキュリティ・高性能に重点を置いた仮想マシンプラットフォームです。クライアントとサーバーの双方のアプリケーションを Wasm 向けにビルドし、ブラウザやその他のランタイムへデプロイできます。詳しくは WebAssembly サポートの vision ドキュメントを参照してください。
Swift 利用者への影響
- 並行処理の注釈を減らせます。 デフォルトでメインアクターに isolate するオプションや、
async関数を呼び出し元コンテキストで動かす upcoming feature により、ボイラープレートを減らしながらデータ競合のないコードを書けます。並列実行したい箇所だけ@concurrentで明示できます。 - 安全な低レベルコードが書きやすくなります。
InlineArrayでヒープ確保を避け、Spanで実行時オーバーヘッドなしに連続メモリへ安全にアクセスできます。strict memory safety はオプトインで、最も厳しいセキュリティ要件のプロジェクトを支えます。 - 日々の開発サイクルが滑らかになります。 公式化された VS Code 拡張機能、診断グループ単位の警告制御、マクロのビルド高速化、改善された非同期デバッグにより、編集・ビルド・デバッグの反復が楽になります。
- ライブラリがよりモダンになります。
Subprocessで外部プロセスを async/await で扱え、型付きのNotificationCenterとObservationsでデータ競合や冗長な UI 更新を避けられます。Swift Testing の exit test・attachments でテストの表現力が増します。 - 新しいターゲットへ広がります。 WebAssembly サポートにより、Swift コードをブラウザや各種ランタイムへデプロイできるようになります。
関連 Proposal・リンク
- 前のリリースについては Swift 6.1 リリース を参照してください。
- 本記事で触れた Proposal ダイジェスト:
- Swift 6.2 に含まれる言語進化の Proposal 一覧: Swift Evolution dashboard
- Swift のインストール