Rust Macros
Written
- Useful Links
- https://danielkeep.github.io/tlborm/book is a useful source of info
- https://github.com/dtolnay/proc-macro-workshop
- Arguments
- Macro argument types
expr
- Any expressionident
- An identifierpath
- A module pathty
- A typeitem
- A top level item (use
,struct Something{}
, etc.)tt
- Any token treeblock
- A code block in brackets
- Argument patterns can have
*
or+
added to it to indicate repetition.-
macro_rules! macro { ($an_arg: expr, $($num: expr),*) => { let mut x = get_number($an_arg); $( x += $num; )* // Wrapping it like this expands the variadic arguments x } }
-
- Macro argument types
- Nested macros
- Macros normally can't call each other if one of the macros is used from another module.
- But you can create another macro rule in the same macro. Traditionally these rules start with @ to reduce chances of accidentally triggering the rule.
-
macro_rules! macro1 { () => { macro1!(@macro2)}; (@macro2) => { the nested macro } }
- Dealing with tokens
- The
paste
crate lets you concatenate multiple identifiers into a new identifier, which is difficult to do in normal macros.
- The
- Proc Macros
- These are more powerful and are written in Rust.
- They can be function-like macros as with
macro_rules!
or attribute macros like#[test]
, or derive macros to work with#[derive(...)]
. - Since these are effectively compiler plugins, they have to be in a separate crate from the one that uses the macro.
- Useful Crates
syn
helps with parsing Rust source.
Thanks for reading! If you have any questions or comments, please send me a note on Twitter or Mastodon.