Почему этот макрос приводит к неразрешенной ошибке имени?

Я хотел бы скомпилировать код, похожий на этот минимальный тестовый пример:

macro_rules! why {
    ( [ $saved:ident ] $body:block ) => {
        let $saved = 3;
        $body
        let _a = $saved;
    }
}

fn bar() {
    why!([saved] {
    });
}

fn main() {
}

Когда я пытаюсь скомпилировать его, я получаю следующую ошибку:

src/main.rs:10:20: 10:21 error: unresolved name `saved` [E0425]
src/main.rs:10         why!([saved] {
                                  ^
src/main.rs:10:9: 11:12 note: in this expansion of why! (defined in src/main.rs)
src/main.rs:10:20: 10:21 help: run `rustc --explain E0425` to see a detailed explanation

Другие макросы, которые вводят переменные, работают; в чем здесь проблема?

2 ответа

Решение

Это потому что macro_rules! что-то не так, когда речь идет о макросах, которые расширяются до операторов.

Проблема в основном в том, что он рассматривает каждое утверждение независимо в целях гигиены. Другими словами, третье утверждение буквально не может видеть привязку, определенную в первой строке.

В некоторых случаях вы можете обойти это, обернув операторы в блок:

macro_rules! why {
    ( [ $saved:ident ] $body:block ) => {
        {
            let $saved = 3;
            $body
            let _a = $saved;
        }
    }
}

Ваш fn bar не имеет ничего по имени saved в области на сайте вызова.

Другие вопросы по тегам