The compiler(*) emits errors while the following code is being compiled with Swift 6 language mode:
(*) 6.0.2 and DEVELOPMENT-SNAPSHOT-2024-11-09-a
// -swift-version 6
class MyValue {
var value: Int
init(_ value: Int) { self.value = value }
func f() async {}
}
func globalFunc() -> MyValue {
return MyValue(0)
}
class MyValueUser {
var value: Int = 0
func otherMethod() -> MyValue {
return MyValue(self.value)
}
func doSomething() async {
func innerFunc() -> MyValue { MyValue(self.value) }
let direct: MyValue = MyValue(self.value)
let fromGlobalFunc: MyValue = globalFunc()
let fromOtherMethod: MyValue = self.otherMethod()
let fromClosure: MyValue = ({ MyValue(self.value) })()
let fromInnerFunc: MyValue = innerFunc()
async let _ = direct.f()
// ✅ No Error.
async let _ = fromGlobalFunc.f()
// ✅ No Error.
async let _ = fromOtherMethod.f()
// ❌ error: sending 'fromOtherMethod' risks causing data races
// 📝 note: sending task-isolated 'fromOtherMethod' into async let risks causing data races between nonisolated and task-isolated uses
async let _ = fromClosure.f()
// ❌ error: sending 'fromClosure' risks causing data races
// 📝 note: sending task-isolated 'fromClosure' into async let risks causing data races between nonisolated and task-isolated uses
async let _ = fromInnerFunc.f()
// ❌ error: sending 'fromInnerFunc' risks causing data races
// 📝 note: sending task-isolated 'fromInnerFunc' into async let risks causing data races between nonisolated and task-isolated uses
}
}
await MyValueUser().doSomething()
I'm not familiar with concurrency and I wonder where the difference (whether or not error occurs) comes from.
Because MyValue
is non-Sendable
? (Compiler says No)
- Errors disappear when
MyValueUser
isSendable
even ifMyValue
remains non-Sendable
. - Vice versa: Errors disappear when
MyValue
isSendable
even ifMyValueUser
remains non-Sendable
. - In short, errors occur only when both
MyValue
andMyValueUser
are non-Sendable
.
Because of missing sending
keywords? (Compiler says No)
- The return type of
globalFunc
is also missingsending
keyword, but it doesn't let an error occur. - Adding
sending
keyword tootherMethod
and toinnerFunc
eliminates their errors, but changing the closure to({ () -> sending MyValue in MyValue(self.value) })()
doesn't fix the problem.
I have no idea😞