What a procedural macro is (in one sentence)
A procedural macro is Rust code that runs at compile time and generates Rust code by programmatically transforming syntax trees.
Normal Rust code runs at runtime
Procedural macros run while the compiler is compiling
How to use procedural macro
- Define the macro
#[proc_macro_attribute]
pub fn my_macro(attr: TokenStream, item: TokenStream) -> TokenStream- The function name (my_macro) is the macro’s identifier.
- To use it, you write:
#[my_macro]TokenStream
A TokenStream is:
A sequence of Rust tokens, not text, not AST.
Tokens are things like:
- identifiers: vm_entry, fn, main
- punctuation: #, (, ), {, }
- literals: “hello”, 123
- keywords: fn, struct, impl
What is a Rust token?
A token is a smallest meaningful unit of Rust syntax.
Examples of tokens:
• keywords: fn, struct, pub
• identifiers: main, x, WomirConfig
• punctuation: ( ) { } , ; #
• operators: + -> =
• literals: 123, "hello"
Spaces, newlines, indentation are NOT tokens
AST
AST = Abstract Syntax Tree
- Tree → hierarchical structure (nodes with children)
- Syntax → structure of the language
- Abstract → details like whitespace, comments, formatting are removed
So:
An AST is a structured, tree-shaped representation of your code that captures its meaningful syntax, not how it was typed.
From text → tokens → AST
Rust compilation (simplified):
source code (text)
↓
tokens
↓
AST
↓
name resolution, type checking, MIR, LLVM, …
Example: code vs AST
Take this code:
fn add(a: i32, b: i32) -> i32 {
a + b
}
As text
Just characters.
As tokens
Something like:
fn | add | ( | a | : | i32 | , | b | : | i32 | ) | -> | i32 | { | a | + | b | }
As AST (conceptually)
Function
├─ name: add
├─ params
│ ├─ a: i32
│ └─ b: i32
├─ return_type: i32
└─ body
└─ BinaryExpr(+)
├─ Ident(a)
└─ Ident(b)What is syn used for in macros?
syn is used to parse a TokenStream into a Rust AST so you can inspect code structurally instead of manually reading tokens.
Most commonly used syn things
Parsing
syn::parse::<T>(tokens)
syn::parse_macro_input!(tokens as T)