Skip to content

False negative in isolation checking #80014

Open
@nickolas-pohilets

Description

@nickolas-pohilets

Description

Since Swift does not allow weak let bindings, it seems that weak closure captures are always mutable and are stored in a heap-allocated box. Re-capturing mutable weak shares heap-allocated box between closures, but if original closure is @Sendable this sharing is ignored by the isolation checker.

Issue reproduces only when outer closure is @Sendable. When @Sendable is removed, data race error is reported as expected:

Task {
      `- error: passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure
   x?.bar()
   `- note: closure captures 'x' which is accessible to code in the current task
}

Some users have reported that attached code crashes, though non-deterministically.
See discussion in https://forums.swift.org/t/weak-captures-in-sendable-sending-closures/78498

Reproduction

final class X: Sendable {
    func bar() {}
}

func doIt(_ block: @Sendable () -> Void) { // Removing @Sendable makes race visible
    block()
}

func foo() {
    let x = X()
    doIt { [weak x] in
        Task {
            x?.bar()
        }
        x = nil
    }
}

Expected behavior

Data race error produced regardless of the sensibility of the outer closure.

Environment

$ xcrun swiftc -version
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-macosx15.0

Additional information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugA deviation from expected or documented behavior. Also: expected but undesirable behavior.triage neededThis issue needs more specific labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions