As far as I can tell, Mutex
suffers the same data races:
import Synchronization
class NS { var a = 0 }
let mutex = Mutex<NS>(NS())
Task.detached {
let a = mutex.withLock {
$0
}
a.a += 1
}
Task.detached {
let a = mutex.withLock {
$0
}
a.a += 1
}
It is not clear to me, whether it is truly valid to use { $0 }
for a (inout sending T) -> sending R
closure. The source of being unsafe is that although $0
was in a disconnected region inside the closure, after it got returned, the value could be merged into any task-isolated regions later, so multiple invocations could definitely race.
The above code has racing accesses on a
, the code compiles fine with Swift 6.1 & 6.2-dev, but was rejected (correctly?) by Swift 6.0.
I believe both Mutex
and your Disconnected
are inherently safe, the problem is the compiler fails to detect some erroneous usages in the client code.
PS: found related discussions: