Why does swift not warn about this nonSendable global passing into different Task?
Asked Answered
A

0

6

Consider the following code:

class Cat {
    var name = "Tom"
}

class Globals {
    var cat = Cat()
}

let glob = Globals()

func one () {
    Task {glob.cat.name="Max"} // Expected Warning about some nonSendable moving into a different concurrency domain
}

Normally, with -warn-concurrency enabled, Swift/Xcode warns about non-sendables crossing concurrency domains.

In my understanding, the closure which is passed to Task must always be a @Sendable closure. A @Sendable closure can only capture Sendables. However, Globals is not a Sendable type. I excpected a warning along the lines of

Capture of 'glob' with non-sendable type 'Globals' in a @Sendable closure

No such warning is emitted.

Amazed answered 23/10, 2022 at 12:25 Comment(2)
Almost certainly a compiler bug. The compiler has many limitations in how it can reason about global variables. The short answer is "don't make global mutable variables." It's come up on the forums, but hasn't gotten any discussion. forums.swift.org/t/sendability-checking-for-global-variables/… I don't see a bug open for it yet, so you may want to do that (bugs.swift.org).Disharmonious
Unrelated (or, at best, very loosely related), but I also find it interesting that if you replace let glob = Globals() with var glob = Globals(), the compiler will warn you that “Reference to var 'glob' is not concurrency-safe because it involves shared mutable state”, but let glob = Globals() seems like it also is not concurrency-safe and has a shared mutable state, too (because it is a reference type). I get that this is a big ask of a compiler, but doesn’t feel right.Ifni

© 2022 - 2025 — McMap. All rights reserved.