swiftlang / swift

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

Can RBI give me a better clue here? #74618

Open mattmassicotte opened 2 months ago

mattmassicotte commented 2 months ago

Motivation

Here is a pretty reduced example that shows the problem. This is unsafe, but its really har to figure out why from the diagnostic alone.

class NonSendableData {

}

class NonSendable {
    let data: NonSendableData

    init(data: NonSendableData) {
        self.data = data
    }

    func doWork() async {

    }
}

actor MyActor {
    let data = NonSendableData()

    func useNonSendable() async {
        // the compiler is noticing here that `value` depends on `data`
        // but data is owned by the actor...
        let value = NonSendable(data: data)

        // ... and this makes the non-isolated async call here unsafe
        await value.doWork()
    }
}
error: sending 'value' risks causing data races
24 | 
25 |         // ... and this makes the non-isolated async call here unsafe
26 |         await value.doWork()
   |                     |- error: sending 'value' risks causing data races
   |                     `- note: sending 'self'-isolated 'value' to nonisolated instance method 'doWork()' risks causing data races between nonisolated and 'self'-isolated uses
27 |     }
28 | }

Proposed solution

I'd like something pointing me to this line of code:

let value = NonSendable(data: data)

Alternatives considered

No response

Additional information

No response

gottesmm commented 2 months ago

@mattmassicotte what you are asking for here is what I call isolation history. This would say "why" is value main actor isolated so that one does not have to decipher it. It is partially implemented on main but needs further work to enable it.

mattmassicotte commented 2 months ago

@gottesmm that sounds like a great tool, and I really appreicate you sharing the idea!