-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Calling an isolated function in a non-Sendable closure shouldn't be sending self #77067
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
Comments
Strangely, marking class MyClass {
let handler: @Sendable (@escaping () -> Void) -> Void = { _ in }
func doThing(isolation: isolated (any Actor)?) {
handler {
self.doOtherThing(isolation: isolation)
}
}
func doOtherThing(isolation: isolated (any Actor)?) {
}
} Removing actor isolation parameters also makes it pass: (obvious, but wanted to provide a complete picture) class MyClass {
let handler: (@escaping () -> Void) -> Void = { _ in }
func doThing() {
handler {
self.doOtherThing()
}
}
func doOtherThing() {
}
} Also works when avoiding a closure's implicit capture of class MyClass {
var handler: (@escaping () -> Void) -> Void = { _ in }
func doThing(isolation: isolated (any Actor)?) {
func _doOtherThing() {
doOtherThing(isolation: isolation)
}
handler(_doOtherThing)
}
func doOtherThing(isolation: isolated (any Actor)?) {
}
} |
Here is another workaround someone found for me, which I think pretty much confirms that this is a bug of some kind. class MyClass {
var handler: (@escaping () -> Void) -> Void = { _ in }
func doThing(isolation: isolated (any Actor)?) {
handler {
self.doOtherThing(isolation: #isolation)
}
}
func doOtherThing(isolation: isolated (any Actor)?) {
}
} |
Welp, actually that workaround is actually a way to pass the non-Sendable type across boundaries. class MyClass {
var handler: (@escaping () -> Void) -> Void = { $0() }
func doThing(isolation: isolated (any Actor)?) {
print("in", isolation as Any)
handler {
self.doOtherThing(isolation: #isolation)
}
}
func doOtherThing(isolation: isolated (any Actor)?) {
print("out", isolation as Any)
}
}
let value = MyClass()
value.doThing(isolation: #isolation) output:
|
@gottesmm this is a potentially interesting one. This is both a data race safety hole, on top of being a difficult-to-workaround problem in general. |
Hi, I just read your comments, and I'm confused how you deduced the code is "to pass the non-Sendable type across boundaries"? |
I'm afraid I don't fully understand the question. Are you saying you think this isn't a data race hole? Or that the isolation differences make sense? The type is non-Sendable, so it is should be impossible to access |
(this is also potentially similar to #77301) |
That't right, I think there isn't a hole in this case, the difference of the 2 printed |
hmm maybe, I'd have to think on this more. But my gut says that this is a bug. I don't see how differences between static isolation and runtime behavior should ever be ok... |
This is fixed by 0ece31e |
Confirmed - thank you!! |
Description
I'm not sure how it's possible that
self
could be sent in this situation. The closures involved are not@Sendable
, so the isolation should never change.Reproduction
Expected behavior
I would expect this to compile error-free.
Environment
swift-driver version: 1.115 Apple Swift version 6.0.2 (swiftlang-6.0.2.1.2 clang-1600.0.26.4)
Target: arm64-apple-macosx14.0
Additional information
No response
The text was updated successfully, but these errors were encountered: