External Publication
Visit Post

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

Rust Internals [Unofficial] May 2, 2026
Source

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 asyncecosystem.

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). 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.

Discussion in the ATmosphere

Loading comments...