# Async iterator: why not both poll\_next and async next?

**URL:** <https://internals.rust-lang.org/t/async-iterator-why-not-both-poll-next-and-async-next/20321>\
**Category:** cargo\
**Created:** [February 14, 2024, 7:14am UTC](https://internals.rust-lang.org/t/async-iterator-why-not-both-poll-next-and-async-next/20321 "2024-02-14T07:14:33Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![dlight](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dlight/32/8462_2.png) [@dlight](https://internals.rust-lang.org/u/dlight)\
**Post date:** [February 14, 2024, 7:14am UTC](https://internals.rust-lang.org/t/async-iterator-why-not-both-poll-next-and-async-next/20321/1 "2024-02-14T07:14:33Z")

</div>

Rust's async iterator could be defined like this

```rust
#[required(or(poll_next, next))]
pub trait AsyncIterator {
    type Item;

    // required methods: either poll_next or next

    fn poll_next(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>
    ) -> Poll<Option<Self::Item>>;

    async fn next(&mut self) -> Option<Self::Item>;

    // Provided method
    fn size_hint(&self) -> (usize, Option<usize>);
}

```

And, using [an idea from Haskell](https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/pragmas.html#minimal-pragma), the trait implementer can define the trait either using `poll_next` or `next`; if one is missing, it is automatically defined in terms of the other (in the trait definition, they are mutually recursive, but one of them is required, in order to tie the knot).

* * *

This idea doesn't require maybe async at all, but,

Even if Rust ends up having effects or "maybe async", extending the already existing `Iterator` trait, having both methods is this is still possible: just define that while the `next` method is maybe async (as expected), the `poll_next` method exists only if the trait is async (but it isn't itself async).

Something like this (made up syntax)

```rust
#[required(or(poll_next, next))]
pub trait async<A> Iterator {
    type Item;

    // required methods: either poll_next or next

    #[if_async<A>] // poll_next exists only when the trait is async
    fn poll_next(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>
    ) -> Poll<Option<Self::Item>>;

    async<A> fn next(&mut self) -> Option<Self::Item>;

    // Provided method
    fn size_hint(&self) -> (usize, Option<usize>);

    // many other provided methods
}

```

In this case, one can either impl a type for `Iterator` using `next` and `async Iterator` using `poll_next` (which is the most low level way, which also enables using async-only constructs in the async implementation), _or_ they can impl a type for both sync and async iterators at the same time (which requires implementing maybe async `next` and not using async-only constructs)

Something like this

```rust
struct S;

// separate implementations for both `Iterator` and `async Iterator`

impl Iterator for S {
    fn next(..) ..
}

impl async Iterator for S {
    fn poll_next(..) ..

    // or async fn next(...) ..
}

```

or

```rust
// a single implementation for both sync and async iterators
impl async<A> Iterator for S {
    async<A> fn next(...) ...
}

```

---

<div class="post-metadata">

**Author:** ![dlight](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dlight/32/8462_2.png) [@dlight](https://internals.rust-lang.org/u/dlight)\
**Post date:** [February 14, 2024, 7:20am UTC](https://internals.rust-lang.org/t/async-iterator-why-not-both-poll-next-and-async-next/20321/2 "2024-02-14T07:20:01Z")

</div>

Note: this idea is kind of a comment on a number of blog posts;

- [A four year plan for async Rust](https://without.boats/blog/a-four-year-plan/)

- [Async Iteration III: The Async Iterator Trait](https://blog.yoshuawuyts.com/async-iterator-trait/)

- [poll\_next](https://without.boats/blog/poll-next/)

---

<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:** [February 14, 2024, 8:42am UTC](https://internals.rust-lang.org/t/async-iterator-why-not-both-poll-next-and-async-next/20321/3 "2024-02-14T08:42:07Z")

</div>

> [@dlight](#):
>
> if one is missing, it is automatically defined in terms of the other

How would you define `poll_next` in terms of `next`? AFAIK the problem is that `next` returns the state in a separate `Future`, while `poll_next` must hold it internally inside `self`.

Also, `next` is not object safe, while `poll_next` is.

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [February 14, 2024, 8:49am UTC](https://internals.rust-lang.org/t/async-iterator-why-not-both-poll-next-and-async-next/20321/4 "2024-02-14T08:49:36Z")

</div>

@traviscross has a concrete proposal for defining these two models in terms of each other. It can be done, but it definitely requires more complexity than just making them both methods of the same trait with default implementations.

---

<div class="post-metadata">

**Author:** ![dlight](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dlight/32/8462_2.png) [@dlight](https://internals.rust-lang.org/u/dlight)\
**Post date:** [February 14, 2024, 9:42am UTC](https://internals.rust-lang.org/t/async-iterator-why-not-both-poll-next-and-async-next/20321/5 "2024-02-14T09:42:10Z")

</div>

> [@SkiFire13](#):
>
> How would you define `poll_next` in terms of `next`?

Oh, I just assumed it would be possible..

> [@josh](#):
>
> @traviscross has a concrete proposal for defining these two models in terms of each other.

That's interesting! Did he post somewhere?

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [August 7, 2025, 9:42am UTC](https://internals.rust-lang.org/t/async-iterator-why-not-both-poll-next-and-async-next/20321/6 "2025-08-07T09:42:22Z")

</div>

This topic was automatically closed 540 days after the last reply. New replies are no longer allowed.
