lotsoftools

Rust Error E0733: Async Recursion Without Boxing

Understanding Rust Error E0733

Rust Error E0733 occurs when an async function attempts to use recursion without proper boxing. To understand this error better, let's examine the erroneous code example provided in the official documentation:

#![allow(unused)]
fn main() {
async fn foo(n: usize) {
    if n > 0 {
        foo(n - 1).await;
    }
}
}

Fixing Rust Error E0733

To fix Rust Error E0733, we need to desugar the async function to make the Future explicit in the return type. Here's how the modified version of the code should look:

#![allow(unused)]
fn main() {
use std::future::Future;
fn foo_desugared(n: usize) -> impl Future<Output = ()> {
    async move {
        if n > 0 {
            foo_desugared(n - 1).await;
        }
    }
}
}

Finally, we need to wrap the future in a pinned box to ensure that the result is of known size and to keep it in the same location in memory:

#![allow(unused)]
fn main() {
use std::future::Future;
use std::pin::Pin;
fn foo_recursive(n: usize) -> Pin<Box<dyn Future<Output = ()>>> {
    Box::pin(async move {
        if n > 0 {
            foo_recursive(n - 1).await;
        }
    })
}
}

Understanding the Solution

The solution involves three primary steps: 1. Desugar the async function to make the Future explicit in the return type. 2. Use async move to transfer ownership of the captured variables, allowing them to be passed into the nested call. 3. Wrap the future in a pinned box to ensure it remains in the same place in memory.

Final Thoughts

In conclusion, Rust Error E0733 can be resolved by properly handling the recursive async functions' return types and ensuring the proper use of pinned boxes. This approach ensures that your Rust code compiles successfully and runs as expected.

Recommended Reading