Using macros to declare new structs


#1

Is it possible to declare a new struct from a macro? I’m getting errors related to the compiler expecting a : where I have a ! because I’m calling a macro rather than declaring a member of the struct:

// in macro rules
struct $name {
  add_members!($args)
}

Looking at procedural macros, these seem to be only useful for custom derive calls, not arbitrary token to token conversions.

The end goal is to have a graphql macro which works similarly to this Go library. See the github issue here. Basically, it would be a macro that you wrap around a raw GraphQL query and the macro would generate the result structures required to hold the result (based on the types from the schema) with Rust attributes for controlling the generated structure and code.


#2

tl;dr: You can’t call add_members! there.

You see, macro_rules! macros are not arbitrary token-to-token conversions either. Macros are only allowed to produce certain kinds of things: an expression, a type, or one or more items (and maybe there’s something else I’m forgetting). Macro syntax is basically embedded into the grammar of these parts of the language.

Unfortunately, a “list of struct members” is not one of those things. You’ll need to have that macro produce the whole struct.


Procedural macros are not just limited to derives. The proc-macro-hack crate allows you to use them to generate an expression or one or more items.

If you want to stick to macro_rules!, all I can say is that it’s dangerous to go alone. Take this: https://danielkeep.github.io/tlborm/book/README.html
(I’m serious. You will learn some very interesting and useful techniques about how to write macro_rules! macros that are almost maintainable—which is nice if it lets you dodge a dependency on syn and quote)


#3

Thanks for the info! It seems that proc-macro-hack isn’t useful to me though since it doesn’t allow $ to be in the input (a few of the other limitations seem relevant as well). It may be possible to use quote with a regular procedural macro though, I’ll look into that.


#4

What input syntax does your macro take that requires $?


#5

I’m looking to support GraphQL queries which support variables and use $.

query HeroNameAndFriends($episode: Episode) {
  hero(episode: $episode) {
    name
    friends {
      name
    }
  }
}