# \[Discussion\] Alternative syntax for async iteration: \`for async i in stream\`?

**URL:** https://internals.rust-lang.org/t/discussion-alternative-syntax-for-async-iteration-for-async-i-in-stream/24218
**Category:** language design
**Created:** [May 2, 2026, 5:40pm UTC](https://internals.rust-lang.org/t/discussion-alternative-syntax-for-async-iteration-for-async-i-in-stream/24218 "2026-05-02T17:40:54Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![soplwang](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/soplwang/32/14298_2.png) [@soplwang](https://internals.rust-lang.org/u/soplwang)
#### Post date: [May 2, 2026, 5:40pm UTC](https://internals.rust-lang.org/t/discussion-alternative-syntax-for-async-iteration-for-async-i-in-stream/24218/1 "2026-05-02T17:40:54Z")

</div>

### Hi everyone,

While the community has been gravitating towards `for await i in stream`, I’d like to propose considering **`for async i in stream`** instead.

My core argument is about **declarative vs. imperative mental models** :

1. **Symmetry with Async Closures/Blocks** : We already use `async move || {}` and `async {}` to define asynchronous contexts. Using `for async i` treats the item `i` as an **async binding**. It signals that the source is asynchronous by nature, rather than just adding an imperative "wait" step at the top of the loop.

2. **Patterns, not Actions** : `for await` feels like a command (loop and wait). `for async i` feels like a pattern (for each async item). This aligns better with potential future features like `let async x = ...` (async pattern matching or async drop).

3. **Reflecting the Stream's Nature** : Just as `async fn` describes a function that yields a future, `for async` describes a loop that consumes an asynchronous producer. It keeps the syntax focused on the **type of iteration** rather than the low-level polling mechanism, staying true to Rust's goal of "zero-cost abstractions" for the mind.

I feel `for async` is more "Rust-y" in its declarativeness and provides a more cohesive aesthetic with the rest of the `async`ecosystem.

What do you think? Does `for async` capture the intent of stream processing better than `for await`?

----

**Quick note on context:** I’m aware of the previous discussions comparing `async for` and `for await` (e.g., **[withoutboats' blog post](https://without.boats/blog/for-await-i/)**). However, I want to clarify that **`for async i`** is distinct from the older `async for` proposal.

While `async for` was often discussed as a way to define the entire loop context, my proposal focuses on **async pattern matching/binding** at the item level. It aims to bridge the gap between "how we poll" (`await`) and "what the data is" (`async`). By using `for async`, we treat asynchrony as a property of the iteration binding, which I believe avoids some of the syntactic weight of `for await` while remaining more declarative than the "block-level" `async for`.

---

<div class="post-metadata">

### Author: ![jrose](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jrose/32/9591_2.png) [@jrose](https://internals.rust-lang.org/u/jrose)
#### Post date: [May 2, 2026, 5:52pm UTC](https://internals.rust-lang.org/t/discussion-alternative-syntax-for-async-iteration-for-async-i-in-stream/24218/2 "2026-05-02T17:52:35Z")

</div>

The `await` in `for await` is trying to suggest a very specific meaning: "there is a suspension point here, unwrapping a future (and possibly pausing execution)". Similarly, the `async` in `async fn` and the hypothetical `async let` [sic; a reference to a Swift feature rather than destructuring] has the opposite meaning: "there's an implicit `async` block here, wrapping computation into a future".

`for async` would make sense to me if you still have to `i.await` in the body of the loop…but if that were the case, how would the loop ever know when to terminate? Either _something_ has to be awaited before the body begins, or the signature of `next` would need to be `Option<Future<…>>` rather than `Future<Option<…>>`, which would be less useful. So I think `for await` remains the correct choice.

---

<div class="post-metadata">

### Author: ![soplwang](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/soplwang/32/14298_2.png) [@soplwang](https://internals.rust-lang.org/u/soplwang)
#### Post date: [May 2, 2026, 6:07pm UTC](https://internals.rust-lang.org/t/discussion-alternative-syntax-for-async-iteration-for-async-i-in-stream/24218/3 "2026-05-02T18:07:31Z")

</div>

Thanks for the feedback!

I agree that in `async fn` or `async {}`, `async` acts as a "wrapper." However, I’d argue that in the context of a **binding site** (like `for <pattern> in <stream>`), `async` can be naturally extended to mean **"this binding is resolved asynchronously."**

A few counter-points to consider:

1. **Async Patterns vs. Async Wrappers** : In a `for` loop, the `i` is a pattern. Just as `&i` in a loop destructures a reference, `async i` could be seen as "destructuring" (or resolving) an asynchronous value. It tells the compiler: "The source is async, and we are binding the resolved value to `i`."

2. **The "Wait" is implicit in `for`** : The `for` keyword already implies a sequential progression. Adding `await` feels like describing _how_ the engine works (imperative), whereas `async` describes the _nature_ of the data being bound (declarative).

3. **Avoiding the "Future of Option" confusion** : You mentioned `Option<Future<...>>`. My proposal doesn't change the underlying `AsyncIterator` trait (which remains `Future<Output = Option<T>>`). Instead, it’s about how we denote the **suspension point**.

If we eventually get `let async i = ...` for destructuring futures or handling async drop, `for async i` becomes perfectly consistent. It marks the **boundary** where asynchrony is handled, rather than just being a label for the `await` operation itself.

---

<div class="post-metadata">

### Author: ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)
#### Post date: [May 2, 2026, 6:08pm UTC](https://internals.rust-lang.org/t/discussion-alternative-syntax-for-async-iteration-for-async-i-in-stream/24218/4 "2026-05-02T18:08:31Z")

</div>

> [@soplwang](#):
>
> While the community has been gravitating towards `for await i in stream`, I’d like to propose considering **`for async i in stream`** instead.

FWIW, other languages also uses `await` here. For example, `await foreach` in C#: [https://learn.microsoft.com/en-us/archive/msdn-magazine/2019/november/csharp-iterating-with-async-enumerables-in-csharp-8#a-tour-through-async-enumerables](https://learn.microsoft.com/en-us/archive/msdn-magazine/2019/november/csharp-iterating-with-async-enumerables-in-csharp-8#a-tour-through-async-enumerables).

`async` is for "this is a thunk", but that's not what's happening in a for loop.

---

<div class="post-metadata">

### Author: ![soplwang](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/soplwang/32/14298_2.png) [@soplwang](https://internals.rust-lang.org/u/soplwang)
#### Post date: [May 2, 2026, 6:13pm UTC](https://internals.rust-lang.org/t/discussion-alternative-syntax-for-async-iteration-for-async-i-in-stream/24218/5 "2026-05-02T18:13:40Z")

</div>

> [@scottmcm](#):
>
> FWIW, other languages also uses `await` here. For example, `await foreach` in C#: [C# - Iterating with Async Enumerables in C# 8 | Microsoft Learn](https://learn.microsoft.com/en-us/archive/msdn-magazine/2019/november/csharp-iterating-with-async-enumerables-in-csharp-8#a-tour-through-async-enumerables).
> 
> `async` is for "this is a thunk", but that's not what's happening in a for loop.

Fair point on C#, but Rust's design philosophy often excels when it diverges from other languages to favor its own strengths: **patterns and bindings.**

While `await` describes an imperative action, `async` in `for async i` describes the **nature of the binding**. In Rust, where we use patterns like `for &x in ...`, treating asynchrony as a property of the data flow (the binding `i`) feels more "Rust-y" and forward-looking than just adding an imperative `await` keyword because others did.

Let's prioritize semantic consistency with Rust's own `async` ecosystem over following the `await foreach` precedent.

---

<div class="post-metadata">

### Author: ![SkiFire13](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/skifire13/32/7579_2.png) [@SkiFire13](https://internals.rust-lang.org/u/SkiFire13)
#### Post date: [May 2, 2026, 7:21pm UTC](https://internals.rust-lang.org/t/discussion-alternative-syntax-for-async-iteration-for-async-i-in-stream/24218/6 "2026-05-02T19:21:32Z")

</div>

> [@soplwang](#):
>
> Just as `async fn` describes a function that yields a future, `for async` describes a loop that consumes an asynchronous producer.

I hope you see the contraddiction here: the former yields while the other consumes (just like `.await`)

> [@soplwang](#):
>
> my proposal focuses on **async pattern matching/binding** at the item level

The issue here is that streams are not `Iterator<Item = impl Future>` where you can just await each item. You have to instead `await` getting the item itself. For this reason they cannot be fit into the existing `for` machinery, and adding a new kind of binding won't change this.

> [@soplwang](#):
>
> Thanks for the insightful feedback! You’ve hit on the core semantic tension here.

Can we please avoid generating posts/answers using LLMs? Or if you really want to do so at least remove the blatant parts.

---

<div class="post-metadata">

### Author: ![soplwang](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/soplwang/32/14298_2.png) [@soplwang](https://internals.rust-lang.org/u/soplwang)
#### Post date: [May 26, 2026, 8:19pm UTC](https://internals.rust-lang.org/t/discussion-alternative-syntax-for-async-iteration-for-async-i-in-stream/24218/8 "2026-05-26T20:19:03Z")

</div>

> [@jrose](#):
>
> The `await` in `for await` is trying to suggest a very specific meaning: "there is a suspension point here, unwrapping a future

Make sense and very helpful for me, thank you!!!

---

<div class="post-metadata">

### Author: ![MusicalNinjaDad](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/musicalninjadad/32/11986_2.png) [@MusicalNinjaDad](https://internals.rust-lang.org/u/MusicalNinjaDad)
#### Post date: [May 27, 2026, 2:57pm UTC](https://internals.rust-lang.org/t/discussion-alternative-syntax-for-async-iteration-for-async-i-in-stream/24218/9 "2026-05-27T14:57:11Z")

</div>

> [@SkiFire13](#):
>
> Can we please avoid generating posts/answers using LLMs? Or if you really want to do so at least remove the blatant parts.

@soplwang - would you be willing to let us know: did you use an LLM:

- to _create_ your answer from a prompt
- to _translate_ your answer from another language
- not at all

I often worry that my usual way of expressing myself, as someone with all kinds of trauma and ND, looks just like an LLM and gets for for that reason ... (Sorry for the off-topic question)

---

<div class="post-metadata">

### Author: ![soplwang](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/soplwang/32/14298_2.png) [@soplwang](https://internals.rust-lang.org/u/soplwang)
#### Post date: [June 8, 2026, 2:51pm UTC](https://internals.rust-lang.org/t/discussion-alternative-syntax-for-async-iteration-for-async-i-in-stream/24218/10 "2026-06-08T14:51:25Z")

</div>

Actually I like @SkiFire13's 坦诚清晰的 response. I've used LLM help _translate_ my intentions (from latent space in my mind).
