Async let does not propogate task cancellation to more than one child task at a time?

with this test program,

@main
enum Main
{
    static
    func main() async
    {
        do
        {
            async
            let a:Void = Self.test("A")
            async
            let b:Void = Self.test("B")
            async
            let c:Void = Self.test("C")

            print("cancel")
        }
    }
}

i would expect all three tasks to be cancelled on scope exit, and then implicitly awaited on, as if

    static
    func main() async
    {
        do
        {
            async
            let a:Void = Self.test("A")
            async
            let b:Void = Self.test("B")
            async
            let c:Void = Self.test("C")

            print("cancel")
            
            c.cancel()
            b.cancel()
            a.cancel()

            await c
            await b
            await a
        }
    }

but instead, it looks like async let does

    static
    func main() async
    {
        do
        {
            async
            let a:Void = Self.test("A")
            async
            let b:Void = Self.test("B")
            async
            let c:Void = Self.test("C")

            print("cancel")
            
            c.cancel()
            await c

            b.cancel()
            await b

            a.cancel()
            await a
        }
    }

this the test function i am using:

    static
    func test(_ name:String) async
    {
        do
        {
            print("\(name): started")
            try await Task.sleep(for: .seconds(2))
            print("\(name): not cancelled")
        }
        catch
        {
            print("\(name): cancelled")
        }
        let delay:Task<Void, Never> = .init
        {
            try? await Task.sleep(for: .seconds(2))
        }
        await delay.value
        print("\(name): completed")
    }

and the output i am getting:

cancel
B: started
A: started
C: started
C: cancelled
A: not cancelled
B: not cancelled
C: completed
A: completed
B: completed

is this intended behavior?

3 Likes

Please file a bug, all should get the same effect applied to them, not just one of those child tasks.

5 Likes

filed:

7 Likes