Swift Concurrency (async let) - Cancellation

I am a bit confused about tasks being cancelled.

Overview:

  • checkCancellation function has 2 child tasks: computeA and computeB that run concurrently,
  • computeB throws an error.

Doubt:

  • I expected child task computeA to be cancelled because computeB threw an error, but computeA was never cancelled.
  • Is my understanding wrong or am I missing something?
  • Or is this a bug?

Note:

  • I am using a SwiftUI project (as Swift Playgrounds don't support async let)
  • macOS Big Sur 11.5.2 (20G95)
  • Xcode Version 13.0 beta 5 (13A5212g)

Output:

A - started
B - going to throw
A - going to return, Task.isCancelled = false
error: infinity

Concurrent Function Definitions:

import Foundation
import UIKit

enum ComputationError: Error {
    case infinity
}

fileprivate func computeA() async throws -> Int {
    print("A - started")
    await Task.sleep(2 * 100_000_000)
    print("A - going to return, Task.isCancelled = \(Task.isCancelled)") //I expected Task.isCancelled to be true
    return 25
}

fileprivate func computeB() async throws -> Int {
    print("B - going to throw")
    throw ComputationError.infinity
}

func checkCancellation() async throws {
    async let a = computeA()
    async let b = computeB()
    
    let c = try await a + b
    print("c = \(c)")
}

Invoking Concurrent function

struct ContentView: View {
    var body: some View {
        Button("check cancellation") {
            Task {
                do {
                    try await checkCancellation()
                    print("normal exit")
                } catch {
                    print("error: \(error)")
                }
            }
        }
    }
}

@eskimo could you help with this, I am not sure if my understanding is wrong or if it is a bug

@eskimo could you help with this, I am not sure if my understanding is wrong or if it is a bug

Why do you expect A to be cancelled ? A and B run each in their thread, no one expecting from the other, just c is awaiting and throws error, but A remains untouched.

@Claude31 Thanks, that makes sense, had a skewed understanding, I think I understand better now, thanks!

Swift Concurrency (async let) - Cancellation
 
 
Q