| # Macros By Example |
| |
| > **<sup>Syntax</sup>**\ |
| > _MacroRulesDefinition_ :\ |
| > `macro_rules` `!` [IDENTIFIER] _MacroRulesDef_ |
| > |
| > _MacroRulesDef_ :\ |
| > `(` _MacroRules_ `)` `;`\ |
| > | `[` _MacroRules_ `]` `;`\ |
| > | `{` _MacroRules_ `}` |
| > |
| > _MacroRules_ :\ |
| > _MacroRule_ ( `;` _MacroRule_ )<sup>\*</sup> `;`<sup>?</sup> |
| > |
| > _MacroRule_ :\ |
| > _MacroMatcher_ `=>` _MacroTranscriber_ |
| > |
| > _MacroMatcher_ :\ |
| > `(` _MacroMatch_<sup>\*</sup> `)`\ |
| > | `[` _MacroMatch_<sup>\*</sup> `]`\ |
| > | `{` _MacroMatch_<sup>\*</sup> `}` |
| > |
| > _MacroMatch_ :\ |
| > [_Token_]<sub>_except `$` and [delimiters]_</sub>\ |
| > | _MacroMatcher_\ |
| > | `$` ( [IDENTIFIER_OR_KEYWORD] <sub>_except `crate`_</sub> | [RAW_IDENTIFIER] | `_` ) `:` _MacroFragSpec_\ |
| > | `$` `(` _MacroMatch_<sup>+</sup> `)` _MacroRepSep_<sup>?</sup> _MacroRepOp_ |
| > |
| > _MacroFragSpec_ :\ |
| > `block` | `expr` | `ident` | `item` | `lifetime` | `literal`\ |
| > | `meta` | `pat` | `pat_param` | `path` | `stmt` | `tt` | `ty` | `vis` |
| > |
| > _MacroRepSep_ :\ |
| > [_Token_]<sub>_except [delimiters] and MacroRepOp_</sub> |
| > |
| > _MacroRepOp_ :\ |
| > `*` | `+` | `?` |
| > |
| > _MacroTranscriber_ :\ |
| > [_DelimTokenTree_] |
| |
| `macro_rules` allows users to define syntax extension in a declarative way. We |
| call such extensions "macros by example" or simply "macros". |
| |
| Each macro by example has a name, and one or more _rules_. Each rule has two |
| parts: a _matcher_, describing the syntax that it matches, and a _transcriber_, |
| describing the syntax that will replace a successfully matched invocation. Both |
| the matcher and the transcriber must be surrounded by delimiters. Macros can |
| expand to expressions, statements, items (including traits, impls, and foreign |
| items), types, or patterns. |
| |
| ## Transcribing |
| |
| When a macro is invoked, the macro expander looks up macro invocations by name, |
| and tries each macro rule in turn. It transcribes the first successful match; if |
| this results in an error, then future matches are not tried. When matching, no |
| lookahead is performed; if the compiler cannot unambiguously determine how to |
| parse the macro invocation one token at a time, then it is an error. In the |
| following example, the compiler does not look ahead past the identifier to see |
| if the following token is a `)`, even though that would allow it to parse the |
| invocation unambiguously: |
| |
| ```rust,compile_fail |
| macro_rules! ambiguity { |
| ($($i:ident)* $j:ident) => { }; |
| } |
| |
| ambiguity!(error); // Error: local ambiguity |
| ``` |
| |
| In both the matcher and the transcriber, the `$` token is used to invoke special |
| behaviours from the macro engine (described below in [Metavariables] and |
| [Repetitions]). Tokens that aren't part of such an invocation are matched and |
| transcribed literally, with one exception. The exception is that the outer |
| delimiters for the matcher will match any pair of delimiters. Thus, for |
| instance, the matcher `(())` will match `{()}` but not `{{}}`. The character |
| `$` cannot be matched or transcribed literally. |
| |
| ### Forwarding a matched fragment |
| |
| When forwarding a matched fragment to another macro-by-example, matchers in |
| the second macro will see an opaque AST of the fragment type. The second macro |
| can't use literal tokens to match the fragments in the matcher, only a |
| fragment specifier of the same type. The `ident`, `lifetime`, and `tt` |
| fragment types are an exception, and *can* be matched by literal tokens. The |
| following illustrates this restriction: |
| |
| ```rust,compile_fail |
| macro_rules! foo { |
| ($l:expr) => { bar!($l); } |
| // ERROR: ^^ no rules expected this token in macro call |
| } |
| |
| macro_rules! bar { |
| (3) => {} |
| } |
| |
| foo!(3); |
| ``` |
| |
| The following illustrates how tokens can be directly matched after matching a |
| `tt` fragment: |
| |
| ```rust |
| // compiles OK |
| macro_rules! foo { |
| ($l:tt) => { bar!($l); } |
| } |
| |
| macro_rules! bar { |
| (3) => {} |
| } |
| |
| foo!(3); |
| ``` |
| |
| ## Metavariables |
| |
| In the matcher, `$` _name_ `:` _fragment-specifier_ matches a Rust syntax |
| fragment of the kind specified and binds it to the metavariable `$`_name_. Valid |
| fragment specifiers are: |
| |
| * `item`: an [_Item_] |
| * `block`: a [_BlockExpression_] |
| * `stmt`: a [_Statement_] without the trailing semicolon (except for item |
| statements that require semicolons) |
| * `pat_param`: a [_PatternNoTopAlt_] |
| * `pat`: at least any [_PatternNoTopAlt_], and possibly more depending on edition |
| * `expr`: an [_Expression_] |
| * `ty`: a [_Type_] |
| * `ident`: an [IDENTIFIER_OR_KEYWORD] or [RAW_IDENTIFIER] |
| * `path`: a [_TypePath_] style path |
| * `tt`: a [_TokenTree_] (a single [token] or tokens in matching delimiters `()`, `[]`, or `{}`) |
| * `meta`: an [_Attr_], the contents of an attribute |
| * `lifetime`: a [LIFETIME_TOKEN] |
| * `vis`: a possibly empty [_Visibility_] qualifier |
| * `literal`: matches `-`<sup>?</sup>[_LiteralExpression_] |
| |
| In the transcriber, metavariables are referred to simply by `$`_name_, since |
| the fragment kind is specified in the matcher. Metavariables are replaced with |
| the syntax element that matched them. The keyword metavariable `$crate` can be |
| used to refer to the current crate; see [Hygiene] below. Metavariables can be |
| transcribed more than once or not at all. |
| |
| For reasons of backwards compatibility, though `_` [is also an |
| expression][_UnderscoreExpression_], a standalone underscore is not matched by |
| the `expr` fragment specifier. However, `_` is matched by the `expr` fragment |
| specifier when it appears as a subexpression. |
| For the same reason, a standalone [const block] is not matched but it is matched when appearing as a subexpression. |
| |
| > **Edition Differences**: Starting with the 2021 edition, `pat` fragment-specifiers match top-level or-patterns (that is, they accept [_Pattern_]). |
| > |
| > Before the 2021 edition, they match exactly the same fragments as `pat_param` (that is, they accept [_PatternNoTopAlt_]). |
| > |
| > The relevant edition is the one in effect for the `macro_rules!` definition. |
| |
| ## Repetitions |
| |
| In both the matcher and transcriber, repetitions are indicated by placing the |
| tokens to be repeated inside `$(`…`)`, followed by a repetition operator, |
| optionally with a separator token between. The separator token can be any token |
| other than a delimiter or one of the repetition operators, but `;` and `,` are |
| the most common. For instance, `$( $i:ident ),*` represents any number of |
| identifiers separated by commas. Nested repetitions are permitted. |
| |
| The repetition operators are: |
| |
| - `*` --- indicates any number of repetitions. |
| - `+` --- indicates any number but at least one. |
| - `?` --- indicates an optional fragment with zero or one occurrence. |
| |
| Since `?` represents at most one occurrence, it cannot be used with a |
| separator. |
| |
| The repeated fragment both matches and transcribes to the specified number of |
| the fragment, separated by the separator token. Metavariables are matched to |
| every repetition of their corresponding fragment. For instance, the `$( $i:ident |
| ),*` example above matches `$i` to all of the identifiers in the list. |
| |
| During transcription, additional restrictions apply to repetitions so that the |
| compiler knows how to expand them properly: |
| |
| 1. A metavariable must appear in exactly the same number, kind, and nesting |
| order of repetitions in the transcriber as it did in the matcher. So for the |
| matcher `$( $i:ident ),*`, the transcribers `=> { $i }`, |
| `=> { $( $( $i)* )* }`, and `=> { $( $i )+ }` are all illegal, but |
| `=> { $( $i );* }` is correct and replaces a comma-separated list of |
| identifiers with a semicolon-separated list. |
| 2. Each repetition in the transcriber must contain at least one metavariable to |
| decide how many times to expand it. If multiple metavariables appear in the |
| same repetition, they must be bound to the same number of fragments. For |
| instance, `( $( $i:ident ),* ; $( $j:ident ),* ) => (( $( ($i,$j) ),* ))` must |
| bind the same number of `$i` fragments as `$j` fragments. This means that |
| invoking the macro with `(a, b, c; d, e, f)` is legal and expands to |
| `((a,d), (b,e), (c,f))`, but `(a, b, c; d, e)` is illegal because it does |
| not have the same number. This requirement applies to every layer of nested |
| repetitions. |
| |
| ## Scoping, Exporting, and Importing |
| |
| For historical reasons, the scoping of macros by example does not work entirely |
| like items. Macros have two forms of scope: textual scope, and path-based scope. |
| Textual scope is based on the order that things appear in source files, or even |
| across multiple files, and is the default scoping. It is explained further below. |
| Path-based scope works exactly the same way that item scoping does. The scoping, |
| exporting, and importing of macros is controlled largely by attributes. |
| |
| When a macro is invoked by an unqualified identifier (not part of a multi-part |
| path), it is first looked up in textual scoping. If this does not yield any |
| results, then it is looked up in path-based scoping. If the macro's name is |
| qualified with a path, then it is only looked up in path-based scoping. |
| |
| <!-- ignore: requires external crates --> |
| ```rust,ignore |
| use lazy_static::lazy_static; // Path-based import. |
| |
| macro_rules! lazy_static { // Textual definition. |
| (lazy) => {}; |
| } |
| |
| lazy_static!{lazy} // Textual lookup finds our macro first. |
| self::lazy_static!{} // Path-based lookup ignores our macro, finds imported one. |
| ``` |
| |
| ### Textual Scope |
| |
| Textual scope is based largely on the order that things appear in source files, |
| and works similarly to the scope of local variables declared with `let` except |
| it also applies at the module level. When `macro_rules!` is used to define a |
| macro, the macro enters the scope after the definition (note that it can still |
| be used recursively, since names are looked up from the invocation site), up |
| until its surrounding scope, typically a module, is closed. This can enter child |
| modules and even span across multiple files: |
| |
| <!-- ignore: requires external modules --> |
| ```rust,ignore |
| //// src/lib.rs |
| mod has_macro { |
| // m!{} // Error: m is not in scope. |
| |
| macro_rules! m { |
| () => {}; |
| } |
| m!{} // OK: appears after declaration of m. |
| |
| mod uses_macro; |
| } |
| |
| // m!{} // Error: m is not in scope. |
| |
| //// src/has_macro/uses_macro.rs |
| |
| m!{} // OK: appears after declaration of m in src/lib.rs |
| ``` |
| |
| It is not an error to define a macro multiple times; the most recent declaration |
| will shadow the previous one unless it has gone out of scope. |
| |
| ```rust |
| macro_rules! m { |
| (1) => {}; |
| } |
| |
| m!(1); |
| |
| mod inner { |
| m!(1); |
| |
| macro_rules! m { |
| (2) => {}; |
| } |
| // m!(1); // Error: no rule matches '1' |
| m!(2); |
| |
| macro_rules! m { |
| (3) => {}; |
| } |
| m!(3); |
| } |
| |
| m!(1); |
| ``` |
| |
| Macros can be declared and used locally inside functions as well, and work |
| similarly: |
| |
| ```rust |
| fn foo() { |
| // m!(); // Error: m is not in scope. |
| macro_rules! m { |
| () => {}; |
| } |
| m!(); |
| } |
| |
| |
| // m!(); // Error: m is not in scope. |
| ``` |
| |
| ### The `macro_use` attribute |
| |
| The *`macro_use` attribute* has two purposes. First, it can be used to make a |
| module's macro scope not end when the module is closed, by applying it to a |
| module: |
| |
| ```rust |
| #[macro_use] |
| mod inner { |
| macro_rules! m { |
| () => {}; |
| } |
| } |
| |
| m!(); |
| ``` |
| |
| Second, it can be used to import macros from another crate, by attaching it to |
| an `extern crate` declaration appearing in the crate's root module. Macros |
| imported this way are imported into the [`macro_use` prelude], not textually, |
| which means that they can be shadowed by any other name. While macros imported |
| by `#[macro_use]` can be used before the import statement, in case of a |
| conflict, the last macro imported wins. Optionally, a list of macros to import |
| can be specified using the [_MetaListIdents_] syntax; this is not supported |
| when `#[macro_use]` is applied to a module. |
| |
| <!-- ignore: requires external crates --> |
| ```rust,ignore |
| #[macro_use(lazy_static)] // Or #[macro_use] to import all macros. |
| extern crate lazy_static; |
| |
| lazy_static!{} |
| // self::lazy_static!{} // Error: lazy_static is not defined in `self` |
| ``` |
| |
| Macros to be imported with `#[macro_use]` must be exported with |
| `#[macro_export]`, which is described below. |
| |
| ### Path-Based Scope |
| |
| By default, a macro has no path-based scope. However, if it has the |
| `#[macro_export]` attribute, then it is declared in the crate root scope and can |
| be referred to normally as such: |
| |
| ```rust |
| self::m!(); |
| m!(); // OK: Path-based lookup finds m in the current module. |
| |
| mod inner { |
| super::m!(); |
| crate::m!(); |
| } |
| |
| mod mac { |
| #[macro_export] |
| macro_rules! m { |
| () => {}; |
| } |
| } |
| ``` |
| |
| Macros labeled with `#[macro_export]` are always `pub` and can be referred to |
| by other crates, either by path or by `#[macro_use]` as described above. |
| |
| ## Hygiene |
| |
| By default, all identifiers referred to in a macro are expanded as-is, and are |
| looked up at the macro's invocation site. This can lead to issues if a macro |
| refers to an item or macro which isn't in scope at the invocation site. To |
| alleviate this, the `$crate` metavariable can be used at the start of a path to |
| force lookup to occur inside the crate defining the macro. |
| |
| <!-- ignore: requires external crates --> |
| ```rust,ignore |
| //// Definitions in the `helper_macro` crate. |
| #[macro_export] |
| macro_rules! helped { |
| // () => { helper!() } // This might lead to an error due to 'helper' not being in scope. |
| () => { $crate::helper!() } |
| } |
| |
| #[macro_export] |
| macro_rules! helper { |
| () => { () } |
| } |
| |
| //// Usage in another crate. |
| // Note that `helper_macro::helper` is not imported! |
| use helper_macro::helped; |
| |
| fn unit() { |
| helped!(); |
| } |
| ``` |
| |
| Note that, because `$crate` refers to the current crate, it must be used with a |
| fully qualified module path when referring to non-macro items: |
| |
| ```rust |
| pub mod inner { |
| #[macro_export] |
| macro_rules! call_foo { |
| () => { $crate::inner::foo() }; |
| } |
| |
| pub fn foo() {} |
| } |
| ``` |
| |
| Additionally, even though `$crate` allows a macro to refer to items within its |
| own crate when expanding, its use has no effect on visibility. An item or macro |
| referred to must still be visible from the invocation site. In the following |
| example, any attempt to invoke `call_foo!()` from outside its crate will fail |
| because `foo()` is not public. |
| |
| ```rust |
| #[macro_export] |
| macro_rules! call_foo { |
| () => { $crate::foo() }; |
| } |
| |
| fn foo() {} |
| ``` |
| |
| > **Version & Edition Differences**: Prior to Rust 1.30, `$crate` and |
| > `local_inner_macros` (below) were unsupported. They were added alongside |
| > path-based imports of macros (described above), to ensure that helper macros |
| > did not need to be manually imported by users of a macro-exporting crate. |
| > Crates written for earlier versions of Rust that use helper macros need to be |
| > modified to use `$crate` or `local_inner_macros` to work well with path-based |
| > imports. |
| |
| When a macro is exported, the `#[macro_export]` attribute can have the |
| `local_inner_macros` keyword added to automatically prefix all contained macro |
| invocations with `$crate::`. This is intended primarily as a tool to migrate |
| code written before `$crate` was added to the language to work with Rust 2018's |
| path-based imports of macros. Its use is discouraged in new code. |
| |
| ```rust |
| #[macro_export(local_inner_macros)] |
| macro_rules! helped { |
| () => { helper!() } // Automatically converted to $crate::helper!(). |
| } |
| |
| #[macro_export] |
| macro_rules! helper { |
| () => { () } |
| } |
| ``` |
| |
| ## Follow-set Ambiguity Restrictions |
| |
| The parser used by the macro system is reasonably powerful, but it is limited in |
| order to prevent ambiguity in current or future versions of the language. In |
| particular, in addition to the rule about ambiguous expansions, a nonterminal |
| matched by a metavariable must be followed by a token which has been decided can |
| be safely used after that kind of match. |
| |
| As an example, a macro matcher like `$i:expr [ , ]` could in theory be accepted |
| in Rust today, since `[,]` cannot be part of a legal expression and therefore |
| the parse would always be unambiguous. However, because `[` can start trailing |
| expressions, `[` is not a character which can safely be ruled out as coming |
| after an expression. If `[,]` were accepted in a later version of Rust, this |
| matcher would become ambiguous or would misparse, breaking working code. |
| Matchers like `$i:expr,` or `$i:expr;` would be legal, however, because `,` and |
| `;` are legal expression separators. The specific rules are: |
| |
| * `expr` and `stmt` may only be followed by one of: `=>`, `,`, or `;`. |
| * `pat_param` may only be followed by one of: `=>`, `,`, `=`, `|`, `if`, or `in`. |
| * `pat` may only be followed by one of: `=>`, `,`, `=`, `if`, or `in`. |
| * `path` and `ty` may only be followed by one of: `=>`, `,`, `=`, `|`, `;`, |
| `:`, `>`, `>>`, `[`, `{`, `as`, `where`, or a macro variable of `block` |
| fragment specifier. |
| * `vis` may only be followed by one of: `,`, an identifier other than a |
| non-raw `priv`, any token that can begin a type, or a metavariable with a |
| `ident`, `ty`, or `path` fragment specifier. |
| * All other fragment specifiers have no restrictions. |
| |
| > **Edition Differences**: Before the 2021 edition, `pat` may also be followed by `|`. |
| |
| When repetitions are involved, then the rules apply to every possible number of |
| expansions, taking separators into account. This means: |
| |
| * If the repetition includes a separator, that separator must be able to |
| follow the contents of the repetition. |
| * If the repetition can repeat multiple times (`*` or `+`), then the contents |
| must be able to follow themselves. |
| * The contents of the repetition must be able to follow whatever comes |
| before, and whatever comes after must be able to follow the contents of the |
| repetition. |
| * If the repetition can match zero times (`*` or `?`), then whatever comes |
| after must be able to follow whatever comes before. |
| |
| |
| For more detail, see the [formal specification]. |
| |
| [const block]: expressions/block-expr.md#const-blocks |
| [Hygiene]: #hygiene |
| [IDENTIFIER]: identifiers.md |
| [IDENTIFIER_OR_KEYWORD]: identifiers.md |
| [RAW_IDENTIFIER]: identifiers.md |
| [LIFETIME_TOKEN]: tokens.md#lifetimes-and-loop-labels |
| [Metavariables]: #metavariables |
| [Repetitions]: #repetitions |
| [_Attr_]: attributes.md |
| [_BlockExpression_]: expressions/block-expr.md |
| [_DelimTokenTree_]: macros.md |
| [_Expression_]: expressions.md |
| [_Item_]: items.md |
| [_LiteralExpression_]: expressions/literal-expr.md |
| [_MetaListIdents_]: attributes.md#meta-item-attribute-syntax |
| [_Pattern_]: patterns.md |
| [_PatternNoTopAlt_]: patterns.md |
| [_Statement_]: statements.md |
| [_TokenTree_]: macros.md#macro-invocation |
| [_Token_]: tokens.md |
| [delimiters]: tokens.md#delimiters |
| [_TypePath_]: paths.md#paths-in-types |
| [_Type_]: types.md#type-expressions |
| [_UnderscoreExpression_]: expressions/underscore-expr.md |
| [_Visibility_]: visibility-and-privacy.md |
| [formal specification]: macro-ambiguity.md |
| [token]: tokens.md |
| [`macro_use` prelude]: names/preludes.md#macro_use-prelude |