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

型付き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

同期のための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 5モードでの警告

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

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

ファイル単位での移行

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

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との互換性も維持されています。

← 一覧に戻る