Not sure, if this has already been covered elsewhere. I stumbled over this issue:
struct Foo<Event> {
enum Error: Swift.Error {
case dropped(Event) // Error: "Associated value 'dropped' of 'Sendable'-conforming enum 'Error' has non-sendable type 'Event'"
}
func send(_ event: sending Event) throws {}
}
OK, this is because the protocol Swift.Error conforms to Sendable.
Trying to apply the "obvious" fix:
struct Foo<Event> {
enum Error: Swift.Error {
case dropped(_ event: sending Event) // Error: "'sending' may only be used on parameters and results"
}
func send(_ event: sending Event) throws {}
}
unfortunately, emits the compiler error
'sending' may only be used on parameters and results',
which IMHO looks like some unimplemented feature in the compiler.
A possible solution is to constrain type parameter Event to be Sendable. However, this is a rather strong constraint and I would rather prefer sending which IMHO should be preferred when possible, especially when this is an API of a library.
Is there a better approach today?
Is it possible to fix this in the compiler, so that parameters in associated values can have a sending specifier?
The reason is that while you can pass the value into MyEvent using sending, once it's there the containing value is marked Sendable. That allows it to be shared freely across concurrency domains, which Event doesn't support.
So no, this is not a missing language feature: it's legitimately not possible.
Ok, understood it with your struct example. In case of an enum, the same rules apply: the underlying storage of a sendable enum requires to be sendable. This consequently means, all associated data need to be sendable as well. Makes sense ;)