swiftlang / swift

The Swift Programming Language
https://swift.org
Apache License 2.0
67.32k stars 10.34k forks source link

I'm not sure what conditions could lead to this ever actually being a race #76038

Open mattmassicotte opened 4 weeks ago

mattmassicotte commented 4 weeks ago

Description

I'm trying to come up with a situation that would result in this actually being a race and I'm having a lot of trouble. I get that the closure has an isolated paramter, but because it is non-Sendable, I don't think the isolation domain could ever actually change.

Reproduction

class Argument {
}

class NonSendable {
    public func noArgument(closure: (isolated (any Actor)?) async -> Void) {
    }

    public func isolatedNoArgument(isolation: isolated (any Actor)? = #isolation, value: Argument) {
        // here, self *must* be on isolation
        noArgument() { innerIsolation in
            // closure is non-Sendable
            // so innerIsolation must be isolation

            // ERROR: sending 'value' risks causing data races
            print(value)
        }
    }
}

Expected behavior

I think this should compile diagnostic-free.

Environment

Apple Swift version 6.0-dev (LLVM 311c8b35213308e, Swift 488a207cc9d2994) Target: arm64-apple-macosx14.0

Additional information

No response

mattmassicotte commented 3 weeks ago

Here's a different take which I think represents the same thing:

class NonSendableArgument {
}

class NonSendable {
    func doThing(
        value: NonSendableArgument,
        closure: @escaping () throws -> Void
    ) {
    }

    func doOtherThing(
        isolation: isolated any Actor,
        value: NonSendableArgument
    ) {
        // isolated to `isolation` here
        doThing(value: value, closure: {
            Task {
                // isolated to `isolation` here as well
                _ = isolation

                // error: sending 'value' risks causing data races
                print(value)
            }
        })
    }
}

Because closure is non-Sendable, I do not believe an implementation of NonSendable.doThing(value:closure:) exists that has a data race (without using unsafe constructs).