Swift 6リリース - 完全な並行性安全を実現

2025.12.08

公式ドキュメント

Swift 6の概要

2024年9月、Xcode 16と共にSwift 6がリリースされました。このバージョンの最大の特徴は、データ競合を完全にコンパイル時に防止できるようになったことです。

参考: Swift.org - Swift 6

データ競合の完全な防止

Swift 6言語モード

Swift 6では、データ競合がコンパイルエラーになります。

// Package.swift で Swift 6モードを有効化
// swift-tools-version: 6.0

var counter = 0

func increment() async {
 counter += 1 // エラー: データ競合の可能性
}

Sendableの厳格化

// Sendableでないオブジェクトを並行コンテキストに渡せない
class UnsafeClass {
 var value = 0
}

func example() async {
 let obj = UnsafeClass()

 Task {
 obj.value += 1 // エラー: UnsafeClassはSendableでない
 }
}

// 解決策1: Sendable準拠
final class SafeClass: Sendable {
 let value: Int // 不変にする
 init(value: Int) { self.value = value }
}

// 解決策2: アクターを使用
actor Counter {
 var value = 0
 func increment() { value += 1 }
}

参考: Swift Concurrency

ポイント: Swift 6ではSendableでないオブジェクトを並行コンテキストに渡すとコンパイルエラーになります。@Sendableクロージャやactorを活用してデータ競合を防ぎましょう。

型付きthrows

エラーの型を明示的に指定できるようになりました。

// 従来: anyエラー
func legacyParse() throws -> Data {
 throw ParseError.invalidFormat
}

// Swift 6: 型付きthrows
enum ParseError: Error {
 case invalidFormat
 case emptyInput
}

func parse() throws(ParseError) -> Data {
 throw .invalidFormat
}

// 呼び出し側で型が分かる
do {
 let data = try parse()
} catch {
 // errorの型はParseError
 switch error {
 case .invalidFormat:
 print("フォーマットエラー")
 case .emptyInput:
 print("入力が空")
 }
}

never を使った絶対に失敗しない関数

// 絶対にエラーを投げない
func safeParse() throws(Never) -> Data {
 return Data()
}

// tryなしで呼び出せる
let data = safeParse()

128ビット整数

let big: Int128 = 170_141_183_460_469_231_731_687_303_715_884_105_727
let ubig: UInt128 = 340_282_366_920_938_463_463_374_607_431_768_211_455

print(big.bitWidth) // 128

Embedded Swift

リソース制限のある環境(マイクロコントローラーなど)向けのSwiftサブセット。

// Embedded Swift用のコード
@main
struct LEDBlink {
 static func main() {
 let led = DigitalOutput(pin: 13)

 while true {
 led.toggle()
 sleep(milliseconds: 500)
 }
 }
}
# Embedded Swiftでビルド
swiftc -enable-experimental-feature Embedded -target armv7em-none-eabi main.swift

参考: Embedded Swift Vision

C++相互運用性の改善

C++からSwiftへ

// C++ヘッダー
class CppCounter {
public:
 CppCounter(int initial);
 void increment();
 int getValue() const;
private:
 int value;
};
// Swiftから使用
import CppCounter

let counter = CppCounter(42)
counter.increment()
print(counter.getValue()) // 43

SwiftからC++へ

// Swift
@_expose(Cxx)
public func swiftFunction() -> Int {
 return 42
}
// C++から呼び出し
#include "MyModule-Swift.h"

int result = swiftFunction();

参考: Swift C++ Interoperability

注意: Swift 6言語モードを有効にすると、既存コードでコンパイルエラーが発生する可能性があります。大規模プロジェクトでは段階的な移行を推奨します。

同期のためのMutexとAtomic

import Synchronization

// Mutex
let mutex = Mutex(initialValue: 0)

mutex.withLock { value in
 value += 1
}

// Atomic
let atomic = Atomic<Int>(0)

atomic.wrappingAdd(1, ordering: .relaxed)
let current = atomic.load(ordering: .acquiring)

実践メモ: Swift 6への移行はファイル単位で段階的に行えます。まずSwift 5モードで警告を有効にし、問題を把握してから移行しましょう。

段階的なマイグレーション

Swift 5モードでの警告

// Package.swift
let package = Package(
 swiftLanguageVersions: [.v5], // まだSwift 5
 // ...
)

// 並行性警告を有効化
swiftSettings: [
 .enableUpcomingFeature("StrictConcurrency")
]

ファイル単位での移行

// 特定のファイルだけSwift 6モードに
// ファイル先頭に追加
// swift-tools-version: 6.0

Xcode 16との統合

ビルド設定

Xcode 16 ビルド設定:

SWIFT_VERSION = 6.0
SWIFT_STRICT_CONCURRENCY = complete

新しい警告と修正提案

// Xcodeが自動修正を提案
class MyClass {
 var data: [Int] = []

 func process() async {
 // 警告 + Fix-it: @MainActor を追加
 data.append(1)
 }
}

パフォーマンス改善

項目Swift 5.10Swift 6
コンパイル速度基準+15%
バイナリサイズ基準-10%
実行速度基準+5%

まとめ

Swift 6は、言語の安全性を新たなレベルに引き上げました。

  • データ競合防止: コンパイル時に完全に検出
  • 型付きthrows: エラーハンドリングの改善
  • 128ビット整数: 大きな数値のサポート
  • Embedded Swift: 組み込みシステム対応
  • C++相互運用: より深い連携

既存のプロジェクトは段階的に移行でき、Swift 5との互換性も維持されています。

参考リソース

← 一覧に戻る
PR
PR
PR
PR