asynchronousrecursionrust

Rust recursion in an async fn


I want to use recursion in an async fn, just like:

async fn test(data: i32) -> i32 {
    if data == 0 {
        0
    } else {
        test(data - 1).await
    }
}

This gives the following compiler error:

error[E0733]: recursion in an async fn requires boxing
 --> src/main.rs:1:1
  |
1 | async fn test(data: i32) -> i32 {
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
5 |         test(data - 1).await
  |         -------------------- recursive call here
  |
  = note: a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future

So I change it like this:

async fn test(data: i32) -> BoxFuture<'static, i32> {
    async move {
        if data == 0 {
            0
        } else {
            test(data - 1).await.await
        }
    }
    .boxed()
}

This results in a different error: cycle used when computing type of test::{opaque#0}

What should I do to fix it?


Solution

  • async is more or less syntax sugar for returning a Future, since you already return one, just remove the async from your definiton, it's not needed any more:

    use futures::{FutureExt, future::BoxFuture};
    fn test(data: i32) -> BoxFuture<'static, i32> {
        if data == 0 {
            async { 0 }.boxed()
        } else {
            test(data - 1)
        }
    }
    

    As a rule of thumb, a function should be either async or return a T: Future not both.