Почему этот макрос приводит к неразрешенной ошибке имени?
Я хотел бы скомпилировать код, похожий на этот минимальный тестовый пример:
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
в области на сайте вызова.