I'm trying to design some guidance for engineers in my codebase to use AsyncSequences. Specifically, it's around how to provide (and to a lesser extent, how to store) AsyncSequences to/from other systems in the application without exposing implementation details or writing excessive amounts of boilerplate.
Until a few weeks ago we were stuck on iOS 17, but now that we've dropped it I was excited to use opaque result types with AsyncSequence, instead of our concrete type eraser AnyAsyncSequence. Being able to tell folks to share as some AsyncSequence<MyType, MyError> and store (if necessary) as any AsyncSequence<MyType, MyError> was a pretty appealing propsect.
Unfortunately, I immediately ran into issues trying to remove the type eraser with the AsyncAlgorithms share() function, which pointed to a broader issue with using this style. share() requires that its base sequence's AsyncIterator associated type conform to SendableMetatype. It doesn't seem to be possible to "spell" this type using opaque result types, I don't know how you'd tack this onto some AsyncSequence<MyType, any Error> . Any kind of a where clause with this syntax is specifically ruled out by the Swift language guide.
Since we don't know what consumers will use a particular sequence for, and losing any information about conformances loses flexibility, it seems like the way forward is to make sure our AnyAsyncSequence has the maximum amount of protocol conformances that operators might need, and then encourage folks to use it with anything that might ultimately be used in this manner. This would probably create a lot of overhead (our current version, due to Swift 6.3 limitations, has an existential AsyncIteratorProtocol inside it) but feels necessary to avoid churn as operators might be applied from inside a library and new consumers might hook the sequence up to increasingly more demanding AsyncSequence operators .
Needing a hand-written type eraser like AnyAsyncSequence to avoid having to write out types like AsyncFilterSequence<AsyncMapSequence<AsyncStream<Int>>> without losing flexibility feels wrong, so I wanted to ask here to make sure there is no better way.