AsyncStream.Iterator.next
and TaskGroup.Iterator.next
don't rethrow
.
Instead, to get
async throws -> Element?
instead of
async -> Element?
, you need the throwing variants. (AsyncThrowingStream and ThrowingTaskGroup).
But the rest of the AsyncIteratorProtocol
adopters in the standard library, while also having throwing and non-throwing variants, use this pair of signatures instead:
async rethrows -> Element?
async throws -> Element?
1. When does that rethrows
get used?
2. Why the inconsistency?
I was looking at the "AnyAsyncSequence
" thread, and thinking that, at this point, we're always working with "some AsyncNonThrowingSequence<Element>
" or "some AsyncThrowingSequence<Element>
":
public protocol AsyncNonThrowingSequence<Element>: AsyncSequence
where AsyncIterator: Swift.AsyncIterator { }
public protocol AsyncIterator<Element>: AsyncIteratorProtocol {
associatedtype Element
mutating func next() async -> Element?
}
public protocol AsyncThrowingSequence<Element>: AsyncSequence
where AsyncIterator: AsyncThrowingIterator { }
public protocol AsyncThrowingIterator<Element>: AsyncIteratorProtocol {
associatedtype Element
mutating func next() async throws -> Element?
}
…but while that idea works with Stream
s…
extension AsyncStream: AsyncNonThrowingSequence { }
extension AsyncStream.Iterator: AsyncIterator { }
extension AsyncThrowingStream: AsyncThrowingSequence { }
extension AsyncThrowingStream.Iterator: AsyncThrowingIterator { }
…it doesn't work with anything else, because rethrows
doesn't propagate into the type system.