Evaluation macro_rules! arguments before procedural macro

Hi there!

I'm currently writing a macro which looks like this:

macro_rules! my_macro {
  ($typename: ident) => {
    #[some_macro]
    impl $typename { /* some code here */ }
  }
}

This throws the could not determine a name for the impl type when I try to compile it. I suppose it is caused by the fact that impl $typename is provided "as is" to the #[some_macro] attribute. What I'd like to do is the opposite, I need to write an impl block with a dynamic name and then apply the procedural macro on it.

How can I do that?

Thanks in advance for your help!

Do you control some_macro? If you do, could you check that the input to it indeed contains $typename as-is? I'm quite sure that this is not the case, but can't check it right now.

I do not, I only control my_macro. #[some_macro] is imported from a third-party crate.

This is not what should happen. First the macro is expanded, and only then the proc macro is called on its output. Can you post the full error, preferrably linking to a playground?

Unfortunately it uses a third-party crate so it's kind of difficult, but the code I posted triggers that error directly by itself.

The proc macro used is juniper::graphql_object.

I've looked into the code of the attribute macro, and, indeed, it doesn't support calling this way.

The reason is that the type, matched as ident, is not a raw ident anymore - it's a Type::Group, i.e. it is wrapped in the invisible parenthesis (due to the hygienic requirements). junuper macro doesn't handle this case correctly.

You can circumevent this issue by using tt matcher instead of ident:

macro_rules! my_macro {
    ($typename:tt) => {
        #[juniper::graphql_object]
        impl $typename {
            /* something here */
        }
    };
}

Tokens matched by tt are passed further as-is, so attribute macro will have no problem with them. However, I'll file an issue to juniper a bit later, anyway.

2 Likes

I didn't know it worked like that!

Thank you very much :pray:

It took a little time, but I've finally filed the PR - Incorrect handling of types matched as idents by Cerber-Ursi · Pull Request #1054 · graphql-rust/juniper · GitHub.

1 Like

Thank you very much!