Понимание `tt` в макросах Rust` macro_rules! ` - PullRequest
2 голосов
/ 29 марта 2020

Мне трудно понять, что именно tt есть в макросах macro_rules! Rust.

От этого ответа , я думал, что

tt будет сопоставлять любой отдельный токен или любую пару скобок / скобок / фигурных скобок с их содержанием.

Однако следующий пример, по-видимому, не следует этому правилу:

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

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

Я ожидаю, что tt будет соответствовать всему, что содержится в {} после content:, и что результатом вызова макроса будет

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

Вместо этого я получаю следующую ошибку сообщение:

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

Что здесь не так? Кроме того, почему Rust говорит мне, что ожидает item, когда я сказал, что он ожидает tt?

1 Ответ

3 голосов
/ 29 марта 2020

tt работает как положено здесь. Ваш макро-вызов выглядит следующим образом:

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

$content это:

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

Итак, результат такой:

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

Вы не можете иметь другой набор фигурных скобок непосредственно внутри объявления mod.

Чтобы заставить ваш код работать, нужно просто поставить $content сразу после mod foo, но я полагаю, вы уже видели, что:

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

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

Playground,

...