I would like to write something like the following:
final class NonSendable {}
@MainActor
final class Foo {
var stream: (source: NonSendable, consumer: Task<Void, any Error>)?
deinit {
stream?.consumer.cancel()
}
}
Unfortunately, it fails to compile with -swift-version 6
:
<source>:8:11: error: cannot access property 'stream' with a non-sendable type '(source: NonSendable, consumer: Task<Void, any Error>)?' from nonisolated deinit
1 | final class NonSendable {}
| `- note: class 'NonSendable' does not conform to the 'Sendable' protocol
2 |
3 | @MainActor
:
6 |
7 | deinit {
8 | stream?.consumer.cancel()
| `- error: cannot access property 'stream' with a non-sendable type '(source: NonSendable, consumer: Task<Void, any Error>)?' from nonisolated deinit
9 | }
10 | }
Now, I understand that deinit
may be invoked from any concurrency domain, so I cannot be allowed to call any methods on stream?.source
(other than deinit
, but we can't call that explicitly).
But I don't think the access to the stream
property itself should be considered unsafe - after all, within a deinit
accesses to the property cannot possibly race because there are no other living references to this object. And there is part of the tuple which I can use from any concurrency context.
Is this perhaps an edge-case that hasn't been accounted for/is difficult to implement, and could it potentially be allowed in future?