Removing the conditional conditional conformance of Array to ActorSendable is likely to be a bit... confusing. It's semantically sound, and very convenient, so I expect we'll end up getting many overlapping retroactive conformances of "Array of something" to ActorSendable. We can absolutely say "don't do that, wrap it in a struct that does the same thing," but it's an unfortunate bit of advice we would have to give.
Ah, I should have just written it out. Doing it as a property wrapper on a function parameter might just be the best way:
@propertyWrapper
struct NSDeepCopy<Wrapped: NSCopying>: ActorSendable {
let wrappedValue: Wrapped
init(wrappedValue: Wrapped) {
self.wrappedValue = wrappedValue.copy() as! Wrapped
}
}
actor class MyActor {
func method(@NSDeepCopy string: NSAttributedString) async { ... }
}
You'll implicitly get the copy when calling the method. The actual NSDeepCopy<NSAttributeString> that ends up getting passed to the function uses the normal copy witness.
This takes implicit customization for sending values out of the actor system and made it explicitly use an existing feature, simplifying the actor system itself---and explicit marking those places where the API contract involves a deep copy.
Yes, they are different concepts. I am saying that, for both ValueSemantic and ActorSendable, we want to to be a normal "copy witness" copy to transfer a value across actors.
I know what you're going for, but I think the NSDeepCopy approach I've detailed above is simpler overall, and has the benefit of eliminating the need for the unsafeSendToActor requirement at all. ActorSendable reduces to a marker protocol indicating that it's okay to use the type across actor boundaries.
Doug