Global vs isolated parameter difference

It is possible that this something that will just be addressed by Closure isolation control, but just in case I want to check.

I believe that there are no races possible in the version of this code that uses an isolated parameter, but the compiler will not accept it. The global actor isolated version compiles error-free.

I filed a bug about this just in case.

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 {
                // force inheritance to `isolation` here as well
                _ = isolation

                // error: sending 'value' risks causing data races
                print(value)
            }
        })
    }
}
@MainActor
class NonSendable {
    func doThing(value: NonSendableArgument, closure: @escaping () throws -> Void) {
    }

    func doOtherThing(value: NonSendableArgument) {
        doThing(value: value, closure: {
            Task {
                print(value)
            }
        })
    }
}

What do you think?

2 Likes

It seems like compiler simply cannot reason enough with isolated parameters, code seems to be safe.

1 Like

I only recently learned about the _ = isolation inference, but ran into the same issue. It would be nice and in my opinion important to be able to explicitly annotate closures with an actor value. Unfortunately, the mentioned pitch is not even in review yet.

The code itself looks good.

1 Like