Swift: Task.detachedのoperationには@_implicitSelfCaptureが付いていない
環境
- Swift 5.10
SE-0304 Structured concurrencyにおける記述
The closure passed to Task is executed immediately, and the only reference to self is what occurs in the body. Therefore, the explicit self. isn't communicating useful information and should not be required.
Note: The same applies to the closure passed to Task.detached and TaskGroup.addTask.
2024/07/13現在、SE-0304 Structured concurrencyには Task.detached
にも Task.init
と同様に、クロージャに @_implicitSelfCapture
が付くよ的なことが書いてある。
しかし、実際には付いていない。実装と異なっている。
コード上の様子
Task.init(priority:operation:)
operation
に @_implicitSelfCapture
が付いている。
Task.detached(priority:operation:)
operation
に @_implicitSelfCapture
が付いておらず、Swift Evolutionの記述と異なっている。
@_implicitSelfCapture
とは
Selfが参照型の場合でも、明示的にキャプチャせずにクロージャ内のselfにアクセスできるようする。
swiftlang/swiftにおいて、Concurrency文脈以外では特に使われていなさそうだった。
考察
Task.init
は呼び出し側のActor上で実行され、クロージャの実行は速やかに行われる。そのため、クロージャ内のselfへの参照が発生しても、本体による参照となるため循環参照は起こらないだろう。
一方で、Task.detached
は呼び出し側のActorとは別でクロージャの実行が行われる。スレッドが変わるため、selfの参照をクロージャ内で持つと循環参照が発生する。よって、開発者側で明にselfをキャプチャさせた方が意識的に循環参照の発生リスクを減らせるため、今のまま @_implicitSelfCapture
は付けない方が良いと思う。
ちなみに、去年に同じ内容でフォーラムに上がっていて、似たようなコメントがある。
参考
- https://docs.swift.org/swift-book/documentation/the-swift-programming-language/closures/#Escaping-Closures
- https://github.com/swiftlang/swift-evolution/blob/main/proposals/0304-structured-concurrency.md
- https://github.com/swiftlang/swift/blob/main/docs/ReferenceGuides/UnderscoredAttributes.md?ref=blog.personal-factory.com#_implicitselfcapture
- https://forums.swift.org/t/task-detached-doesn-t-allow-implicit-self/63862/4
Discussion