# SE-0493: Support \`async\` calls in \`defer\` bodies

**URL:** <https://forums.swift.org/t/se-0493-support-async-calls-in-defer-bodies/82293>\
**Category:** Proposal Reviews\
**Tags:** concurrency\
**Created:** [September 22, 2025, 10:38pm UTC](https://forums.swift.org/t/se-0493-support-async-calls-in-defer-bodies/82293 "2025-09-22T22:38:13Z")\
**Posts on this page:** 20\
**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:** [September 22, 2025, 10:38pm UTC](https://forums.swift.org/t/se-0493-support-async-calls-in-defer-bodies/82293/1 "2025-09-22T22:38:13Z")

</div>

Hello, Swift community!

The review of [SE-0493: Support `async` calls in `defer` bodies](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0493-defer-async.md) begins now and runs through October 6, 2025.

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-0493" in the subject line.

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

If you'd like to try this proposal out, you can download a toolchain supporting it for [Linux](https://download.swift.org/tmp/pull-request/83891/1497/ubuntu2204/PR-ubuntu2204.tar.gz), [Windows](https://ci-external.swift.org/job/swift-PR-build-toolchain-windows/6094/artifact/*zip*/archive.zip), or [macOS](https://ci.swift.org/job/swift-PR-toolchain-macos/2069/artifact/branch-main/swift-PR-83891-2069-osx.tar.gz).

##### **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:

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

Thank you,

Holly Borla  
Review Manager

---

<div class="post-metadata">

**Author:** ![mickeyl](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/mickeyl/32/12258_2.png) [@mickeyl](https://forums.swift.org/u/mickeyl)\
**Post date:** [September 23, 2025, 7:26am UTC](https://forums.swift.org/t/se-0493-support-async-calls-in-defer-bodies/82293/2 "2025-09-23T07:26:04Z")

</div>

Hurray! This came up a lot of times since 5.5, hopefully it makes it this time. A strong +1 from me.

---

<div class="post-metadata">

**Author:** ![x-sheep](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/x-sheep/32/40748_2.png) [@x-sheep](https://forums.swift.org/u/x-sheep)\
**Post date:** [September 23, 2025, 8:32am UTC](https://forums.swift.org/t/se-0493-support-async-calls-in-defer-bodies/82293/3 "2025-09-23T08:32:21Z")

</div>

+1 on the current version from me. As currently proposed, the `defer` statement is still the same as manually copying the same block of code to every exit path (including `catch` blocks), which doesn't affect cancellation behavior.

---

<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:** [September 23, 2025, 11:09am UTC](https://forums.swift.org/t/se-0493-support-async-calls-in-defer-bodies/82293/4 "2025-09-23T11:09:29Z")

</div>

+1 on the proposal. While it doesn't solve the asynchronous resource management problem I think it addresses an inconsistency in the language. Regardless if developers run clean-up code _normally_ or in a defer they will have to consider task cancellation anyways.

---

<div class="post-metadata">

**Author:** ![Jason\_Gregori](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jason_gregori/32/15205_2.png) [@Jason\_Gregori](https://forums.swift.org/u/Jason_Gregori)\
**Post date:** [September 23, 2025, 1:47pm UTC](https://forums.swift.org/t/se-0493-support-async-calls-in-defer-bodies/82293/5 "2025-09-23T13:47:43Z")

</div>

This is great! +1

---

<div class="post-metadata">

**Author:** ![noremac](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/noremac/32/7222_2.png) [@noremac](https://forums.swift.org/u/noremac)\
**Post date:** [September 23, 2025, 1:58pm UTC](https://forums.swift.org/t/se-0493-support-async-calls-in-defer-bodies/82293/6 "2025-09-23T13:58:43Z")

</div>

I’ve needed this many times. The proposal looks great. +1!

Since it was mentioned I’ll also +1 to expressing interest on the more general `withCancellationIgnored`.

---

<div class="post-metadata">

**Author:** ![tourultimate](https://avatars.discourse-cdn.com/v4/letter/t/85f322/32.png) [@tourultimate](https://forums.swift.org/u/tourultimate)\
**Post date:** [September 23, 2025, 3:22pm UTC](https://forums.swift.org/t/se-0493-support-async-calls-in-defer-bodies/82293/7 "2025-09-23T15:22:58Z")

</div>

+ 1.

Looks good. I Agree on the reasons why cancellation is honored as normal and that a general purpose `withCancellationIgnored` can be part of a future proposal.

---

<div class="post-metadata">

**Author:** ![jaleel](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jaleel/32/45076_2.png) [@jaleel](https://forums.swift.org/u/jaleel)\
**Post date:** [September 23, 2025, 4:32pm UTC](https://forums.swift.org/t/se-0493-support-async-calls-in-defer-bodies/82293/8 "2025-09-23T16:32:09Z")

</div>

Simply **+1** , long _awaited_.

---

<div class="post-metadata">

**Author:** ![vanvoorden](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/vanvoorden/32/33619_2.png) [@vanvoorden](https://forums.swift.org/u/vanvoorden)\
**Post date:** [September 23, 2025, 6:49pm UTC](https://forums.swift.org/t/se-0493-support-async-calls-in-defer-bodies/82293/9 "2025-09-23T18:49:43Z")

</div>

LGTM! I saw some discussion in the pitch threads about a throwing `defer` as a potential future direction. Is this anything about this specific pitch that would in any way block a potential future throwing `defer` from shipping? Are there any gotchas or callouts that should be added to the proposal for engineers that want to come back to this in the future to ship throwing `defer`? Or are they independent and orthogonal such that a throwing `defer` is just an easy composition that can happen later without too much trouble?

---

<div class="post-metadata">

**Author:** ![grynspan](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/grynspan/32/15315_2.png) [@grynspan](https://forums.swift.org/u/grynspan)\
**Post date:** [September 23, 2025, 10:36pm UTC](https://forums.swift.org/t/se-0493-support-async-calls-in-defer-bodies/82293/10 "2025-09-23T22:36:50Z")

</div>

How do I put this concisely and politely?

_YES PLEASE._ 😁

**Edit:** I should probably say _something_ substantive. The reasoning in the proposal seems perfectly sound to me. And having `async defer` behave fundamentally the same way as `defer` does today is absolutely the right way to go.

I look forward to using this feature in Swift Testing!

---

<div class="post-metadata">

**Author:** ![Jumhyn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jumhyn/32/3891_2.png) [@Jumhyn](https://forums.swift.org/u/Jumhyn)\
**Post date:** [September 23, 2025, 10:42pm UTC](https://forums.swift.org/t/se-0493-support-async-calls-in-defer-bodies/82293/11 "2025-09-23T22:42:00Z")

</div>

I don’t see any reason why anything in this proposal would block future work on throwing `defer`. I expect that whatever difficulties we’ll have to contend with will be equally applicable to both regular `defer` bodies in addition to `defer` bodies which contain an `await`. Open to the idea that there’s something I haven’t considered but as far as I can tell these are separable concerns!

---

<div class="post-metadata">

**Author:** ![grynspan](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/grynspan/32/15315_2.png) [@grynspan](https://forums.swift.org/u/grynspan)\
**Post date:** [September 23, 2025, 10:44pm UTC](https://forums.swift.org/t/se-0493-support-async-calls-in-defer-bodies/82293/12 "2025-09-23T22:44:20Z")

</div>

> [@Jumhyn](#):
>
> I don’t see any reason why anything in this proposal would block future work on throwing `defer`.

The only real concern I have with throwing `defer` is how to handle the case where two or more errors might need to be thrown:

```swift
func f() throws {
  defer { throw DeferredError() }
  throw OriginalError()
}

```

Which is as much a question of documentation as it is anything else. And I don't read this question as blocking `async defer`.

---

<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:** [September 23, 2025, 11:56pm UTC](https://forums.swift.org/t/se-0493-support-async-calls-in-defer-bodies/82293/13 "2025-09-23T23:56:39Z")

</div>

Right, there's a fundamental semantic problem with throwing `defer` that the `throw` messes up whatever control flow you were doing previously to exit the `defer` scope. If that control flow was normal, the silent override from the error is much trickier for programmers to reason about. If it was abnormal, you have to decide which error actually gets thrown. There's just no appealing generic answer there in any case. But, fortunately, it's completely separable from `async`.

---

<div class="post-metadata">

**Author:** ![beccadax](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/beccadax/32/34217_2.png) [@beccadax](https://forums.swift.org/u/beccadax)\
**Post date:** [September 24, 2025, 2:35am UTC](https://forums.swift.org/t/se-0493-support-async-calls-in-defer-bodies/82293/14 "2025-09-24T02:35:09Z")

</div>

I think this is a very good idea.

While the point made in the alternatives about there being no `await` at the actual site of the suspension is interesting, I don’t think there’s a good design that would adequately address this issue. The only model I can think of in the language for an await happening later is with `async let`, but that only covers a single expression, not multiple statements, and it provides a natural syntax to hang the eventual `await` keyword off of. There are places where scopes end and `defer`s may be run that simply do not have anything to mark with `await`, or where requiring an `await` would shed more heat than light (imagine if you had to `await` every `try` that could run an async `defer`). I think we’ll just have to consider the `await` being inside a `defer` to be notice enough that the scope exit may suspend execution.

---

<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 24, 2025, 5:48am UTC](https://forums.swift.org/t/se-0493-support-async-calls-in-defer-bodies/82293/15 "2025-09-24T05:48:30Z")

</div>

Great to see this come to review 🙂

As we chatted in the previous thread, I think this is very good and a necessary step towards better async cleanups, that we’re slowly making progress towards recently (isolated deinits, this feature, and in the future cancellation shielding, and eventually most likely some form of context managers…).

And this version has the right tradeoffs about cancellation–we can build on top of it with cancellation shielding later on, separately.

The implicit await at end of scope if unavoidable and the right thing to do anyway; It is already a thing with `async let` so it’s not a new surprising semantic in that sense.

–

I kept thinking about whether or not we need the `async` in `defer async`. The one problem I see with omitting the async is that technically, when folding code, like so:

```swift
func test() async { 
  defer { ... } // folded
}

```

then… we don’t have information by scanning just the “outer” keywords anymore about the suspensions… if the body of the defer has an await, there will be a suspension, if not… then not.

This is in contrast to async let, where the same scope the `async` appears is known to potentially suspend:

```swift
func test() async { 
  async let x = { ... } // folded or just "don't have to read the body"
}

```

So there’s a bit of a difference here… It would be a bit more consistent to say that implicit suspensions can only happen in a scope where an async happens.

I think the explicit `defer async` is a small price to pay for the ability to very easily visually scanning a piece of code to understand if there might be suspensions, rather than having to then unpack and think about the defer _might_ have an await etc.

Where this is important is of course trying to write code which doesn’t accidentally become reentrant due to such suspension.

```swift
func test() async { 
  defer async { ... } // folded or just "don't have to read the body"
}

```

So this is definitely simpler to read and remember and more visually consistent… so I’m leaning towards that to be honest.

If one were to think about the `{ }` like it’s just a closure then one might argue that we just infer the `throws` and `async` on those… However, such closure isn’t called by itself – and any call site would then have the visual signal about those effects. So I think we have to base our comparison here on the existing prior art of `async let` and not just treating it “just” like a closure.

It’s not a huge argument, but thinking about this a bit today I ended up thinking that for visual consistency and ease of reading the `defer async` may be preferable after all.

It also makes error messages and explaining things a bit easier, since we can name it an “async defer” when we refer to it, but that’s just a minor bit.

---

<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:** [September 24, 2025, 7:18am UTC](https://forums.swift.org/t/se-0493-support-async-calls-in-defer-bodies/82293/16 "2025-09-24T07:18:30Z")

</div>

> [@ktoso](#):
>
> ```swift
> func test() async { 
> defer { ... } // folded
> }
> 
> ```

> Where this is important is of course trying to write code which doesn’t accidentally become reentrant due to such suspension.

I don’t think this is such a big problem, since you already have the `async` keyword in the function declaration, meaning you already need to keep a careful eye against reentrancy in this scope.

I don’t think it’s in any way different from `await` calls being folded out inside `do { … }` or `if … { … }` bodies or such.

---

<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:** [September 24, 2025, 10:42am UTC](https://forums.swift.org/t/se-0493-support-async-calls-in-defer-bodies/82293/17 "2025-09-24T10:42:17Z")

</div>

> [@John\_McCall](#):
>
> Right, there's a fundamental semantic problem with throwing `defer` that the `throw` messes up whatever control flow you were doing previously to exit the `defer` scope. If that control flow was normal, the silent override from the error is much trickier for programmers to reason about. If it was abnormal, you have to decide which error actually gets thrown. There's just no appealing generic answer there in any case. But, fortunately, it's completely separable from `async`.

This is going outside the scope of this proposal but it would be interesting if we can model this with an `inout Error?` parameter into `defer`. If the scope is using typed throws we would need to support that as well.

---

<div class="post-metadata">

**Author:** ![grynspan](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/grynspan/32/15315_2.png) [@grynspan](https://forums.swift.org/u/grynspan)\
**Post date:** [September 24, 2025, 11:18am UTC](https://forums.swift.org/t/se-0493-support-async-calls-in-defer-bodies/82293/18 "2025-09-24T11:18:01Z")

</div>

> [@beccadax](#):
>
> I think we’ll just have to consider the `await` being inside a `defer` to be notice enough that the scope exit may suspend execution.

If we think of `defer` as a control flow statement like `if` or `while`, then this is no different from them. If you have an `await` expression inside the body of a `while`-loop, you don't annotate the `while` loop with extra keywords either.

(Did I already say that earlier? ☕)

---

<div class="post-metadata">

**Author:** ![Jumhyn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jumhyn/32/3891_2.png) [@Jumhyn](https://forums.swift.org/u/Jumhyn)\
**Post date:** [September 24, 2025, 2:03pm UTC](https://forums.swift.org/t/se-0493-support-async-calls-in-defer-bodies/82293/19 "2025-09-24T14:03:10Z")

</div>

> [@ktoso](#):
>
> I kept thinking about whether or not we need the `async` in `defer async`. The one problem I see with omitting the async is that technically, when folding code, like so:
> 
> ```swift
> func test() async { 
> defer { ... } // folded
> }
> 
> ```

Yeah, as others have mentioned, I don’t think this is meaningfully different than the ability to ‘collapse’ the scope of a `do { … }` or an `if { … }` or a `while { … }` etc.

The _vast_ majority of `defer`s that I write are also extremely short, typically just a line or two at most, and often collapsed onto a single line. Which means that if we required marking the whole `defer` we’d end up with something like:

```swift
defer async { await cleanup() }

```

Which feels excessive to me... moreover, I think that the naturally short nature of `defer` bodies naturally means that they're exceedingly unlikely to be collapsed in an IDE.

> [@ktoso](#):
>
> It also makes error messages and explaining things a bit easier, since we can name it an “async defer” when we refer to it, but that’s just a minor bit.

I'm interested in prodding at this a bit more—I'm actually curious to hear how you think we might need to refer to "async defer" as a proper standalone concept. It is of course necessary in this proposal since we're introducing the feature, but the reasoning around not messing with the cancellation behavior is to keep the semantics of code in a `defer` identical to code outside a `defer`. The rule remains that `defer` is 'just' a way to run some block of code on scope exit, and that block of code may or may not suspend as indicated by an `await`. IOW the 'normal' rules for `defer` combined with the 'normal' rules for `await` combine to fully describe the behavior here. I'm not sure we'll _need_ to refer to "async defer" as anything other than a `defer` which happens to contain an `await`.

(Our explanatory job here is _easier_ than it was when introducing `async let` because the 'code that implicitly runs on scope exit' semantics are already fully covered by `defer`—for `async let` the implicit cancellation and `await` on scope exit was totally novel. To the extent we're introducing 'implicit' suspension points, any explanation is more or less in the 'avoidance of doubt category: 'yes, these two features compose in the most simple, straightforward way'.)

---

<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 24, 2025, 3:00pm UTC](https://forums.swift.org/t/se-0493-support-async-calls-in-defer-bodies/82293/20 "2025-09-24T15:00:51Z")

</div>

> [@Jumhyn](#):
>
> ```swift
> defer async { await cleanup() }
> 
> ```
> 
> Which feels excessive to me... moreover, I think that the naturally short nature of `defer` bodies naturally means that they're exceedingly unlikely to be collapsed in an IDE.

Yeah that one’s quite a mouthful, a good counterpoint really – since a lot of defers look like that.

> [@Jumhyn](#):
>
> I'm interested in prodding at this a bit more—I'm actually curious to hear how you think we might need to refer to "async defer" as a proper standalone concept.

It’s a very small nit, but I was thinking about “async defer cannot appear in non-async method” or a similar message like that.

But I guess we could not refer to the defer at all – just that the `await` cannot appear in a non-async method, without really introducing a new diagnostic at all.

–

So yeah, those aren’t points I’m supper convinced of but thought it might be good to bring them up for discussion. It seems we may be well off with just the `defer` after all then. Thanks for entertaining the thought experiment, always better to double check I feel 🙂

[Next page](https://forums.swift.org/t/se-0493-support-async-calls-in-defer-bodies/82293.md?page=2)
