Skip to content

Conversion from inout sending to inout allows protected value to be transferred out #80489

Open
@NSFatalError

Description

@NSFatalError

Description

From the Mutex proposal, the following code is unsafe and doesn't compile:

var ref = NonSendable()
let mutex = Mutex(NonSendable())

mutex.witwLock { value in
    ref = value // error!
}

However, those safety guarantees can be bypassed by passing inout sending parameter to another function accepting an inout parameter without any special "unsafe" annotations.

Reproduction

extension Mutex {
    borrowing func withUnsafeLock<Result: ~Copyable, E: Error>(
        _ body: (inout /* instead of inout sending */ Value) throws(E) -> sending Result
    ) throws(E) -> sending Result {
        try withLock { (value: inout sending Value) throws(E) -> sending Result in
            try body(&value)
        }
    }
} 

class NonSendable {}
var ref = NonSendable()
let mutex = Mutex(NonSendable())

mutex.withUnsafeLock { value in
    ref = value // value transferred out to ref without being reinitialized
}

Expected behavior

Conversion from inout sending to inout should be a compiler error.

Environment

swift-driver version: 1.120.5 Apple Swift version 6.1 (swiftlang-6.1.0.110.21 clang-1700.0.13.3)
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.concurrencyFeature: umbrella label for concurrency language features

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions