🫀

Swift5.10 新機能: 厳密な並行処理チェック

2024/04/03に公開

次のコードをターミナル上でコンパイルする。

strict.swift
var v = 1
// nonisolated(unsafe) var v = 1
func f() {
  v = 2
}
f()
print(v) // => 2

コンパイル・オプションは次の通り

$ swift -strict-concurrency=complete strict.swift
strict.swift:4:3: error: main actor-isolated var 'v' can not be mutated from a non-isolated context
  v = 2
  ^
strict.swift:1:5: note: mutation of this var is only permitted within the actor
var v = 1
    ^
strict.swift:3:6: note: add '@MainActor' to make global function 'f()' part of global actor 'MainActor'
func f() {
     ^
@MainActor

データ競合により意図しない値の変更に悩まされた時に、原因調査の手段として以前からコンパイラ・オプション-strict-concurrency=completeは有った。このオプションはコードを部分的に調査するものだったのが、5.10からすべての安全でないコードにコンパイルエラーを発する様になった。

今回のコードの場合コンパイルエラーを取り除くには次の手段がある

1. 変数vへの同時アクセスするコードは無いので原因調査の対象から外す。つまりnonisolated(unsafe) var v = 1とコードを書き換えれば良い
2. 変数vを書き換える処理を含むf()を相互排他制御(Mutex, Mutual Exclusion)の対象とする。つまり@MainActor func f()...とコードを書き換える。排他制御は計算コストの増大を招く。本当に必要でない場合はコードの書き換えを避ける
3. コンパイラ・オプションを取る

環境

$ sw_vers
ProductName:		macOS
ProductVersion:		14.4.1
BuildVersion:		23E224
$ swift -v
Apple Swift version 5.10 (swiftlang-5.10.0.13 clang-1500.3.9.4)
Target: arm64-apple-macosx14.0

swift-evolution/proposals/0412-strict-concurrency-for-global-variables.md at main · apple/swift-evolution
Swift 6 に備える - 今後の機能(Upcoming Feature)の段階的適用 編

Discussion