# Is \`sending\` allowed in AsyncSequences?

**URL:** <https://forums.swift.org/t/is-sending-allowed-in-asyncsequences/76498>\
**Category:** Using Swift\
**Tags:** concurrency, asyncsequence\
**Created:** [December 10, 2024, 8:28am UTC](https://forums.swift.org/t/is-sending-allowed-in-asyncsequences/76498 "2024-12-10T08:28:03Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![dehesa](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/dehesa/32/10911_2.png) [@dehesa](https://forums.swift.org/u/dehesa)\
**Post date:** [December 10, 2024, 8:28am UTC](https://forums.swift.org/t/is-sending-allowed-in-asyncsequences/76498/1 "2024-12-10T08:28:03Z")

</div>

Is it possible to use `sending` on the return type of an `AsyncSequence`'s `next(isolation:)` function?

I am trying to create an async sequence "forwarding" non-sendable values. These non-sendable values are created by the asyncsequence and can therefore be sent. For example:

```swift
actor CustomSequence: AsyncSequence, AsyncIteratorProtocol {
  init() {}

  nonisolated func makeAsyncIterator() -> CustomSequence {
    self
  }

  func next(isolation actor: isolated (any Actor)?) async throws(Never) -> sending Reference? {
    await computeNext()
  }

  nonisolated(unsafe) func next() async throws -> sending Reference? {
    await next(isolation: nil)
  }
}

private extension CustomSequence {
  func computeNext() async -> sending Reference? {
    Reference()
  }
}

final class Reference {}

```

The following throws an error within the `next(isolation:)` function saying: `Sending 'self.computeNext' risks causing data races`. Interestingly if I slightly modify `next(isolation:)` to:

```swift
func next(isolation actor: isolated (any Actor)?) async throws(Never) -> sending Reference? {
  let result = await computeNext()
  return result
}

```

Then I get a compiler error: `Pattern that the region based isolation checker does not understand how to check. Please file a bug`.

---

<div class="post-metadata">

**Author:** ![ole](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ole/32/18720_2.png) [@ole](https://forums.swift.org/u/ole)\
**Post date:** [December 10, 2024, 12:18pm UTC](https://forums.swift.org/t/is-sending-allowed-in-asyncsequences/76498/2 "2024-12-10T12:18:54Z")

</div>

> [@dehesa](#):
>
> The following throws an error within the `next(isolation:)` function saying: `Sending 'self.computeNext' risks causing data races`.

The compiler also emits a note with this error:

```swift
Error: Sending 'self.computeNext' risks causing data races
  Note: 'self'-isolated 'self.computeNext' cannot be a 'sending' result.
  'self'-isolated uses may race with caller uses

```

I'm not sure what this means to be honest, but FWIW your code compiles if you make your `computeNext` function `nonisolated`.

---

<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 10, 2024, 1:34pm UTC](https://forums.swift.org/t/is-sending-allowed-in-asyncsequences/76498/3 "2024-12-10T13:34:26Z")

</div>

> [@dehesa](#):
>
> Is it possible to use `sending` on the return type of an `AsyncSequence`'s `next(isolation:)` function?

i've outlined my current best theory as to what's going on in such cases [here](https://forums.swift.org/t/region-based-isolation-sending-return-value-actor-isolation-what-is-the-expected-behavior/75455). though i've not had 'official' confirmation from the domain experts, i am fairly confident that, as of now, the issue here doesn't have to do with `AsyncSequence`, but rather that any actor-isolated function of this form:

```swift
func returnSending() -> sending NonSendable { ... }

```

will effectively _not_ return a `sending` value. instead the value is seemingly merged into the actor's region, so cannot be passed through as a `sending` parameter elsewhere.

as @ole accurately points out – a potential workaround is to ensure that the function producing the `sending` value is not actor-isolated.

---

<div class="post-metadata">

**Author:** ![dehesa](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/dehesa/32/10911_2.png) [@dehesa](https://forums.swift.org/u/dehesa)\
**Post date:** [December 10, 2024, 2:53pm UTC](https://forums.swift.org/t/is-sending-allowed-in-asyncsequences/76498/4 "2024-12-10T14:53:58Z")

</div>

Thank you @ole and @jamieQ. This is useful!

The whole idea with having an actor as a sequence is to have some kind of protected state at generation time. Therefore having a non-isolated `computeNext()` is not a good solution. In any case, it is good to know what are the current problems with `actor` and `sending` and therefore pivot to use other kind of concurrent state protection such as `Mutex`es.

---

<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 10, 2024, 3:50pm UTC](https://forums.swift.org/t/is-sending-allowed-in-asyncsequences/76498/5 "2024-12-10T15:50:13Z")

</div>

depending on your needs, you may be able to adapt your code to build within the current constraints. does the construction of the non-`Sendable` elements of the sequence depend on other actor-isolated non-`Sendable` state? is so, then yes you may need another mechanism. but if not, perhaps you can achieve this via something like the following:

```swift
// make this either a global or static function
nonisolated func computeNext(for sequence: CustomSequence) async -> sending Reference? {
  let sendableState = await sequence.getSendableState() // pull out state that may be mutable but can be sent across isolation boundaries
  return Reference(sendableState) // construct the next non-Sendable element from it
}

```

that is, if you can separate some `Sendable` actor-protected state from the non-`Sendable` bits, then you might be able to use what you have with minor modifications.
