🔖
【Swift Concurrency】引数に付与するsendingキーワードについて
引数に付与するsendingキーワード
現在sendingキーワードは、「引数に付与するケース」と「返り値に付与するケース」があります。本記事では、引数に付与する場合のsendingキーワードについて解説していきます。
引数に付与するsendingキーワードは、「関数がnon-Sendableな値を引数として受け取るときに、その値が呼び出し元で引き渡し後に使用されないこと」を保証させるキーワードです。
これにより、引数として受け取ったnon-Sendableな値が隔離境界(isolation boundary)を超えることができるようになります。[1]
以下のコードでは、action2関数内でNonSendableClassのインスタンスを生成し、action1関数の引数として、生成したインスタンスを渡しています。
class NonSendableClass { var num = 0 }
func action1(nonSendableClass: sending NonSendableClass) {
Task { @MainActor in
print(nonSendableClass)
}
}
func action2() {
let nonSendableClass = NonSendableClass()
action1(nonSendableClass: nonSendableClass)
}
action1関数の引数として受け取るNonSendableClassのインスタンスは、action1関数内でnon-isolatedな隔離領域からMainActorの隔離領域に渡ります。(つまりは隔離境界を超える。)
そのため、「関数がnon-Sendableな値を引数として受け取るときに、その値が呼び出し元で引き渡し後に使用されないこと」を保証させるsendingキーワードが必要です。
蛇足
もし、以下コードのように引き渡し後にnonSendableClassにアクセスした場合は、エラーで教えてくれます。
class NonSendableClass { var num = 0 }
func action1(nonSendableClass: sending NonSendableClass) {
Task { @MainActor in
print(nonSendableClass)
}
}
func action2() {
let nonSendableClass = NonSendableClass()
action1(nonSendableClass: nonSendableClass) // ※1
print(nonSendableClass) // nonSendableClassにアクセス
}
// ※1: Sending 'nonSendableClass' risks causing data races
参考
Xcode 16 & Swift 6 キャッチアップ: Swift Concurrencyの基礎と最重要ポイントを総復習 - YouTube
swift-evolution/proposals/0430-transferring-parameters-and-results.md at main · swiftlang/swift-evolution · GitHub
-
このような隔離境界を超えることができる値を
sending valueと呼びます。 ↩︎
Discussion