recursive_proc_macro_impl/
lib.rs1use proc_macro::TokenStream;
4use quote::{quote, ToTokens};
5use syn::{parse_macro_input, ItemFn, ReturnType, Type};
6
7#[proc_macro_attribute]
8pub fn recursive(args: TokenStream, item: TokenStream) -> TokenStream {
9 let arg_parser = syn::meta::parser(|meta| {
10 Err(meta.error("#[recursive] does not have configuration options"))
11 });
12 parse_macro_input!(args with arg_parser);
13
14 let mut item_fn: ItemFn =
15 syn::parse(item.clone()).expect("#[recursive] can only be applied to functions");
16 assert!(
17 item_fn.sig.asyncness.is_none(),
18 "#[recursive] does not support async functions"
19 );
20
21 let block = item_fn.block;
22 let ret = match &item_fn.sig.output {
23 ReturnType::Type(_, typ) if matches!(**typ, Type::ImplTrait(_)) => ReturnType::Default,
26 _ => item_fn.sig.output.clone(),
27 };
28 let wrapped_block = quote! {
29 {
30 ::recursive::__impl::stacker::maybe_grow(
31 ::recursive::get_minimum_stack_size(),
32 ::recursive::get_stack_allocation_size(),
33 move || #ret { #block }
34 )
35 }
36 };
37 item_fn.block = Box::new(syn::parse(wrapped_block.into()).unwrap());
38 item_fn.into_token_stream().into()
39}