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 match ::syn::parse::Parser::parse(arg_parser, args) {
::syn::__private::Ok(data) => data,
::syn::__private::Err(err) => {
return ::syn::__private::TokenStream::from(err.to_compile_error());
}
};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 if !item_fn.sig.asyncness.is_none() {
{
::core::panicking::panic_fmt(format_args!("#[recursive] does not support async functions"));
}
};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 #[allow(non_exhaustive_omitted_patterns)] match **typ {
Type::ImplTrait(_) => true,
_ => false,
}matches!(**typ, Type::ImplTrait(_)) => ReturnType::Default,
26 _ => item_fn.sig.output.clone(),
27 };
28 let wrapped_block = {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "recursive");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "__impl");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "stacker");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "maybe_grow");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "recursive");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s,
"get_minimum_stack_size");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
::quote::__private::push_comma(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "recursive");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s,
"get_stack_allocation_size");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "move");
::quote::__private::push_or_or(&mut _s);
::quote::ToTokens::to_tokens(&ret, &mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&block, &mut _s);
_s
});
_s
});
_s
});
_s
}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}