Skip to content

Commit 41e5c78

Browse files
authored
Merge pull request #1169 from petrochenkov/procmacrotokens
Document compatibility between declarative and procedural macro tokens
2 parents 6acced7 + 26acee2 commit 41e5c78

File tree

1 file changed

+61
-0
lines changed

1 file changed

+61
-0
lines changed

src/procedural-macros.md

+61
Original file line numberDiff line numberDiff line change
@@ -271,12 +271,73 @@ fn invoke4() {}
271271
// out: item: "fn invoke4() {}"
272272
```
273273

274+
### Declarative macro tokens and procedural macro tokens
275+
276+
Declarative `macro_rules` macros and procedural macros use similar, but
277+
different definitions for tokens (or rather [`TokenTree`s].)
278+
279+
Token trees in `macro_rules` (corresponding to `tt` matchers) are defined as
280+
- Delimited groups (`(...)`, `{...}`, etc)
281+
- All operators supported by the language, both single-character and
282+
multi-character ones (`+`, `+=`).
283+
- Note that this set doesn't include the single quote `'`.
284+
- Literals (`"string"`, `1`, etc)
285+
- Note that negation (e.g. `-1`) is never a part of such literal tokens,
286+
but a separate operator token.
287+
- Identifiers, including keywords (`ident`, `r#ident`, `fn`)
288+
- Lifetimes (`'ident`)
289+
- Metavariable substitutions in `macro_rules` (e.g. `$my_expr` in
290+
`macro_rules! mac { ($my_expr: expr) => { $my_expr } }` after the `mac`'s
291+
expansion, which will be considered a single token tree regardless of the
292+
passed expression)
293+
294+
Token trees in procedural macros are defined as
295+
- Delimited groups (`(...)`, `{...}`, etc)
296+
- All punctuation characters used in operators supported by the language (`+`,
297+
but not `+=`), and also the single quote `'` character (typically used in
298+
lifetimes, see below for lifetime splitting and joining behavior)
299+
- Literals (`"string"`, `1`, etc)
300+
- Negation (e.g. `-1`) is supported as a part of integer
301+
and floating point literals.
302+
- Identifiers, including keywords (`ident`, `r#ident`, `fn`)
303+
304+
Mismatches between these two definitions are accounted for when token streams
305+
are passed to and from procedural macros. \
306+
Note that the conversions below may happen lazily, so they might not happen if
307+
the tokens are not actually inspected.
308+
309+
When passed to a proc-macro
310+
- All multi-character operators are broken into single characters.
311+
- Lifetimes are broken into a `'` character and an identifier.
312+
- All metavariable substitutions are represented as their underlying token
313+
streams.
314+
- Such token streams may be wrapped into delimited groups ([`Group`]) with
315+
implicit delimiters ([`Delimiter::None`]) when it's necessary for
316+
preserving parsing priorities.
317+
- `tt` and `ident` substitutions are never wrapped into such groups and
318+
always represented as their underlying token trees.
319+
320+
When emitted from a proc macro
321+
- Punctuation characters are glued into multi-character operators
322+
when applicable.
323+
- Single quotes `'` joined with identifiers are glued into lifetimes.
324+
- Negative literals are converted into two tokens (the `-` and the literal)
325+
possibly wrapped into a delimited group ([`Group`]) with implicit delimiters
326+
([`Delimiter::None`]) when it's necessary for preserving parsing priorities.
327+
328+
Note that neither declarative nor procedural macros support doc comment tokens
329+
(e.g. `/// Doc`), so they are always converted to token streams representing
330+
their equivalent `#[doc = r"str"]` attributes when passed to macros.
331+
274332
[Attribute macros]: #attribute-macros
275333
[Cargo's build scripts]: ../cargo/reference/build-scripts.html
276334
[Derive macros]: #derive-macros
277335
[Function-like macros]: #function-like-procedural-macros
336+
[`Delimiter::None`]: ../proc_macro/enum.Delimiter.html#variant.None
337+
[`Group`]: ../proc_macro/struct.Group.html
278338
[`TokenStream`]: ../proc_macro/struct.TokenStream.html
279339
[`TokenStream`s]: ../proc_macro/struct.TokenStream.html
340+
[`TokenTree`s]: ../proc_macro/enum.TokenTree.html
280341
[`compile_error`]: ../std/macro.compile_error.html
281342
[`derive` attribute]: attributes/derive.md
282343
[`extern` blocks]: items/external-blocks.md

0 commit comments

Comments
 (0)