Swift5 & Strict Concurrency Checking(complete)で警告では無くコンパイルエラーが出る件について調べるスレ
https://zenn.dev/link/comments/441f784c272216 のエラーが出たので調べた。
結論
Swift 5.5 までは UIKit で付与される MainActor は MainActor(unsafe) なので非隔離ドメインから同期的なアクセスをしてもコンパイルエラーにはならないものの、Swift5.6以上のある時点から UIKit側の MainActor(unsafe) が MainActor に変わりコンパイルエラーとなった模様。
UIKit の class に付与された MainActor の実態
- swift5.8.1以上〜swift6以下: MainActor
- swift5.6..5.8: 未検証なので不明
- swift5.5: MainActor(unsafe)
同期非隔離ドメインからUIKit由来のMainActor隔離メソッドの呼び出しがどうなるか
Xcode 14.3.1以上〜15.4以下 & strict concurrency checking=complete
UIKitのextensionを同期非隔離ドメインから呼ぶとコンパイルエラーになる。
Xcode 14以上〜14.3以下 & strict concurrency checking=complete
未検証だが、UIKitのextensionを同期非隔離ドメインから呼ぶとコンパイルエラーになりそう。
Xcode 13(swift5.5)
未検証。Xcode13でUIKitのextensionをnon-isolatedなコンテキストで呼んでも MainActor(unsafe)
なので検査は無視されコンパイルエラーにならない。(明示的にUIViewControllerをサブクラスして@MainActorを付与したケースは異なりそう)
手元のプロジェクト(Xcode15.4)の Strict Concurrency Checking を Complete にしてみるも、UIViewController の extension のメソッドを呼び出すコードで Call to main actor-isolated instance method 'xxx()' in a synchronous nonisolated context
的なコンパイルエラーが出て戸惑う。Strict Concurrency Checkingってswift5では警告にしかならないんじゃなかったっけ..?
Strict Concurrency Checkingってswift5では警告にしかならない
↑の想定が正しいかを調べる。Enabling Complete Concurrency Checking というドキュメントがあったので読む。
you can enable the compiler’s actor isolation and Sendable checking as warnings in the Swift 5 language mode
とか
To enable complete concurrency checking when running swift or swiftc directly at the command line, pass -strict-concurrency=complete:
などからは警告に留まるような書き方に見える。
giginetさんのスライドを見つけて読んでみると、以下の記述がありどうやら swift5 & concurrency checking = complete でもエラーになるケースがある模様
MainActor(unsafe)
が有効になる
UIViewControllerなど、メインスレッドでの動作を想定している実装がMainActor以外から呼べなくなる
https://speakerdeck.com/giginet/go-beyond-the-actor-boundary?slide=20
MainActor(unsafe) が有効になる
はどのタイミングで有効になったんだろう。
swift 5.10から変わっていったのかな(改めて 5.10 のリリースは読み込んどきたい)
5.9.1と5.9をそれぞれtoolchain変えて試してみる。
ここで古いswift toolchainを落としてみる
toolchainをインストールした後は Xcode > Toolchains
から切り替えできる。
結果、5.9.1と5.9でも https://zenn.dev/link/comments/441f784c272216 のエラーは出たまま。
https://forums.swift.org/t/concurrency-in-swift-5-and-6/49337 UIKitのNS_SWIFT_UI_ACTORはSwift5.5ではMainActor(unsafe) なので利用側が concurrency の機能を使っている時だけ強制されると思います
前に教えてもらったんですが、Swift 5.5の時点ではUIViewControllerなどがMainActorなのはオプトインっぽい
なるほど。swift5.6以上のどこかのタイミングではUIKitのNS_SWIFT_UI_ACTOR
がMainActor(unsafe)
ではなくMainActor
になる。なのでUIViewControllerのextensionの呼び出し側でエラーになるという流れだった。(コミュニティの皆さんの会話助かる)
以下のような話もありややこしい
データ競合により意図しない値の変更に悩まされた時に、原因調査の手段として以前からコンパイラ・オプション-strict-concurrency=completeは有った。このオプションはコードを部分的に調査するものだったのが、5.10からすべての安全でないコードにコンパイルエラーを発する様になった。