Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding `tt` in Rust's `macro_rules!` macros

I'm having trouble understanding what exactly a tt is in Rust's macro_rules! macros.

From this answer, I thought that

tt will match any single token or any pair of parenthesis/brackets/braces with their content.

However, the following example does not seem to follow this rule:

macro_rules! foo {
  (content: $content:tt) => {
    mod foo {
      $content
    }
  }
}

foo! (
  content: {
    pub fn main() {
      println!("Hello");
    }  
  }
);

I would expect that the tt would match everything contained in the {} after content: and that the result of the macro invocation would be

mod foo {
  pub fn main() {
    println!("Hello");
  }
}

Instead, I get the following error message:

error: expected item, found `{`
  --> src/main.rs:10:12
   |
10 |   content: {
   |            ^ expected item

What's going wrong here? Also, why does Rust tell me it's expecting an item when I've told it to expect a tt?

like image 727
Greg Owen Avatar asked Jan 18 '26 05:01

Greg Owen


1 Answers

tt is working as expected here. Your macro invocation is as follows:

foo! (
  content: {
    pub fn main() {
      println!("Hello");
    }  
  }
);

$content is this:

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

So, the result is this:

mod foo {
    { // <-- Error occurs here
        pub fn main() {
            println!("Hello");
        }  
    }
}

You cannot have another set of curly braces directly inside of a mod declaration.

The solution to make your code work is to just put $content directly after mod foo, but I presume you already saw that:

macro_rules! foo {
  (content: $content:tt) => {
    mod foo $content
  }
}

foo! (
  content: {
    pub fn main() {
      println!("Hello");
    }  
  }
);

Playground.

like image 114
Optimistic Peach Avatar answered Jan 21 '26 01:01

Optimistic Peach