Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does the tt metavariable type mean in Rust macros?

I'm reading a book about Rust, and start playing with Rust macros. All metavariable types are explained there and have examples, except the last one – tt. According to the book, it is a “a single token tree”. I'm curious, what is it and what is it used for? Can you please provide an example?

like image 295
Pavel Davydov Avatar asked Oct 28 '16 09:10

Pavel Davydov


People also ask

How do macros work in Rust?

Rust has excellent support for macros. Macros enable you to write code that writes other code, which is known as metaprogramming. Macros provide functionality similar to functions but without the runtime cost. There is some compile-time cost, however, since macros are expanded during compile time.

Can you use macros on Rust?

The most widely used form of macros in Rust is the declarative macro. These are also sometimes referred to as “macros by example,” “ macro_rules! macros,” or just plain “macros.” At their core, declarative macros allow you to write something similar to a Rust match expression.

What is Macro_rules?

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.


1 Answers

That's a notion introduced to ensure that whatever is in a macro invocation correctly matches (), [] and {} pairs. tt will match any single token or any pair of parenthesis/brackets/braces with their content.

For example, for the following program:

fn main() {     println!("Hello world!"); } 

The token trees would be:

  • fn
  • main
  • ()
  • { println!("Hello world!"); }
    • println
    • !
    • ("Hello world!")
      • "Hello world!"
    • ;

Each one forms a tree where simple tokens (fn, main etc.) are leaves, and anything surrounded by (), [] or {} has a subtree. Note that ( does not appear alone in the token tree: it's not possible to match ( without matching the corresponding ).

For example:

macro_rules! {     (fn $name:ident $params:tt $body:tt) => { /* … */ } } 

would match the above function with $name → main, $params → (), $body → { println!("Hello world!"); }.

Token tree is the least demanding metavariable type: it matches anything. It's often used in macros which have a “don't really care” part, and especially in macros which have a “head” and a “tail” part. For example, the println! macros have a branch matching ($fmt:expr, $($arg:tt)*) where $fmt is the format string, and $($arg:tt)* means “all the rest” and is just forwarded to format_args!. Which means that println! does not need to know the actual format and do complicated matching with it.

like image 120
mcarton Avatar answered Oct 02 '22 00:10

mcarton