Swift 6, consume optional nonCopyable property and transfer(sending) it out

struct NonSendableValue: ~Copyable {}

// Making it nonSendable
@available(*, unavailable)
extension NonSendableValue: Sendable { }

final class SomeClass {
    var val: NonSendableValue? = NonSendableValue()

    func foo() -> sending NonSendableValue {
        let x = consume val
        return x
    }
}

How can I make val to nil and consume its value and return it?

Isn't it just a case of saying val = nil, before returning from foo?

Class properties can't be directly consumed from since objects can have multiple dynamic references, so the variable always has to be valid when it isn't under an active exclusive access for mutation. You can use the new take() method on Optional now, though, which will consume the value and leave nil behind in one operation:

final class SomeClass {
    var val: NonSendableValue? = NonSendableValue()

    func foo() -> sending NonSendableValue {
        return val.take()!
    }
}
1 Like

if i write like you, I got an error of Task or actor isolated value cannot be sent:

    func foo() -> sending NonSendableValue {
        return val._take()! 
    }

if I write as below, I got an error of Sending 'x' risks causing data races Task-isolated 'x' cannot be a 'sending' result. task-isolated uses may race with caller uses

    func foo() -> sending NonSendableValue {
        let x = val._take()!
        return x
    }

It seems like I can't transfer(sending) it back and discount the val.

I am running on swift 6 docker, swiftlang/swift:nightly-6.0-focal

You cannot currently declare that a property has to hold a disconnected value — we'd like to be able to express that, but it's not in the language yet. You can use nonisolated(unsafe) as a workaround; I recommend doing this in some very narrow place so that you can enforce that you're actually maintaining the disconnectedness of the value.

how can I use nonisolated(unsafe) in the example above?