MCPcopy Index your code
hub / github.com/dcchut/async-recursion

github.com/dcchut/async-recursion @v1.1.1

Chat with this repo
repository ↗ · DeepWiki ↗ · release v1.1.1 ↗ · + Follow
103 symbols 142 edges 42 files 1 documented · 1%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

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:

```rust,compile_fail 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:

```console
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://crates.io/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 * Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) * MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)

at your option.

Extension points exported contracts — how you extend this code

ThirtySeven (Interface)
(no doc) [1 implementers]
tests/generic_parameters.rs

Core symbols most depended-on inside this repo

descend
called by 3
tests/generic_parameters.rs
contains_value
called by 2
tests/expand/lifetimes_no_send_bound.rs
assert_is_sync
called by 2
tests/ui/arg_not_sync.rs
expand
called by 1
src/expand.rs
transform_block
called by 1
src/expand.rs
lifetime
called by 1
src/expand.rs
transform_sig
called by 1
src/expand.rs
fib
called by 1
tests/fibonacci.rs

Shape

Function 75
Method 15
Class 10
Enum 2
Interface 1

Languages

Rust100%

Modules by API surface

tests/generic_parameters.rs9 symbols
src/expand.rs9 symbols
tests/struct_methods.rs8 symbols
tests/lifetimes.rs7 symbols
src/parse.rs5 symbols
tests/ui/args_repeated.rs4 symbols
tests/ui/args_invalid.rs4 symbols
tests/ui/arg_not_sync.rs4 symbols
tests/fibonacci.rs4 symbols
tests/expand/args_punctuated.rs4 symbols
tests/expand/args_punctuated.expanded.rs4 symbols
tests/expand/macros_nested.expanded.rs3 symbols

For agents

$ claude mcp add async-recursion \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact