# Please help me understand this compiler error when using async sequence with existential type / boxed type (Swift 6)

**URL:** <https://forums.swift.org/t/please-help-me-understand-this-compiler-error-when-using-async-sequence-with-existential-type-boxed-type-swift-6/83847>\
**Category:** Using Swift\
**Tags:** concurrency\
**Created:** [December 26, 2025, 12:14pm UTC](https://forums.swift.org/t/please-help-me-understand-this-compiler-error-when-using-async-sequence-with-existential-type-boxed-type-swift-6/83847 "2025-12-26T12:14:39Z")\
**Posts on this page:** 1\
**Showing post:** 2

<div class="post-metadata">

**Author:** ![jamieQ](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jamieq/32/5117_2.png) [@jamieQ](https://forums.swift.org/u/jamieQ)\
**Post date:** [December 26, 2025, 11:07pm UTC](https://forums.swift.org/t/please-help-me-understand-this-compiler-error-when-using-async-sequence-with-existential-type-boxed-type-swift-6/83847/2 "2025-12-26T23:07:19Z")

</div>

let's consider a stripped-down example that exhibits similar behavior, without involving any closed-source code:

```swift
open class NS {} // non-Sendable type

@MainActor
func doit(
    _ seq: any AsyncSequence<NS, Never>
) async throws {
    var it: any AsyncIteratorProtocol<NS, Never> = seq.makeAsyncIterator()
    _ = try await it.next() // 🛑 error: sending 'it' risks causing data races
}

```

`AsyncIteratorProtocol` is a bit unusual because it effectively has two versions of the same requirement for the `next()` method, one of which was introduced in some sense to solve this exact problem. you can read the details in [SE-421](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0421-generalize-async-sequence.md) if interested, but this quote from the [motivation section](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0421-generalize-async-sequence.md#motivation) is essentially the issue you've run into:

> Additionally, `AsyncSequence` types are designed to work with `Sendable` and non-`Sendable` element types, but it's currently impossible to use an `AsyncSequence` with non-`Sendable` elements in an actor-isolated context:
> 
> ```swift
> class NotSendable { ... }
> 
> @MainActor
> func iterate(over stream: AsyncStream<NotSendable>) {
> for await element in stream { // warning: non-sendable type 'NotSendable?' returned by implicitly asynchronous call to nonisolated function cannot cross actor boundary
> 
> }
> }
> 
> ```
> 
> Because `AsyncIteratorProtocol.next()` is `nonisolated async`, it always runs on the generic executor, so calling it from an actor-isolated context crosses an isolation boundary. If the result is non-`Sendable`, the call is invalid under strict concurrency checking.

in the case that the iterator's concrete type is hidden behind an existential, it's not entirely clear to me why, but it seems the compiler emits calls to the original `next()` requirement (not the isolation-inheriting overload). i _think_ this may be because some types may only implement that requirement, and in the existential case the compiler may have to conservatively assume that's the only one available? not totally sure if this behavior is entirely necessary though (see below regarding `for-await`)... it's possible this is an implementation bug/limitation – maybe someone more knowledgeable can weigh in.

if the callsite is changed to explicitly use the isolated overload, then the issue is resolved:

```swift
@MainActor
func doit2(
    _ seq: any AsyncSequence<NS, Never>
) async throws {
    var it: any AsyncIteratorProtocol<NS, Never> = seq.makeAsyncIterator()
    _ = await it.next(isolation: #isolation) // ✅
    // also note that this can be performed without a `try` because the
    // isolated requirement also uses typed-throws so knows an error can
    // never be produced
}

```

i think this also explains why the `for-await` loop doesn't exhibit the same problem – since the compiler gets to synthesize that code, it can choose to generate calls to the isolation-inheriting version of `next()`, rather than the legacy API:

```swift
@MainActor
func doit3(
    _ seq: any AsyncSequence<NS, Never>
) async throws {
    for await _ in seq { // ✅ – generated calls occur to the iterator's next(isolation:) method
        break
    }
}

```

as for why the first example only produces a warning... i'm not certain, but i suspect it may have something to do with the fact that some of the `Notifications` API is marked `@preconcurrency` (but i haven't investigated much, so this is mostly a guess).

> [@ivan](#):
>
> Additionally, the compile error doesn’t happen when my AsyncSequence is concrete type, even though I cast my async iterator using `as! AsyncIteratorProtocol<Notification, Never>`

i was unable to replicate this behavior locally – what environment were you using that exhibited it?

---

_[View the full topic](https://forums.swift.org/t/please-help-me-understand-this-compiler-error-when-using-async-sequence-with-existential-type-boxed-type-swift-6/83847)._
