Return a sending value from a disconnected region causing error

struct Protect<T: ~Copyable>: ~Copyable {
    
    let locker: NSLock = NSLock()

    var storedValue: T

    init(_ storedValue: consuming T) {
        self.storedValue = storedValue
    }

    @discardableResult
    mutating func safe<R: ~Copyable>(_ execute: (inout T) throws -> sending R) rethrows -> sending R {
        locker.lock()
        defer {
            locker.unlock()
        }
        let result = try execute(&self.storedValue)
        // Returning task-isolated 'result' risks causing data races since the caller assumes that 'result' can be safely sent to other isolation domains
        return result
    }
}

I don't understand why I got the error as result is disconnected.

2 Likes

It isn't identical, but reminds me a lot of this issue: Unable to return a sending value as sending without an error · Issue #75473 · swiftlang/swift · GitHub

I have had quite a bit of trouble using sending, but I'm hopeful that this bug, plus a few others, will make 6.1 much better.

do you think this is a bug?

Anecdotally, I have also been having a lot of trouble with sending and understanding when I can/can't/should/shouldn't use it. Honestly, just marking everything I can as Sendable and using nonisolated(unsafe)/@unchecked Sendable when necessary has been a lot easier than trying to figure out why I can't make it work right.

i don't want to go this path by using nonisolated(unsafe)/@unchecked Sendable

1 Like

Well I just checked, and this code compiles error-free with the 6.1 snapshot. So it looks like this was indeed a bug/limitation that has been addressed.

The implementation was quite conservative in 6.0, but it is improving a lot with 6.1. Many of my own issues have been resolved in that release as well.

2 Likes

Do you still get an error if you remove the defer statement?