# \[Pitch\] Typed throws in the Concurrency module

**URL:** <https://forums.swift.org/t/pitch-typed-throws-in-the-concurrency-module/68210>\
**Category:** Pitches\
**Tags:** concurrency, typed-throws\
**Created:** [November 2, 2023, 1:53pm UTC](https://forums.swift.org/t/pitch-typed-throws-in-the-concurrency-module/68210 "2023-11-02T13:53:55Z")\
**Posts on this page:** 20\
**Page:** 2

<div class="post-metadata">

**Author:** ![ktoso](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ktoso/32/44526_2.png) [@ktoso](https://forums.swift.org/u/ktoso)\
**Post date:** [November 9, 2023, 7:08am UTC](https://forums.swift.org/t/pitch-typed-throws-in-the-concurrency-module/68210/22 "2023-11-09T07:08:22Z")

</div>

Sadly it is a pretty annoying special case so we'd like to keep those to a minimum, but doing so for a core type like AsyncSequence would justify the pain if we have to... Especially if we could at the same time fix some isolation issues that currently prevent AsyncSequence to be used properly inside actors (due to the iterator not being Sendable, however perhaps this may be solved by send-not-sendable semantics).

The difficult thing here is about getting the level of deprecations "just right", and we struggled with this for quite a while with Executor -- we'd want to issue warnings, but not too much warnings to cause people with otherwise good implementations to get warnings they cannot resolve etc.

We're getting to the third instance of such thing now with "next2" so it might be time to generalize but I don't think this would be a public feature, but an internal attribute really -- at least for now.

---

<div class="post-metadata">

**Author:** ![KeithBauerANZ](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/keithbaueranz/32/27897_2.png) [@KeithBauerANZ](https://forums.swift.org/u/KeithBauerANZ)\
**Post date:** [December 21, 2023, 3:37am UTC](https://forums.swift.org/t/pitch-typed-throws-in-the-concurrency-module/68210/23 "2023-12-21T03:37:30Z")

</div>

The async sequence combinators currently always throw the `Failure` type of the receiving sequence. I think there should be a second variant which allows introducing a failure type where there was not already one (this mirrors similar cases in Combine, for example):

```swift
// proposed above
  public func map<Transformed>(
    _ transform: @Sendable @escaping (Element) async throws(Failure) -> Transformed
  ) -> some AsyncSequence<ElementOfResult, Failure>

// we should also add
  public func map<Transformed, NewFailure>(
    _ transform: @Sendable @escaping (Element) async throws(NewFailure) -> Transformed
  ) -> some AsyncSequence<ElementOfResult, NewFailure> where Failure == Never

```

(unfortunately this explodes things with the current idea to offer multiple overloads to allow mixing `Sendable` and opaque result types, leaving 4 overloads for most of these functions. Perhaps it would be better to return to explicitly named result types to allow collapsing the `Sendable` variants?)

---

<div class="post-metadata">

**Author:** ![pyrtsa](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/pyrtsa/32/740_2.png) [@pyrtsa](https://forums.swift.org/u/pyrtsa)\
**Post date:** [December 21, 2023, 4:55am UTC](https://forums.swift.org/t/pitch-typed-throws-in-the-concurrency-module/68210/24 "2023-12-21T04:55:18Z")

</div>

> [@KeithBauerANZ](#):
>
> I think there should be a second variant which allows introducing a failure type

I think it'd be best to achieve this not by introducing overloads but the equivalent of [`setFailureType(to:)`](https://developer.apple.com/documentation/combine/fail/setfailuretype(to:)) for `Never`-throwing async sequences. (Or a `mapFailure` for transforming error types from one, e.g. `Never`, to another.)

---

<div class="post-metadata">

**Author:** ![KeithBauerANZ](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/keithbaueranz/32/27897_2.png) [@KeithBauerANZ](https://forums.swift.org/u/KeithBauerANZ)\
**Post date:** [December 21, 2023, 9:26pm UTC](https://forums.swift.org/t/pitch-typed-throws-in-the-concurrency-module/68210/25 "2023-12-21T21:26:07Z")

</div>

I think both those are important things to add too, but I think it'd be quite unexpected that eg.

```swift
AsyncStream(sequence: [1, 3]) // a trivial enough extension to define...
    .map { i in
        if i % 2 == 0 {
            throw IHateEvenNumbers()
        }
        return i
    }

```

should be rejected by the compiler. And I don't think that many people would think to look to

```swift
AsyncStream(sequence: [1, 3])
    .setFailureType(to: IHateEvenNumbers.self)
    .map { i in
        if i % 2 == 0 {
            throw IHateEvenNumbers()
        }
        return i
    }

```

as the solution, when they do hit that rejection!

---

<div class="post-metadata">

**Author:** ![1-877-547-7272](https://avatars.discourse-cdn.com/v4/letter/1/278dde/32.png) [@1-877-547-7272](https://forums.swift.org/u/1-877-547-7272)\
**Post date:** [December 22, 2023, 6:28am UTC](https://forums.swift.org/t/pitch-typed-throws-in-the-concurrency-module/68210/26 "2023-12-22T06:28:16Z")

</div>

> Furthermore, a problem that has been brought up is the `@discardableResult` annotation on the initializers. This annotation silences any warning if the resulting `Task` is not stored; however, the only cases where this really makes sense are `Task<Void, Never>` or `Task<Never, Never>` . We propose to add the following new initializers

While it would be nice to have `@discardableResult` for both `Task<Void, Never>` and `Task<Never, Never>`, it should be noted that overloading a function/initializer with a function type returning `Void` or `Never` can cause errors due to ambiguity.

```swift
func f(_: () -> Void) {}
func f(_: () -> Never) {}
f { while true {} }
// error: ambiguous use of 'f'

```

In order to avoid breaking currently-working code, the `Task<Never, Never>` initializer will have to be marked as `@_disfavoredOverload`. In addition, to prevent the type checker choosing them over the `Task<Never, Never>` initializer, all of the non–discardable result initializers will also have to be marked `@_disfavoredOverload` as well. Same goes for the `detached` methods.

Or, alternatively, the type checker could be changed and given a new rule to choose a favored overload in cases like this. It should be noted that for cases without overloads like this:

```swift
let x = { while true {} }

```

the type checker already defaults to giving `x` the type `() -> Void`.

---

<div class="post-metadata">

**Author:** ![pyrtsa](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/pyrtsa/32/740_2.png) [@pyrtsa](https://forums.swift.org/u/pyrtsa)\
**Post date:** [December 22, 2023, 7:40am UTC](https://forums.swift.org/t/pitch-typed-throws-in-the-concurrency-module/68210/27 "2023-12-22T07:40:48Z")

</div>

> [@KeithBauerANZ](#):
>
> I think it'd be quite unexpected that eg.
> 
> ```swift
> AsyncStream(sequence: [1, 3]) // a trivial enough extension to define...
> .map { i in
> if i % 2 == 0 {
> throw IHateEvenNumbers()
> }
> return i
> }
> 
> ```
> 
> should be rejected by the compiler.

Oh yes, that's problematic indeed. That made me wonder if instead of limiting the API to the `Failure` type of `self`, it would be possible to do a type conversion on failure types as well; so instead of the proposed new `map(_:)` API

```swift
extension AsyncSequence {
  public func map<Transformed>(
    _ transform: @Sendable @escaping (Element) async throws(Failure) -> Transformed
  ) -> some AsyncSequence<ElementOfResult, Failure>
}

```

we could get back

```swift
  ) -> some AsyncSequence<Transformed, errorUnion(Failure, NewFailure)>

```

I'm not sure if the `errorUnion(e1, e2, ..., EN)` type function [introduced by SE-0413](https://github.com/apple/swift-evolution/blob/main/proposals/0413-typed-throws.md#catching-typed-thrown-errors) was actually meant to be usable in type expressions, but here it would be useful IMO\[1\].

* * *

> [@](#):
>
> And I don't think that many people would think to look to
> 
> ```swift
> AsyncStream(sequence: [1, 3])
> .setFailureType(to: IHateEvenNumbers.self)
> .map { i in ... }
> 
> ```
> 
> as the solution, when they do hit that rejection!

Can't disagree on that either!

* * *

1. As I understood it, the semantics of `errorUnion` were meant to be:   
(1) `errorUnion(E, E) = E`  
(2) `errorUnion(E, Never) = E`  
(3) `errorUnion(E1, E2) = any Error` where `E1 != E2`

---

<div class="post-metadata">

**Author:** ![Douglas\_Gregor](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/douglas_gregor/32/1362_2.png) [@Douglas\_Gregor](https://forums.swift.org/u/Douglas_Gregor)\
**Post date:** [January 2, 2024, 10:02pm UTC](https://forums.swift.org/t/pitch-typed-throws-in-the-concurrency-module/68210/28 "2024-01-02T22:02:32Z")

</div>

Hey all,

I took a stab at implementing the `AsyncSequence` part of this protocol, to assess whether it's possible to introduce typed throws in a manner that is both backward compatible and achieves the composability we want, with support for `any AsyncSequence<Element, Failure>` and such. The implementation in the compiler and library is in [this pull request](https://github.com/apple/swift/pull/70635), along with toolchains to play with, but the salient details are below.

**tl;dr** we can stage in the new `Failure` associated type without breaking existing code, and the unfinished/unofficial `@rethrows` can be removed over time.

With my implementation, `AsyncSequence` and `AsyncIteratorProtocol` both get `Failure` associated types and adopt primary associated types, as in the proposal. `AsyncIteratorProtocol` gets a new function requirement `_nextElement()` that is a typed-throws version of `next()`:

```swift
protocol AsyncIteratorProtocol<Element, Failure> {
  associatedtype Element
  associatedtype Failure: Error = any Error
  mutating func next() async throws -> Element?
  mutating func _nextElement() async throws(Failure) -> Element?
}

public protocol AsyncSequence<Element, Failure> {
  associatedtype AsyncIterator: AsyncIteratorProtocol
  associatedtype Element where AsyncIterator.Element == Element
  associatedtype Failure = AsyncIterator.Failure where AsyncIterator.Failure == Failure
  func makeAsyncIterator() -> AsyncIterator
}

```

Because existing `AsyncIteratorProtocol`-conforming types only implement `next()`, we need to provide a default implementation of `_nextElement`:

```swift
extension AsyncIteratorProtocol {
  /// Default implementation of `_nextElement()` in terms of `next()`, which is
  /// required to maintain backward compatibility with existing async iterators.
  public mutating func _nextElement() async throws(Failure) -> Element? {
    do {
      return try await next()
    } catch {
      throw error as! Failure
    }
  }
}

```

I didn't also implement `next()` in terms of `_nextElement()`, but we'd want to do that so that new async sequences could implement just `_nextElement()`.

Now, one of the harder problems is how to get the right `Failure` type for existing async sequences. If the async sequence doesn't get recompiled, it'll get the default `Failure` type of `any Error` at runtime. This is fine---either it doesn't throw anything in practice, or its clients will see the `any Error` instance.

When the async sequence does get recompiled, we want to pick an appropriate `Failure` type even when there is no explicitly-specified one. I ended up using the following inference logic based on the `next()` implementation:

- If `next()` throws nothing, `Failure` is inferred to `Never`.
- If `next()` throws, `Failure` is inferred to `any Error`.
- If `next()` rethrows, `Failure` is inferred to `T.Failure`, where `T` is the first type parameter with a conformance to either `AsyncSequence` or `AsyncIteratorProtocol`. If there are multiple such requirements, take the `errorUnion` of them all.

The async `for..in` loop switches from using `next()` to using `_nextElement()`, so iteration over an async sequence throws its `Failure` type. This subsumes the specialized behavior for `@rethrows` (if `Failure` is `Never`, you don't need the `try` because nothing is thrown), and gives us typed-throws behavior for iteration.

`@rethrows` protocols had another bit of special behavior, which is that conformance requirements to `@rethrows` protocols can be considered as sources of errors for rethrowing. So, you can currently write a `rethrows` function like this:

```swift
extension AsyncSequence {
  func contains(_ predicate: (Element) async throws -> Bool) rethrows -> Bool { ... }
}

```

and this function can throw if either the `AsyncSequence` throws (i.e., it's `Failure` type is not `Never`) or if the `predicate` throws. @pyrtsa [noted this issue](https://forums.swift.org/t/pitch-typed-throws-in-the-concurrency-module/68210/27). I've partially addressed the problem by introducing a specific rule that allows requirements on `AsyncSequence` and `AsyncIteratorProtocol` to be involved in `rethrows` checking, so existing code that uses `rethrows` in this manner with async sequences will continue to work.

However, that doesn't address the fact that we can't write a proper typed throws signature for `contains`. As @pyrtsa noted, we could elevate `errorUnion` to an actual type in the type system, so we could write, e.g.,:

```swift
extension AsyncSequence {
  func contains<E: Error>(_ predicate: (Element) async throws(E) -> Bool) throws(errorUnion(Failure,E)) -> Bool { ... }
}

```

that's effectively what I've turned `rethrows` into, implicitly. We'd need to do something like this to fully replace the current `rethrows` behavior.

Doug

---

<div class="post-metadata">

**Author:** ![FranzBusch](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/franzbusch/32/19447_2.png) [@FranzBusch](https://forums.swift.org/u/FranzBusch)\
**Post date:** [January 3, 2024, 1:18pm UTC](https://forums.swift.org/t/pitch-typed-throws-in-the-concurrency-module/68210/29 "2024-01-03T13:18:52Z")

</div>

That's great progress. Thanks for putting in the work @Douglas_Gregor. Just a small naming bikeshed: I don't think we should underscore prefix the new method `_nextElement()` since it is quite common for developers to manually create an iterator and call `next()` on it. Having the new method underscored would hide it from code completion.

---

<div class="post-metadata">

**Author:** ![greggwon](https://avatars.discourse-cdn.com/v4/letter/g/3be4f8/32.png) [@greggwon](https://forums.swift.org/u/greggwon)\
**Post date:** [January 9, 2024, 2:58pm UTC](https://forums.swift.org/t/pitch-typed-throws-in-the-concurrency-module/68210/30 "2024-01-09T14:58:14Z")

</div>

I really like chained exceptions for this kind of thing. Every exception should have a constructor that includes a message and an inner exception. This allows the type system to remain constant because only the recognized exception type is ever visible to the called where a throw occurred.

---

<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:** [January 15, 2024, 2:06pm UTC](https://forums.swift.org/t/pitch-typed-throws-in-the-concurrency-module/68210/31 "2024-01-15T14:06:23Z")

</div>

> #### Task cancellation
> 
> A few of the `Task` APIs are documented to only throw `CancellationError` and can adopt typed throws. For example, `checkCancellation`:
> 
> ```swift
> public static func checkCancellation() throws(CancellationError)
> 
> ```

Small editorial note: I find this phrasing problematic for a proposal. Are there more `Task` APIs that will be changed in this way? "A few" and "For example" seems to imply so. In that case, we should list all of them explicitly.

---

<div class="post-metadata">

**Author:** ![ktoso](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ktoso/32/44526_2.png) [@ktoso](https://forums.swift.org/u/ktoso)\
**Post date:** [January 15, 2024, 3:07pm UTC](https://forums.swift.org/t/pitch-typed-throws-in-the-concurrency-module/68210/32 "2024-01-15T15:07:14Z")

</div>

Yeah wording should be precise here.

Strictly speaking it is just:

- `checkCancellation` that can ONLY throw CancellationError

And we could argue about Task.sleep, since in practice this is the only error it will throw nowadays and we document that like this:

```swift
  /// If the task is canceled before the time ends,
  /// this function throws `CancellationError`.

```

The only other place are the sleep methods. The static `Task.sleep` methods...

Those are debatable if we should strictly guarantee only this specific error type -- I'd argue that no.

A specific `Clock` may want to throw for various reasons though. And unless I'm misreading the sources, the Clock.sleep method has no documentation at all, so... we didn't promise we'll just throw a specific error there it seems.

---

<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:** [January 15, 2024, 3:11pm UTC](https://forums.swift.org/t/pitch-typed-throws-in-the-concurrency-module/68210/33 "2024-01-15T15:11:00Z")

</div>

> [@ktoso](#):
>
> A specific `Clock` may want to throw for various reasons though. And unless I'm misreading the sources, the Clock.sleep method has no documentation at all, so... we didn't promise we'll just throw a specific error there it seems.

Yes, the `Clock.sleep` issue is mentioned under [Alternatives considered](https://github.com/apple/swift-evolution/blob/7678a61c3c705f564e734005af544da3768b1f12/proposals/NNNN-typed-throws-concurrency-library.md#adopt-typed-throws-for-clocksleep):

> Most of the clock implementation only throw a `CancellationError` from their `sleep` method; however, nothing enforces this right now and there might be implementations out there that throw a different error. Restricting the protocol to only throw `CancellationError`s would be a breaking change.

---

<div class="post-metadata">

**Author:** ![wadetregaskis](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/wadetregaskis/32/8494_2.png) [@wadetregaskis](https://forums.swift.org/u/wadetregaskis)\
**Post date:** [January 15, 2024, 4:13pm UTC](https://forums.swift.org/t/pitch-typed-throws-in-the-concurrency-module/68210/34 "2024-01-15T16:13:15Z")

</div>

> [@ktoso](#):
>
> And we could argue about Task.sleep, since in practice this is the only error it will throw nowadays and we document that like this:
> 
> ```swift
> /// If the task is canceled before the time ends,
> /// this function throws `CancellationError`.
> 
> ```

I think those horses have left the barn. I rely on that documented behaviour, as does quite a lot of 3rd party code I see. Changing it now will break a lot of existing code, in ways that are somewhat subtle and hard to anticipate and locate.

As such, I think the `sleep` methods should adopt `throws(CancellationError)` - might as well have the compiler ensure the documented invariant lots of people are relying on already.

---

<div class="post-metadata">

**Author:** ![wadetregaskis](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/wadetregaskis/32/8494_2.png) [@wadetregaskis](https://forums.swift.org/u/wadetregaskis)\
**Post date:** [January 16, 2024, 5:52am UTC](https://forums.swift.org/t/pitch-typed-throws-in-the-concurrency-module/68210/35 "2024-01-16T05:52:51Z")

</div>

And I meant to add: it'd be easy enough to add another variant of `sleep` which permits other types of errors, that could be _opted-into_ by interested parties.

e.g. the classic reason why `usleep` bails prematurely is that a signal was received, unless you manually remember to adjust the current thread's signal mask first, which (a) almost nobody ever does and (b) presumably doesn't work for Swift Concurrency since the underlying thread is ill-defined and could change at any suspension point).

I'm led to believe `Task.sleep` ignores signals, but - even with typed throws aside - it would be handy to have a variant which doesn't, e.g.:

```swift
enum Signal {
    case abort
    case alarm
    …
    case hangup
    …
    case userDefined1
    case userDefined2
    …
}

enum SleepError: Error {
    case cancelled
    case interruptedBySignal(Signal)
}

static func sleep<C>(
    until deadline: C.Instant,
    orSignal signals: Set<Signal>,
    tolerance: C.Instant.Duration? = nil,
    clock: C = ContinuousClock()
) async throws(SleepError) where C : Clock

```

(unfortunately Swift currently requires that manual `SleepError` sum type, but ideally one day we'll get built-in support such that it could just say `throws(CancellationError | InterruptedBySignalError)`)

---

<div class="post-metadata">

**Author:** ![filiplazov](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/filiplazov/32/7886_2.png) [@filiplazov](https://forums.swift.org/u/filiplazov)\
**Post date:** [September 4, 2024, 12:09pm UTC](https://forums.swift.org/t/pitch-typed-throws-in-the-concurrency-module/68210/36 "2024-09-04T12:09:08Z")

</div>

Hello

Have these changes been introduced in Swift 6 yet? If not do we know when?  
I tried looking though the Xcode beta release notes and couldn't find a mention of this anywhere.

Thanks  
BR  
FIlip

---

<div class="post-metadata">

**Author:** ![ktoso](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ktoso/32/44526_2.png) [@ktoso](https://forums.swift.org/u/ktoso)\
**Post date:** [September 4, 2024, 12:34pm UTC](https://forums.swift.org/t/pitch-typed-throws-in-the-concurrency-module/68210/37 "2024-09-04T12:34:43Z")

</div>

This proposal wasn’t accepted during the 6.0 timeframe so we’ll continue pursuing in a subsequent release.

---

<div class="post-metadata">

**Author:** ![BastianKusserow](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/bastiankusserow/32/30307_2.png) [@BastianKusserow](https://forums.swift.org/u/BastianKusserow)\
**Post date:** [February 24, 2025, 7:44pm UTC](https://forums.swift.org/t/pitch-typed-throws-in-the-concurrency-module/68210/38 "2025-02-24T19:44:10Z")

</div>

Hey :) Is there maybe already an estimate if or in which swift release those changes will land? I'd be very interested in this, especially because afaik this is currently a roadblocker for shared/distributed async sequences.

Thanks,  
Basti

---

<div class="post-metadata">

**Author:** ![ktoso](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ktoso/32/44526_2.png) [@ktoso](https://forums.swift.org/u/ktoso)\
**Post date:** [February 24, 2025, 11:54pm UTC](https://forums.swift.org/t/pitch-typed-throws-in-the-concurrency-module/68210/39 "2025-02-24T23:54:34Z")

</div>

There's no schedule for this adoption so far.

PS: It's not a blocker for distributed async sequences at all, no. An [distributed async sequence has a PoC over here](https://github.com/apple/swift-distributed-actors/pull/1171) and does not need typed throws. Nice to hear you're interested in distributed, which transport (actor system implementation) were you looking at?

---

<div class="post-metadata">

**Author:** ![filiplazov](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/filiplazov/32/7886_2.png) [@filiplazov](https://forums.swift.org/u/filiplazov)\
**Post date:** [June 19, 2025, 7:52pm UTC](https://forums.swift.org/t/pitch-typed-throws-in-the-concurrency-module/68210/40 "2025-06-19T19:52:15Z")

</div>

Why is this not planned?  
This is one of the biggest reasons for not adopting async streams compared to combine publishers, it is long over due.

---

<div class="post-metadata">

**Author:** ![technogen](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/technogen/32/45489_2.png) [@technogen](https://forums.swift.org/u/technogen)\
**Post date:** [June 19, 2025, 9:25pm UTC](https://forums.swift.org/t/pitch-typed-throws-in-the-concurrency-module/68210/41 "2025-06-19T21:25:25Z")

</div>

> [@filiplazov](#):
>
> Why is this not planned?  
> This is one of the biggest reasons for not adopting async streams compared to combine publishers, it is long over due.

Aside from rude tone being unwelcome, choosing `Combine` over `AsyncSequence` just because `AsyncStream` doesn't have a desired convenience is like choosing `class` over `struct` just to avoid having to write `mutating`... I'll stop elaborating to avoid offending someone on accident.

It's extremely trivial to wrap an `AsyncStream<Result<Success, Failure>, Never>` into an `AsyncSequence` with the appropriate associated types, as a temporary workaround. Removing the workaround in the future should be easy, given how `AsyncStream` is supposed to be an implementation detail and properly abstracted away.

Contributions are welcome.

[Previous page](https://forums.swift.org/t/pitch-typed-throws-in-the-concurrency-module/68210.md?page=1)

[Next page](https://forums.swift.org/t/pitch-typed-throws-in-the-concurrency-module/68210.md?page=3)
