Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't enqueue main-actor-isolated async func directly with addTask #76488

Open
jumhyn-browser opened this issue Sep 16, 2024 · 1 comment
Open
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. triage needed This issue needs more specific labels

Comments

@jumhyn-browser
Copy link

Description

In the below example, the call to addTask which calls h give a concurrency warning that seems incorrect. The given error is:

error: sending value of non-Sendable type '() async -> ()' risks causing data races
note: Passing main actor-isolated value of non-Sendable type '() async -> ()' as a 'sending' parameter risks causing races inbetween main actor-isolated uses and uses reachable from the call

Am I missing something about why this is not allowable in the general case?

Reproduced on godbolt nightly but have seen the same/similar issue adopting Swift 6.0

Reproduction

@MainActor
func f() async {
    await withTaskGroup(of: Void.self) { group in
        for x in 0..<10 {
            group.addTask { @MainActor in
                g(x)
            }

            group.addTask { @MainActor in // error
                await h(x)
            }
        }
    }
}

@MainActor
func g(_: Int) {}

@MainActor
func h(_: Int) async {}

Expected behavior

Both calls to addTask compile without warning.

Environment

Swift version 6.1-dev (LLVM b5c60054ab3ee7b, Swift 09b543187803093)
Target: x86_64-unknown-linux-gnu
Compiler returned: 0

Additional information

No response

@jumhyn-browser jumhyn-browser added bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. triage needed This issue needs more specific labels labels Sep 16, 2024
@jamieQ
Copy link
Contributor

jamieQ commented Sep 17, 2024

here's a reduction for future triaging/investigations:

func f() async {
    await withTaskGroup(of: Void.self) { group in
        group.addTask { @MainActor in
            await Task.yield()
        }
    }
}
/*
<source>:3:15: error: sending value of non-Sendable type '() async -> ()' risks causing data races
 1 | func f() async {
 2 |     await withTaskGroup(of: Void.self) { group in
 3 |         group.addTask { @MainActor in
   |               |- error: sending value of non-Sendable type '() async -> ()' risks causing data races
   |               `- note: Passing main actor-isolated value of non-Sendable type '() async -> ()' as a 'sending' parameter risks causing races inbetween main actor-isolated uses and uses reachable from the callee
 4 |             await Task.yield()
 5 |         }
*/

it also appears it's not unique to the main actor – any global actor exhibits the issue. the following approaches all seem to avoid the diagnostic:

func f() async {
    await withTaskGroup(of: Void.self) { group in
        // 1
        let op: @MainActor () async -> Void = { await Task.yield() }
        group.addTask(operation: op)

        // 2
        group.addTask(operation: { await Task.yield() } as @MainActor () async -> Void)

        // 3
        group.addTask { @Sendable @MainActor in
            await Task.yield()
        }
    }
}

edit: this is perhaps the same underlying issue as #76242

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. triage needed This issue needs more specific labels
Projects
None yet
Development

No branches or pull requests

2 participants