diff --git a/src/expand.rs b/src/expand.rs index 41e838b..0218f59 100644 --- a/src/expand.rs +++ b/src/expand.rs @@ -61,8 +61,18 @@ fn transform_sig(sig: &mut Signature, args: &RecursionArgs) { for arg in &mut sig.inputs { if let FnArg::Typed(pt) = arg { - if let Type::Reference(tr) = pt.ty.as_mut() { - ref_arguments.push(tr); + match pt.ty.as_mut() { + // rustc can give us a None-delimited group if this type comes from + // a macro_rules macro. I don't this can happen for code the user has written. + Type::Group(tg) => { + if let Type::Reference(tr) = &mut *tg.elem { + ref_arguments.push(tr); + } + } + Type::Reference(tr) => { + ref_arguments.push(tr); + } + _ => {} } } else if let FnArg::Receiver(recv) = arg { if let Some((_, slt)) = &mut recv.reference { diff --git a/tests/macros_all_the_way_down.rs b/tests/macros_all_the_way_down.rs new file mode 100644 index 0000000..29d2b57 --- /dev/null +++ b/tests/macros_all_the_way_down.rs @@ -0,0 +1,26 @@ +use futures_executor::block_on; + +macro_rules! recurse { + ($name:ident, $param:ty) => { + #[::async_recursion::async_recursion] + async fn $name(param: $param, f: &F) + where + F: Fn($param) + Sync + Send, + { + f(param); + } + }; +} + +recurse!(owned, usize); +recurse!(by_ref, &usize); +recurse!(by_ref_mut, &mut usize); + +#[test] +fn async_in_macro() { + block_on(async move { + owned(5, &|_| ()).await; + by_ref(&5, &|_| ()).await; + by_ref_mut(&mut 5, &|_| ()).await; + }); +}