Hey there!
I have a question in regards to actors that are conforming to certain protocols. Lets say I have an actor A
that has a function that is returning a non-Sendable type, like this:
actor A {
func doThingA() -> sending NonSendable {
NonSendable()
}
}
In addition to that, I have a class B
that uses actor A
(in my codebase the class is also sendable, but I think that does not make a difference right now):
class B {
let a = A()
func doSomethingWithA() async {
let nonSendable = await a.doThingA()
}
}
This is all fine and thanks to the sending
keyword the NonSendable
class can be sent across actor boundaries just fine (or at least the compiler does not complain about it).
But now the thing that keeps me puzzling. If I introduce a protocol for the doThingA()
function and conform the actor A
to it, the compiler suddenly tells me that Task or actor isolated value cannot be sent
.
So this does not compile without warnings, and the only change is the protocol conformance:
protocol Proto: Actor {
func doThingA() -> sending NonSendable
}
actor A: Proto {
func doThingA() -> sending NonSendable { /* warning: Task or actor isolated value cannot be sent */
NonSendable()
}
}
Now I am wondered, whats the difference between both of those versions that one can compile without warnings and the other not? Or is this a false positive in region based isolation?
And if the warning is correct, is there a way to make that whole thing safe?
Thanks,
Basti