Using actor inheritance/typed throws and continuations

Yes, body is always guaranteed to execute before you suspend. Essentially the suspension happens after you return from body (or not at all if continuation.resume() has been called before you return from body).

with*Continuation hasn't been updated for typed throws yet (at least on the latest toolchain I tried) so that's why you can't get that working. Probably best to wait for that to be officially supported but you can in theory do something like this:

func myOwnTypedThrowsWithContinuation<Success, Failure: Error>(
    isolation _: isolated (any Actor)? = #isolation,
    function: String = #function,
    body: (CheckedContinuation<Success, any Error>) -> Void
) async throws(Failure) -> Success {
    do {
        return try await withCheckedThrowingContinuation(function: function) { continuation in
            body(continuation)
        }
    } catch let error as Failure {
        throw error
    } catch {
        fatalError()
    }
}

Note that the checked continuation still uses any Error since that's what we get from the stdlib API so the error type wouldn't be properly enforced by the compiler. To do better you would need to wrap the CheckedContinuation with your own type and forward to the actual continuation internally.

4 Likes