macrosrustinfinite-recursion

Infinite recursion in Rust derive macro?


I have made the following attampt at a derive macro in Rust:

extern crate proc_macro;

use crate::proc_macro::TokenStream;
use quote::quote;
use syn;

#[proc_macro_derive(DeserializeConfigurable)]
pub fn deserialize_configurable_derive(input: TokenStream) -> TokenStream {
    let ast: syn::DeriveInput = syn::parse(input).unwrap();
    let name = &ast.ident;
    let gen = quote! {
        impl<'de> Deserialize<'de> for #name {
            fn deserialize<D>(deserializer: D) -> Result<#name, D::Error>
            where
                D: Deserializer<'de>,
            {
                let config = <#name as Configurable>::Config::deserialize(deserializer)?;
                Ok(#name::from_config(config))
            }
        }
    };
    gen.into()
}

The goal is to provide a specific blanket implementation for deserialize based on another trait, Configurable.

However, the compiler has the following complaint regarding my quote statement:

recursion limit reached while expanding the macro stringify

I don't see the recursion here. I am not even using stringify! What is calling what in infinity here?


Solution

  • Trying to compile this locally gives this full error message:

    error: recursion limit reached while expanding the macro `stringify`
      --> src/lib.rs:13:15
       |
    13 |       let gen = quote! {
       |  _______________^
    14 | |         impl<'de> Deserialize<'de> for #name {
    15 | |             fn deserialize<D>(deserializer: D) -> Result<#name, D::Error>
    16 | |             where
    ...  |
    22 | |         }
    23 | |     };
       | |_____^
       |
       = help: consider adding a `#![recursion_limit="128"]` attribute to your crate
       = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)                                                                                                                                 
    
    error: aborting due to previous error
    

    Putting the following as the first line of the crate makes the error go away. My guess is that the default recursion_limit is simply too low for a macro this complex (which IMO isn't that complex). I'm sure there's a good reason, and I'm glad the error message contained the solution:

    #![recursion_limit="128"]