Given a simple async function:
async fn foo(n: usize) -> usize {
if n > 0 { foo(n - 1).await }
else { 0 }
}
The compiler complains that async fn
must be rewritten to return a boxed dyn Future
.
| async fn foo(n: usize) -> usize {
| ^^^^^ recursive `async fn`
= note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`.
For more information about this error, try `rustc --explain E0733`.
Compiler explanation (rustc --explain E0733
):
To achieve async recursion, the async fn
needs to be desugared
such that the Future
is explicit in the return type:
use std::future::Future;
fn foo_desugared(n: usize) -> impl Future<Output = ()> {
async move {
if n > 0 {
foo_desugared(n - 1).await;
}
}
}
Finally, the future is wrapped in a pinned box:
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;
}
})
}
The Box<...>
ensures that the result is of known size,
and the pin is required to keep it in the same place in memory.
Now consider this code:
fn foo(n: &usize) -> Pin<Box<dyn Future<Output = usize>>> {
Box::pin(async move {
if *n > 0 {
foo(&n).await
} else {
0
}
})
}
The compiler complains that the lifetime of &n
should be 'static
.
| fn foo(n: &usize) -> Pin<Box<dyn Future<Output = usize>>> {
| ------ help: add explicit lifetime `'static` to the type of `n`: `&'static usize`
| / Box::pin(async move {
| | if *n > 0 {
| | foo(&n).await
| | } else {
| | 0
| | }
| | })
| |______^ lifetime `'static` required
Please help me understand what is going on.