@@ -271,12 +271,73 @@ fn invoke4() {}
271
271
// out: item: "fn invoke4() {}"
272
272
```
273
273
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
+
274
332
[ Attribute macros ] : #attribute-macros
275
333
[ Cargo's build scripts ] : ../cargo/reference/build-scripts.html
276
334
[ Derive macros ] : #derive-macros
277
335
[ Function-like macros ] : #function-like-procedural-macros
336
+ [ `Delimiter::None` ] : ../proc_macro/enum.Delimiter.html#variant.None
337
+ [ `Group` ] : ../proc_macro/struct.Group.html
278
338
[ `TokenStream` ] : ../proc_macro/struct.TokenStream.html
279
339
[ `TokenStream`s ] : ../proc_macro/struct.TokenStream.html
340
+ [ `TokenTree`s ] : ../proc_macro/enum.TokenTree.html
280
341
[ `compile_error` ] : ../std/macro.compile_error.html
281
342
[ `derive` attribute ] : attributes/derive.md
282
343
[ `extern` blocks ] : items/external-blocks.md
0 commit comments