It is my understanding that when conforming to Sendable it is safe to use @unchecked if the type is safe to use across tasks using a method the compiler cannot check, e.g. locks. That would mean the following code is valid, does not produce errors or warnings, and the conformance to Sendable is valid too:
final class CustomClass: @unchecked Sendable {
var property: Int {
get {
propertyLock.lock()
defer {
propertyLock.unlock()
}
return _property
}
set {
propertyLock.lock()
defer {
propertyLock.unlock()
}
_property = newValue
}
}
private var _property: Int = 0
private var propertyLock = NSLock()
}
However, if another property is added to this class that isn't Sendable there will be no warnings from the compiler because @unchecked Sendable has been applied to the type.
My first instinct was to add @unchecked to _property, but that doesn't work and I can't find anything referencing a similar syntax that would work for this.
One option I see is to use a wrapper type that uses @unchecked Sendable and contains the locking logic. One example is OSAllocatedUnfairLock, although that's restricted to the latest Apple platforms. Using a custom type for this would also be possible.
Is there a recommended way of writing classes like this to prevent these regressions? Maybe there's an obvious solution I've missed!
3 Likes