# SE-0520: Discardable result use in Task initializers

**URL:** <https://forums.swift.org/t/se-0520-discardable-result-use-in-task-initializers/85374>\
**Category:** Proposal Reviews\
**Created:** [March 16, 2026, 9:33pm UTC](https://forums.swift.org/t/se-0520-discardable-result-use-in-task-initializers/85374 "2026-03-16T21:33:53Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![hborla](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/hborla/32/27563_2.png) [@hborla](https://forums.swift.org/u/hborla)\
**Post date:** [March 16, 2026, 9:33pm UTC](https://forums.swift.org/t/se-0520-discardable-result-use-in-task-initializers/85374/1 "2026-03-16T21:33:53Z")

</div>

Hello, Swift community!

The review of [SE-0520: Discardable result use in Task initializers](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0520-discardableresult-task-initializers.md) begins now and runs through March 30, 2026.

Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you would like to keep your feedback private, directly to me as the review manager by [email](mailto:hborla@apple.com) or [DM](https://forums.swift.org/u/hborla/summary). When contacting the review manager directly, please put "SE-0520" in the subject line.

##### **Trying it out**

The toolchain with the latest implementation is currently building - @ktoso will update the review thread with the toolchain links for macOS, Linux, and Windows when they're ready.

##### **What goes into a review?**

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift. When writing your review, here are some questions you might want to answer in your review:

- What is your evaluation of the proposal?
- Is the problem being addressed significant enough to warrant a change to Swift?
- Does this proposal fit well with the feel and direction of Swift?
- If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
- How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

More information about the Swift evolution process is available at:

> [swift-evolution/process.md at main · swiftlang/swift-evolution · GitHub](https://github.com/swiftlang/swift-evolution/blob/main/process.md)

Thank you,

Holly Borla  
Review Manager

---

<div class="post-metadata">

**Author:** ![CrystDragon](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/crystdragon/32/10461_2.png) [@CrystDragon](https://forums.swift.org/u/CrystDragon)\
**Post date:** [March 17, 2026, 7:29am UTC](https://forums.swift.org/t/se-0520-discardable-result-use-in-task-initializers/85374/2 "2026-03-17T07:29:03Z")

</div>

Overall +1.

I'm just concerned about one point:

> instead, this proposal will introduce a new bespoke warning mechanism which is able to trigger ...

I assume magic like this that complicates the compiler is generally not preferred?

---

<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:** [March 17, 2026, 10:08am UTC](https://forums.swift.org/t/se-0520-discardable-result-use-in-task-initializers/85374/3 "2026-03-17T10:08:20Z")

</div>

Yeah generally it's better to model things with general features, agreed.

The way I've implemented this is with an attribute that basically says "if there is an parameter with a closure, and it throws, assume we must not discard the result even though it's not re-throwing". It COULD be generalized in the future to make it into an official attribute as such behavior is common for any "future-like" type, like Task. So it's kinda niche, but not necessarily tied to Task, and I could see other libraries making use of it (basically an extension of @discardableResult).

So I wouldn't mind the extra work to pitch an official spelling for this in the future. Since we're a bit late for the 6.4 release I'd suggest reviewing this independently though.

---

<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:** [March 17, 2026, 10:27pm UTC](https://forums.swift.org/t/se-0520-discardable-result-use-in-task-initializers/85374/4 "2026-03-17T22:27:03Z")

</div>

Here's toolchain links, built freshly off [Sign in to GitHub · GitHub](https://github.com/swiftlang/swift/pull/87439:)

- macOS: [https://download.swift.org/tmp/pull-request/87439/2255/xcode/swift-PR-87439-2255-osx.tar.gz](https://download.swift.org/tmp/pull-request/87439/2255/xcode/swift-PR-87439-2255-osx.tar.gz)
- Linux (Ubuntu 22.04, x86\_64): [https://download.swift.org/tmp/pull-request/87439/1684/ubuntu2204/PR-ubuntu2204.tar.gz](https://download.swift.org/tmp/pull-request/87439/1684/ubuntu2204/PR-ubuntu2204.tar.gz)

---

<div class="post-metadata">

**Author:** ![jrose](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jrose/32/408_2.png) [@jrose](https://forums.swift.org/u/jrose)\
**Post date:** [March 18, 2026, 5:17am UTC](https://forums.swift.org/t/se-0520-discardable-result-use-in-task-initializers/85374/5 "2026-03-18T05:17:43Z")

</div>

Is it not possible to do this via the existing overloads, from before typed throws? Admittedly that doesn't account for `throws(Never)`, but that's a bit of an edge case anyway.

(I am in favor of the proposal in general.)

---

<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:** [March 18, 2026, 6:10am UTC](https://forums.swift.org/t/se-0520-discardable-result-use-in-task-initializers/85374/6 "2026-03-18T06:10:22Z")

</div>

Part of the goal here is to reduce the number of overloads. It's gotten so bad that we had to use gyb to generate the sheer number of overloads of task initializers and task groups in the past.

Adopting typed throws has a side-benefit of being able to kill off this gyb generation and converge on less overloads: the [de-gybification](https://github.com/swiftlang/swift/pull/87822) is in progress over here, and isn't really tied to the proposal semantics itself, but since you asked why we're doing it this way and not another way, that's a contributing factor.

---

<div class="post-metadata">

**Author:** ![OneSadCookie](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/onesadcookie/32/3205_2.png) [@OneSadCookie](https://forums.swift.org/u/OneSadCookie)\
**Post date:** [March 18, 2026, 7:43am UTC](https://forums.swift.org/t/se-0520-discardable-result-use-in-task-initializers/85374/7 "2026-03-18T07:43:01Z")

</div>

I continue to believe that you don't generally want to discard task handles, aside from possibly "`dispatch_async`-like" cases (synchronous after an initial actor hop).

That said, this is clearly better than the status quo, and nothing prevents adding warnings in more cases in future, so definitely +1.

---

<div class="post-metadata">

**Author:** ![ellie20](https://avatars.discourse-cdn.com/v4/letter/e/6f9a4e/32.png) [@ellie20](https://forums.swift.org/u/ellie20)\
**Post date:** [March 25, 2026, 5:04pm UTC](https://forums.swift.org/t/se-0520-discardable-result-use-in-task-initializers/85374/8 "2026-03-25T17:04:38Z")

</div>

> [@ktoso](#):
>
> Yeah generally it's better to model things with general features, agreed.
> 
> The way I've implemented this is with an attribute that basically says "if there is an parameter with a closure, and it throws, assume we must not discard the result even though it's not re-throwing". It COULD be generalized in the future to make it into an official attribute as such behavior is common for any "future-like" type, like Task. So it's kinda niche, but not necessarily tied to Task, and I could see other libraries making use of it (basically an extension of @discardableResult).
> 
> So I wouldn't mind the extra work to pitch an official spelling for this in the future. Since we're a bit late for the 6.4 release I'd suggest reviewing this independently though.

If this does eventually get an official spelling, perhaps it could take the form of a `where` clause on `@discardableResult`. So the `Task` initializer could have `@discardableResult(where Failure == Never)`.

But since for now, this proposal introduces magic, I think it could be worthwhile to extend the magic to also account for non-`Void` and non-`@discardableResult` closures. That is, there could be another compiler-internal attribute that says "if there is a parameter with a closure, and the closure returns `Void` _or_ it has an implicit return from a single expression that calls a `@discardableResult` function".

---

<div class="post-metadata">

**Author:** ![tera](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tera/32/38201_2.png) [@tera](https://forums.swift.org/u/tera)\
**Post date:** [March 27, 2026, 11:36am UTC](https://forums.swift.org/t/se-0520-discardable-result-use-in-task-initializers/85374/9 "2026-03-27T11:36:10Z")

</div>

> [@ellie20](#):
>
> So the `Task` initializer could have `@discardableResult(where Failure == Never)`.

Perhaps "where Failure == Never && Success == Void" to ensure that not only errors but results themselves are never lost.

---

<div class="post-metadata">

**Author:** ![tera](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tera/32/38201_2.png) [@tera](https://forums.swift.org/u/tera)\
**Post date:** [March 29, 2026, 12:37pm UTC](https://forums.swift.org/t/se-0520-discardable-result-use-in-task-initializers/85374/10 "2026-03-29T12:37:03Z")

</div>

Could this work:

> [@](#):
>
> extension Task where **Success == Void,** Failure == Never {  
> @discardableResult init(...)  
> }
> 
> extension Task ** ~~where Failure == any Error~~ ** {  
> ** ~~@discardableResult~~ ** init(...)  
> }

to only have `discardableResult` for `Success == Void && Failure == Never` combination?

What was the reason for having `where Failure == any Error` at all, could it be anything else?

---

<div class="post-metadata">

**Author:** ![Nobody1707](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/nobody1707/32/2169_2.png) [@Nobody1707](https://forums.swift.org/u/Nobody1707)\
**Post date:** [March 29, 2026, 5:07pm UTC](https://forums.swift.org/t/se-0520-discardable-result-use-in-task-initializers/85374/11 "2026-03-29T17:07:28Z")

</div>

Surely `Failure` could be a concrete `Error` type.

---

<div class="post-metadata">

**Author:** ![tera](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tera/32/38201_2.png) [@tera](https://forums.swift.org/u/tera)\
**Post date:** [March 30, 2026, 3:10pm UTC](https://forums.swift.org/t/se-0520-discardable-result-use-in-task-initializers/85374/12 "2026-03-30T15:10:57Z")

</div>

This seems to work desirably (mocking the Task API):

```swift
struct Test<Success, Failure: Error> {}

extension Test where Success == Void, Failure == Never {
    @discardableResult init(operation: () -> Success) {}
}

extension Test where Failure == any Error {
    init(operation: () throws -> Success) {}
}

enum MyError: Error { case error }

Test { () -> Void in } // void, no throw, ✅ no warning
Test { () -> Int in 0 } // int, no throw, 🔶 unused warning
Test { throw MyError.error } // void, throw 🔶 unused warning
Test { throw MyError.error; return 0 } // int, throw 🔶 unused warning

```

---

<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:** [March 30, 2026, 3:40pm UTC](https://forums.swift.org/t/se-0520-discardable-result-use-in-task-initializers/85374/13 "2026-03-30T15:40:24Z")

</div>

I think we want the latter extension to use typed throws like so:

```swift
extension Test {
    init(operation: () throws(Failure) -> Success) {}
}

```

But that also compiles just like your mock, and the point remains and I agree only `Task<Void, Never>.init` should be `@discardableResult`.

But there's a practical question of whether the code churn of having to type `_ = ...` in non-throwing cases too would be too large. For instance, one practical issue with `@discardableResult` is that it doesn't get forwarded in [cases like](https://developer.apple.com/documentation/swift/asyncstream/continuation/yield(_:)):

```swift
let (stream, continuation) = AsyncStream.makeStream(of: Int.self)
Test { // ⚠️ Result of 'Test<Success, Failure>' initializer is unused
    continuation.yield(42)
}

```

forcing to prepend either the inner or the outer expression with `_ =`.

---

<div class="post-metadata">

**Author:** ![tera](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tera/32/38201_2.png) [@tera](https://forums.swift.org/u/tera)\
**Post date:** [March 30, 2026, 3:46pm UTC](https://forums.swift.org/t/se-0520-discardable-result-use-in-task-initializers/85374/14 "2026-03-30T15:46:50Z")

</div>

> [@pyrtsa](#):
>
> ```swift
> let (stream, continuation) = AsyncStream.makeStream(of: Int.self)
> Test { // ⚠️ Result of 'Test<Success, Failure>' initializer is unused
> continuation.yield(42)
> }
> 
> ```
> 
> forcing to prepend either the inner or the outer expression with `_ =`.

I'd say neither of those, but something more like:

```swift
try continuation.yield(42).checkResult()

```

which will throw on yield errors.

---

<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:** [March 30, 2026, 3:53pm UTC](https://forums.swift.org/t/se-0520-discardable-result-use-in-task-initializers/85374/15 "2026-03-30T15:53:35Z")

</div>

That's not my point. In this case, my code wanted to form a `Task<Void, Never>` (or your mock `Test<Void, Never>`) from a non-throwing expression, but due to [`yield(_:)`](https://developer.apple.com/documentation/swift/asyncstream/continuation/yield(_:)) returning a `@discardableResult` itself, the type system actually made it a `Task<AsyncStream<Int>.Continuation.YieldResult, Never>`, which by your proposed new rules would no longer be `@discardableResult` itself.

I also think the API would be clearest if only `Task<Void, Never>` was `@discardableResult`, and all other types of unstructured `Task`s (throwing, or non-throwing but value-returning) would give the warning unless explicitly discarded.

But I'm trying to point out that there may be cases where the community may still want to keep `Task<_, Never>` also `@discardableResult` for all other `Success` types than `Void`, as well.

---

<div class="post-metadata">

**Author:** ![tera](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tera/32/38201_2.png) [@tera](https://forums.swift.org/u/tera)\
**Post date:** [March 30, 2026, 4:01pm UTC](https://forums.swift.org/t/se-0520-discardable-result-use-in-task-initializers/85374/16 "2026-03-30T16:01:46Z")

</div>

Yeah, I see. One example I had in mind was `items.removeLast()` which returns the item which would have to be silenced with `_ = ` if it's unwanted.

In case of your example it could be silenced with `try! continuation.yield(42).checkResult()` to not get that throw propagated outside (with the side benefit that if it does throw – you'd quickly know about that).

> [@pyrtsa](#):
>
> I also think the API would be clearest if only `Task<Void, Never>` was `@discardableResult`, and all other types of unstructured `Task`s (throwing, or non-throwing but value-returning) would give the warning unless explicitly discarded.

I'd love that as well... even to the point if `discardableResults` returning functions were not be able participating in the "single (or last) expression don't need return" machinery and require explicit return statements to make intent clear (as [pitched here](https://forums.swift.org/t/pitch-idea-compiler-warnings-about-explicit-vs-implicit-returns/))

* * *

Thinking out loud: what if discardable was on type? And thus propagable along with the type..

```swift
Task { // inferred as Task<discardable Int, Never>
    items.removeLast() // `discardable Int`
}

```

along with something akin to:

```swift
extension Task where Success is discardable, Failure == Never {
    @discardableResult init(...) { ... }
}

```

* * *

> **Existing precedents from other languages of embedding discardability in types**
>
> ```swift
> struct [[nodiscard]] SomeType {
> int x;
> };
> SomeType foo() {
> return SomeType();
> }
> void bar() {
> auto proc = []{ return foo(); };
> proc(); // 🔶 Warning: Ignoring return value of function declared with 'nodiscard' attribute
> }
> 
> ```

---

<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:** [March 30, 2026, 11:19pm UTC](https://forums.swift.org/t/se-0520-discardable-result-use-in-task-initializers/85374/17 "2026-03-30T23:19:34Z")

</div>

An unfortunate development here is that we're not able to use typed throws in this API (yet), as doing so has caused a significant flood of source compatibility regressions. We'll have to solve these implications of typed throws before this API will be able to adopt it. (typed throws adoption was [reverted](https://github.com/swiftlang/swift/pull/88172)).

This discussion should continue about just "throws" but the spirit of the proposal remains the same.

---

<div class="post-metadata">

**Author:** ![hborla](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/hborla/32/27563_2.png) [@hborla](https://forums.swift.org/u/hborla)\
**Post date:** [April 21, 2026, 8:16pm UTC](https://forums.swift.org/t/se-0520-discardable-result-use-in-task-initializers/85374/18 "2026-04-21T20:16:10Z")

</div>

Thank you to everyone who participated in this review! The proposal has been **accepted**.

> [@\[Accepted\] SE-0520: Discardable result use in Task initializers](https://forums.swift.org/t/accepted-se-0520-discardable-result-use-in-task-initializers/86159):
>
> Hello, Swift Evolution! The [review](https://forums.swift.org/t/se-0520-discardable-result-use-in-task-initializers/85374) of [SE-0520: Discardable result use in Task initializers](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0520-discardableresult-task-initializers.md) concluded, and the Language Steering Group decided that the proposal is accepted. The review discussion was positive, and the constructive discussion focused on more cases where we should consider producing warnings on discarded task handles: Some reviewers argued that ignoring task handles should always produce a warning. The LSG believes this would be an overly pervasive warning; fire-and-forget task…

Holly Borla  
Review Manager

---

<div class="post-metadata">

**Author:** ![John\_McCall](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/john_mccall/32/1351_2.png) [@John\_McCall](https://forums.swift.org/u/John_McCall)\
**Post date:** [April 21, 2026, 9:26pm UTC](https://forums.swift.org/t/se-0520-discardable-result-use-in-task-initializers/85374/19 "2026-04-21T21:26:30Z")

</div>

Closed on April 21, 2026, 9:26pm UTC


