mirror of https://github.com/rust-lang/reference
105 lines
2.9 KiB
Markdown
105 lines
2.9 KiB
Markdown
# 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
|
|
|
|
> **<sup>Syntax</sup>**\
|
|
> _MacroInvocation_ :\
|
|
> [_SimplePath_] `!` _DelimTokenTree_
|
|
>
|
|
> _DelimTokenTree_ :\
|
|
> `(` _TokenTree_<sup>\*</sup> `)`\
|
|
> | `[` _TokenTree_<sup>\*</sup> `]`\
|
|
> | `{` _TokenTree_<sup>\*</sup> `}`
|
|
>
|
|
> _TokenTree_ :\
|
|
> [_Token_]<sub>_except [delimiters]_</sub> | _DelimTokenTree_
|
|
>
|
|
> _MacroInvocationSemi_ :\
|
|
> [_SimplePath_] `!` `(` _TokenTree_<sup>\*</sup> `)` `;`\
|
|
> | [_SimplePath_] `!` `[` _TokenTree_<sup>\*</sup> `]` `;`\
|
|
> | [_SimplePath_] `!` `{` _TokenTree_<sup>\*</sup> `}`
|
|
|
|
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:
|
|
|
|
* [Expressions] and [statements]
|
|
* [Patterns]
|
|
* [Types]
|
|
* [Items] including [associated items]
|
|
* [`macro_rules`] transcribers
|
|
* [External blocks]
|
|
|
|
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.
|
|
|
|
```rust
|
|
// Used as an expression.
|
|
let x = vec![1,2,3];
|
|
|
|
// Used as a statement.
|
|
println!("Hello!");
|
|
|
|
// Used in a pattern.
|
|
macro_rules! pat {
|
|
($i:ident) => (Some($i))
|
|
}
|
|
|
|
if let pat!(x) = Some(1) {
|
|
assert_eq!(x, 1);
|
|
}
|
|
|
|
// Used in a type.
|
|
macro_rules! Tuple {
|
|
{ $A:ty, $B:ty } => { ($A, $B) };
|
|
}
|
|
|
|
type N2 = Tuple!(i32, i32);
|
|
|
|
// Used as an item.
|
|
# use std::cell::RefCell;
|
|
thread_local!(static FOO: RefCell<u32> = RefCell::new(1));
|
|
|
|
// Used as an associated item.
|
|
macro_rules! const_maker {
|
|
($t:ty, $v:tt) => { const CONST: $t = $v; };
|
|
}
|
|
trait T {
|
|
const_maker!{i32, 7}
|
|
}
|
|
|
|
// Macro calls within macros.
|
|
macro_rules! example {
|
|
() => { println!("Macro call in a macro!") };
|
|
}
|
|
// Outer macro `example` is expanded, then inner macro `println` is expanded.
|
|
example!();
|
|
```
|
|
|
|
[Macros by Example]: macros-by-example.md
|
|
[Procedural Macros]: procedural-macros.md
|
|
[_SimplePath_]: paths.md#simple-paths
|
|
[_Token_]: tokens.md
|
|
[associated items]: items/associated-items.md
|
|
[delimiters]: tokens.md#delimiters
|
|
[expressions]: expressions.md
|
|
[items]: items.md
|
|
[`macro_rules`]: macros-by-example.md
|
|
[patterns]: patterns.md
|
|
[statements]: statements.md
|
|
[types]: types.md
|
|
[visibility qualifiers]: visibility-and-privacy.md
|
|
[External blocks]: items/external-blocks.md
|