What are Rust's three procedural macros and derive's advantage over macro_rules?
Tests Rust macros and AST generation vs text macros. Lists derive, attribute-like, and function-like macros, then explains derive needs AST introspection for per-field impl unreachable with macro_rules. Red flag: that macro_rules can iterate struct fields.
WHAT THIS TESTS: This question tests whether you understand the architectural boundary between declarative and procedural macros in Rust. Interviewers want to see that you know procedural macros run at compile time on TokenStream inputs and operate at the AST level, while macro_rules is a pattern-matching system on token trees without semantic understanding of Rust syntax.
A GOOD ANSWER COVERS: First, list the three kinds of procedural macros: custom derive, attribute-like, and function-like. Second, explain that a custom derive macro is attached to a type definition and receives the full AST of that type as a TokenStream. Third, contrast this with macro_rules, which can only match and substitute token patterns but cannot inspect the semantic structure of a type, such as counting fields, reading field names, or checking types. Fourth, emphasize that derive macros generate code based on the actual shape of the data, which requires parsing Rust syntax into a structured form, something macro_rules cannot do robustly because it lacks type introspection and operates before name resolution.
COMMON WRONG ANSWERS: A major red flag is claiming that macro_rules could implement a custom derive by simply repeating a pattern. Another mistake is confusing the three types or omitting attribute-like and function-like procedural macros. Some candidates also incorrectly state that procedural macros run at runtime or that they modify the compiler itself. Failing to mention TokenStream or AST-level manipulation suggests shallow knowledge.
LIKELY FOLLOW-UPS: An interviewer might ask how you would implement a custom derive macro in practice, including the use of syn and quote crates. They might ask about hygiene in procedural macros or how to emit helpful compiler errors from within a proc macro. Another follow-up is asking when you would choose an attribute-like macro over a derive macro, or how function-like procedural macros differ from macro_rules in terms of invocation syntax and capabilities.
ONE CONCRETE EXAMPLE: Suppose you want to implement a MyDebug derive that prints each field name and value. A procedural derive macro receives the struct AST, iterates over fields, and generates an impl Debug block with format_args for each field. With macro_rules, you cannot write a pattern that accepts an arbitrary struct and iterates its fields by name and type, because macro_rules has no mechanism to destructure a struct definition into its constituent fields during expansion. You would need to write a separate macro invocation per field or use a brittle recursive pattern that does not scale.
Read the original → doc.rust-lang.org
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.