Mutually recursive async fns are hard to make Send · Issue #62284 · rust-lang/rust (original) (raw)

There are several other related issues to this, but I'm opening this to track this one specifically since it's a pain-- there are workarounds, but it'd be lovely (and should be possible) to make this "just work." The following example compiles just fine without + Send, but adding the Send bound causes a cycle error:

#![feature(async_await)]

use { std::{ future::Future, pin::Pin, }, };

type BoxFuture = Pin<Box<dyn Future<Output = ()> /* + Send */>>; // adding Send causes a cycle error

async fn foo() -> BoxFuture { Box::pin(bar()) as _ }

async fn bar() { let _ = foo().await; }

Working around the cycle error is possible, but annoying:

#![feature(async_await)]

use { std::{ future::Future, pin::Pin, }, };

type BoxFuture = Pin<Box<dyn Future<Output = ()> + Send>>;

async fn foo() -> BoxFuture { box_bar() }

fn box_bar() -> BoxFuture { Box::pin(bar()) }

async fn bar() { let _ = foo().await; }

Ideally we wouldn't have a cycle error in either case, since it is possible to see that foo must be Send without ever looking at the body of bar, since bar is immediately boxed into a BoxFuture.