compiler cannot detect that both with functions have the same isolation. Passing isolation explicitly to the withTaskCancellationHandler doesn't fix the issue. While removing passing isolation to withCheckedContinuation does. I think it is safe to drop an explicit isolation passing here, which makes it work.
On macOS 15 as well, that's odd to me: I would've expected isolation to propagate, given that withTaskCancellationHandler simply calls operation in the end. However, if I put body of withContinuation method inside actor's method directly, it works fine. So probably it is an issue somewhere, because I'd expect either be able to explicitly pass isolation to both functions or have it propagated all the way.
Isn’t this a correct error simply because the isolation parameter is merely a default? If you passed a different actor in for the isolation than what body is isolated to, you’d be in trouble. I’m still a novice at the concurrency stuff though…
EDIT: No, if that were the case then you’d never be able to use a non-Sendable body in an async function at all, independent of the continuation parts.
Yep the synchronous body closure is only safe to execute with the isolation it was formed in and the compiler correctly prevents it from being sent across isolation domains.
It shouldn't be possible for the caller to form a reference to any other isolation than the current. The compiler does prevent the caller passing isolation: nil
private var continuation: CheckedContinuation<T, Never>?
...
await withContinuation(isolation: nil) {
continuation = $0 // ❌'Sending 'self'-isolated value of type '(CheckedContinuation<T, Never>) -> ()' with later accesses to nonisolated context risks causing data races
}
The compiler just seems to lose track of this when withCheckedContinuation is nested within withTaskCancellationHandler. All the testing I have performed via Actor.assertIsolated() suggests that isolation is preserved.