Macros
The functionality and syntax of Rust can be extended with custom definitions called macros. They are given names, and invoked through a consistent syntax: some_extension!(...).
There are two ways to define new macros:
- Macros by example define new syntax in a higher-level, declarative way.
- Procedural macros define function-like macros, custom derives, and custom attributes using functions that operate on input tokens.
Macro invocation
MacroInvocation ->
SimplePath `!` DelimTokenTree
DelimTokenTree ->
`(` TokenTree* `)`
| `[` TokenTree* `]`
| `{` TokenTree* `}`
TokenTree ->
Token _except [delimiters][lex.token.delim]_ | DelimTokenTree
MacroInvocationSemi ->
SimplePath `!` `(` TokenTree* `)` `;`
| SimplePath `!` `[` TokenTree* `]` `;`
| SimplePath `!` `{` TokenTree* `}`
A macro invocation expands a macro at compile time and replaces the invocation with the result of the macro. Macros may be invoked in the following situations:
- Items including associated items
macro_rulestranscribers
When used as an item or a statement, the [MacroInvocationSemi] form is used where a semicolon is required at the end when not using curly braces. Visibility qualifiers are never allowed before a macro invocation or macro_rules definition.
// Used as an expression.
let x = vec!;
// Used as a statement.
println!;
// Used in a pattern.
if let pat! = Some
// Used in a type.
=> ;
}
type N2 = Tuple!;
// Used as an item.
# use RefCell;
thread_local!;
// Used as an associated item.
// Macro calls within macros.
// Outer macro `example` is expanded, then inner macro `println` is expanded.
example!;
Macros invocations can be resolved via two kinds of scopes:
- Textual Scope
- Path-based scope