mirror of
https://github.com/apple/swift.git
synced 2026-03-04 18:24:35 +01:00
The pass works by walking functions in the modules looking for mutable alloc_box that contains a weak variable and is knowably a capture. In such a case, the pass checks all uses of the alloc_box interprocedurally including through closures and if provably immutable marks the box and all closure parameters as being inferred immutable. This change also then subsequently changes SILIsolationInfo to make it so that such boxes are considered Sendable in a conservative manner that pattern matches the weak reference code emission pretty closely. The reason why I am doing this is that issue #82427 correctly tightened region isolation checking to catch unsafe concurrent access to mutable shared state. However, this introduced a regression for a common Swift pattern: capturing `self` weakly in escaping closures. The problem occurs because: 1. Weak captures are stored in heap-allocated boxes. 2. By default, these boxes are **mutable** (`var`) even if never written to after initialization 3. Mutable boxes are non-Sendable (they could be unsafely mutated from multiple threads) 4. Region isolation now correctly errors when sending non-Sendable values across isolation boundaries This breaks code like: ```swift @MainActor class C { func test() { timer { [weak self] in // Captures self in a mutable box Task { @MainActor in self?.update() // ERROR: sending mutable box risks data races } } } } ``` Note how even though `self` is Sendable since it is MainActor-isolated, the *box containing* the weak reference is not Sendable because it is mutable. With the change in this commit, we now recognize that the box can safely be treated as Sendable since we would never write to it. rdar://166081666
10 KiB
10 KiB