Skip to content

Commit 0808f92

Browse files
committed
[wip] reference: rework Macros section
Rearrange and add content to the Macros section to make it more informative and useful.
1 parent f6e125f commit 0808f92

File tree

1 file changed

+40
-21
lines changed

1 file changed

+40
-21
lines changed

src/doc/reference.md

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -555,28 +555,45 @@ Users of `rustc` can define new syntax extensions in two ways:
555555

556556
## Macros
557557

558-
`macro_rules` allows users to define syntax extension in a declarative way. We
559-
call such extensions "macros by example" or simply "macros" — to be distinguished
560-
from the "procedural macros" defined in [compiler plugins][plugin].
558+
`macro_rules` allows users to define syntax extensions in a declarative way.
559+
We call such extensions "macros by example" or simply "macros" — to be
560+
distinguished from the "procedural macros" defined in [compiler plugins][plugin].
561561

562-
Currently, macros can expand to expressions, statements, items, or patterns.
562+
As shown below, the body of a `macro_rules` macro consists of one or more
563+
semicolon-separated arms, similar in appearance to a `match` statement. On
564+
the left side of the `=>` is a matcher describing the syntax that the macro
565+
accepts, optionally capturing parts of it for use in the transcriber, which
566+
is on the right side of the `=>`. (Choice of delimiters for the macro body,
567+
matchers, and transcribers is arbitrary.)
563568

564-
(A `sep_token` is any token other than `*` and `+`. A `non_special_token` is
565-
any token other than a delimiter or `$`.)
569+
```rust,ignore
570+
macro_rules! /* name of macro */ {
571+
(/* matcher for arm 1 */) => { /* transcriber for arm 1 */ };
572+
(/* matcher for arm 2 */) => { /* transcriber for arm 2 */ }
573+
}
574+
```
566575

567-
The macro expander looks up macro invocations by name, and tries each macro
568-
rule in turn. It transcribes the first successful match. Matching and
576+
Currently, macros can expand to expressions, statements, items, patterns, or
577+
types[^typemacros]. This distinction is inferred from the context in which the
578+
macro is invoked, and carefully written macros may work in multiple contexts.
579+
580+
[^typemacros]: Gated by
581+
[the `type_macros` feature](https://github.com/rust-lang/rust/issues/27245).
582+
583+
The macro expander looks up macro invocations by name, and tries each
584+
arm in turn. It transcribes the first successful match. Matching and
569585
transcription are closely related to each other, and we will describe them
570586
together.
571587

572-
### Macro By Example
588+
### Macros By Example
573589

574590
The macro expander matches and transcribes every token that does not begin with
575591
a `$` literally, including delimiters. For parsing reasons, delimiters must be
576592
balanced, but they are otherwise not special.
577593

578594
In the matcher, `$` _name_ `:` _designator_ matches the nonterminal in the Rust
579-
syntax named by _designator_. Valid designators are:
595+
syntax named by _designator_ (also called a _fragment specifier_). Valid
596+
designators are:
580597

581598
* `item`: an [item](#items)
582599
* `block`: a [block](#block-expressions)
@@ -586,36 +603,36 @@ syntax named by _designator_. Valid designators are:
586603
* `ty`: a [type](#types)
587604
* `ident`: an [identifier](#identifiers)
588605
* `path`: a [path](#paths)
589-
* `tt`: either side of the `=>` in macro rules
606+
* `tt`: a "token tree": either one [token](#token) or a delimited sequence
607+
of token trees
590608
* `meta`: the contents of an [attribute](#attributes)
591609

592-
In the transcriber, the
593-
designator is already known, and so only the name of a matched nonterminal comes
594-
after the dollar sign.
610+
In the transcriber, the designator is already known, and so only the name of a matched
611+
nonterminal comes after the dollar sign.
595612

596-
In both the matcher and transcriber, the Kleene star-like operator indicates
613+
In both the matcher and transcriber, the Kleene star operator indicates
597614
repetition. The Kleene star operator consists of `$` and parentheses, optionally
598615
followed by a separator token, followed by `*` or `+`. `*` means zero or more
599-
repetitions, `+` means at least one repetition. The parentheses are not matched or
616+
repetitions; `+` means at least one repetition. The parentheses are not matched or
600617
transcribed. On the matcher side, a name is bound to _all_ of the names it
601618
matches, in a structure that mimics the structure of the repetition encountered
602619
on a successful match. The job of the transcriber is to sort that structure
603620
out.
604621

605-
The rules for transcription of these repetitions are called "Macro By Example".
622+
The rules for transcription of these repetitions are called "Macros By Example".
606623
Essentially, one "layer" of repetition is discharged at a time, and all of them
607624
must be discharged by the time a name is transcribed. Therefore, `( $( $i:ident
608-
),* ) => ( $i )` is an invalid macro, but `( $( $i:ident ),* ) => ( $( $i:ident
609-
),* )` is acceptable (if trivial).
625+
),* ) => ( $i )` is an invalid macro, but `( $( $i:ident ),* ) => ( $( $i ),* )`
626+
is acceptable (though trivial).
610627

611-
When Macro By Example encounters a repetition, it examines all of the `$`
628+
When Macros By Example encounters a repetition, it examines all of the `$`
612629
_name_ s that occur in its body. At the "current layer", they all must repeat
613630
the same number of times, so ` ( $( $i:ident ),* ; $( $j:ident ),* ) => ( $(
614631
($i,$j) ),* )` is valid if given the argument `(a,b,c ; d,e,f)`, but not
615632
`(a,b,c ; d,e)`. The repetition walks through the choices at that layer in
616633
lockstep, so the former input transcribes to `(a,d), (b,e), (c,f)`.
617634

618-
Nested repetitions are allowed.
635+
Nested repetitions are allowed. In the transcriber, `*` vs `+` does not matter.
619636

620637
### Parsing limitations
621638

@@ -634,6 +651,8 @@ Rust syntax is restricted in two ways:
634651

635652
[RFC 550]: https://github.com/rust-lang/rfcs/blob/master/text/0550-macro-future-proofing.md
636653

654+
### Scoping
655+
637656
# Crates and source files
638657

639658
Although Rust, like any other language, can be implemented by an interpreter as

0 commit comments

Comments
 (0)