Swift 6 で起きるランタイムクラッシュを警告に留めて移行作業をする

Swift 6 言語モードでは、エグゼキュータの等価性チェックでクラッシュが発生する可能性があります。例えば、暗黙的に MainActor なクロージャがバックグラウンドスレッドから呼ばれてクラッシュする、のようなケースです。

移行作業の最中では、クラッシュされるとアプリケーションのビルドをし直したりしないといけないので面倒なのです。

そこで便利なのが、 SWIFT_IS_CURRENT_EXECUTOR_LEGACY_MODE_OVERRIDE というランタイム環境変数です。

github.com

Xcode では Product > Scheme > Edit Scheme... から設定できます。

SWIFT_IS_CURRENT_EXECUTOR_LEGACY_MODE_OVERRIDE を設定

例えば legacy を設定すると、ランタイムクラッシュから以下のようなランタイム警告になります。MainActorな関数がメインスレッド以外から呼ばれていることがわかるようになるので、stacktraceを見るよりも対応が容易になります。

warning: data race detected: @MainActor function at {ファイル名}.swift:{行番号} was not called on the main thread

SWIFT_IS_CURRENT_EXECUTOR_LEGACY_MODE_OVERRIDE では、Swift 6.2.4 時点で以下を設定できます。

  • lagacy :
    • Swift 5 系の挙動。isolation が違ってもクラッシュせず、ランタイム警告に留まる
  • swift6 :
    • Swift 6.0-6.1の挙動をする。SerialExecutor.checkIsolated() を実行して isolation が違うとクラッシュ
  • isIsolatingCurrentContext :
    • Swift 6.2の挙動。SerialExecutor.checkIsolated() ではなく SerialExecutor.isIsolatingCurrentContext() を強制的に使う場合に設定する

移行フェーズに応じて活用してみてはいかがでしょうか。ちなみにランタイム環境変数なので、設定してクラッシュを握りつぶした状態でリリースすることはできないので注意が必要です。