Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: dcchut/async-recursion
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.0.2
Choose a base ref
...
head repository: dcchut/async-recursion
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v1.0.3
Choose a head ref
  • 2 commits
  • 8 files changed
  • 1 contributor

Commits on Mar 18, 2023

  1. Copy the full SHA
    68e44e4 View commit details
  2. v1.0.3 release

    dcchut committed Mar 18, 2023
    Copy the full SHA
    53e178f View commit details
Showing with 79 additions and 46 deletions.
  1. +51 −0 .github/workflows/ci.yml
  2. +0 −22 .github/workflows/rust.yml
  3. +2 −2 Cargo.toml
  4. +11 −15 README.md
  5. +2 −0 rustfmt.toml
  6. +7 −4 src/expand.rs
  7. +5 −2 src/parse.rs
  8. +1 −1 tests/ui/must_use.stderr
51 changes: 51 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: CI

on:
push:
branches:
- master
pull_request:
schedule: [cron: "0 0 * * *"]

permissions:
contents: read

env:
RUSTFLAGS: -Dwarnings

jobs:
test:
name: Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@stable
- run: cargo test --verbose

fmt:
name: Fmt
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@nightly
with:
components: rustfmt
- run: cargo fmt -- --check

clippy:
name: Clippy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@nightly
with:
components: clippy
- run: cargo clippy -- -Dwarnings

outdated:
name: Outdated
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: dtolnay/install@cargo-outdated
- run: cargo outdated --exit-code 1
22 changes: 0 additions & 22 deletions .github/workflows/rust.yml

This file was deleted.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "async-recursion"
version = "1.0.2"
version = "1.0.3"
authors = ["Robert Usher <266585+dcchut@users.noreply.github.com>"]
edition = "2018"
license = "MIT OR Apache-2.0"
@@ -15,7 +15,7 @@ proc-macro = true
[dependencies]
proc-macro2 = { version = "1.0", default-features = false }
quote = { version = "1.0", default-features = false }
syn = { version = "1.0", features = ["full", "parsing", "printing", "proc-macro", "clone-impls"], default-features = false }
syn = { version = "2.0", features = ["full", "parsing", "printing", "proc-macro", "clone-impls"], default-features = false }

[dev-dependencies]
futures-executor = "0.3"
26 changes: 11 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@

[![Latest version](https://img.shields.io/crates/v/async-recursion)](https://crates.io/crates/async-recursion)
[![crates.io downloads](https://img.shields.io/crates/d/async_recursion)](https://crates.io/crates/async-recursion)
[![Build Status](https://img.shields.io/github/actions/workflow/status/dcchut/async-recursion/rust.yml?branch=master)](https://github.com/dcchut/async-recursion/actions)
[![Build Status](https://img.shields.io/github/actions/workflow/status/dcchut/async-recursion/ci.yml?branch=master)](https://github.com/dcchut/async-recursion/actions)
![Apache/MIT2.0 License](https://img.shields.io/crates/l/async-recursion)

Procedural macro for recursive async functions.
@@ -13,12 +13,10 @@ Procedural macro for recursive async functions.
## Motivation
Consider the following recursive implementation of the fibonacci numbers:

```rust,ignore
async fn fib(n : u32) -> u64 {
```rust,compile_fail
async fn fib(n : u32) -> u32 {
match n {
0 => panic!("zero is not a valid argument to fib()!"),
1 | 2 => 1,
3 => 2,
0 | 1 => 1,
_ => fib(n-1).await + fib(n-2).await
}
}
@@ -28,13 +26,13 @@ The compiler helpfully tells us that:

```console
error[E0733]: recursion in an `async fn` requires boxing
--> src/main.rs:1:26
--> src/main.rs:1:26
|
1 | async fn fib(n : u32) -> u64 {
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
= 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
@@ -46,12 +44,10 @@ to one returning a boxed `Future`.
use async_recursion::async_recursion;

#[async_recursion]
async fn fib(n : u32) -> u64 {
async fn fib(n : u32) -> u32 {
match n {
0 => panic!("zero is not a valid argument to fib()!"),
1 | 2 => 1,
3 => 2,
_ => fib(n-1).await + fib(n-2).await
0 | 1 => 1,
_ => fib(n-1).await + fib(n-2).await
}
}
```
2 changes: 2 additions & 0 deletions rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
group_imports = "StdExternalCrate"
imports_granularity = "Crate"
11 changes: 7 additions & 4 deletions src/expand.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
use crate::parse::{AsyncItem, RecursionArgs};
use proc_macro2::{Span, TokenStream};
use quote::{quote, ToTokens};
use syn::punctuated::Punctuated;
use syn::{parse_quote, Block, FnArg, Lifetime, ReturnType, Signature, Type, WhereClause};
use syn::{
parse_quote, punctuated::Punctuated, Block, FnArg, Lifetime, ReturnType, Signature, Type,
WhereClause,
};

use crate::parse::{AsyncItem, RecursionArgs};

impl ToTokens for AsyncItem {
fn to_tokens(&self, tokens: &mut TokenStream) {
@@ -75,7 +78,7 @@ fn transform_sig(sig: &mut Signature, args: &RecursionArgs) {
for ra in &mut ref_arguments {
// If this reference arg doesn't have a lifetime, give it an explicit one
if ra.lifetime.is_none() {
let lt = Lifetime::new(&format!("'life{}", counter), Span::call_site());
let lt = Lifetime::new(&format!("'life{counter}"), Span::call_site());

lifetimes.push(ArgLifetime::New(parse_quote!(#lt)));

7 changes: 5 additions & 2 deletions src/parse.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use proc_macro2::Span;
use syn::parse::{Error, Parse, ParseStream, Result};
use syn::{token::Question, ItemFn, Token};
use syn::{
parse::{Error, Parse, ParseStream, Result},
token::Question,
ItemFn, Token,
};

pub struct AsyncItem(pub ItemFn);

2 changes: 1 addition & 1 deletion tests/ui/must_use.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ error: unused return value of `apples` that must be used
--> tests/ui/must_use.rs:9:5
|
9 | apples(3);
| ^^^^^^^^^^
| ^^^^^^^^^
|
note: the lint level is defined here
--> tests/ui/must_use.rs:1:9