首页 文章

无法在宏中使用self,因为宏扩展忽略了令牌“self”

提问于
浏览
7

我想写一个打印“OK”然后在方法中返回self的宏 . 这是我的第一个宏,所以我尝试了这个,认为它会像文本替换一样,但它失败了:

macro_rules! print_ok_and_return_self {
    () => {
        println!("OK");
        self
    }
}

fn main() {
    let a = A{};
    a.a().a();
}

struct A {}

impl A {
    fn a(self) -> Self {
        print_ok_and_return_self!()
    }
}

错误:

error: macro expansion ignores token `self` and any following
 --> src/main.rs:4:13
  |
4 |             self
  |             ^^^^
  |
note: caused by the macro expansion here; the usage of `print_ok_and_return_self!` is likely invalid in expression context
 --> src/main.rs:17:13
  |
17|             print_ok_and_return_self!()
  |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^

快速浏览一下文档后,我知道它不仅仅是文本替换,而且我仍然不知道如何使它工作 .

1 回答

  • 13

    连续有两个错误,让我们修复第一个错误 .

    宏臂的语法是:

    (...) => {
        ...
    }
    

    这意味着你的宏花费的是:

    println!("OK");
    self
    

    哪个不好(两个陈述) .

    相反,它应该扩展为一个表达式(在这种情况下),你可以将它包含在 {} 中:

    macro_rules! print_ok_and_return_self {
        () => {
            {
                println!("OK");
                self
            }
        }
    }
    

    这导致第二个错误:

    error[E0424]: `self` is not available in a static method
      --> <anon>:4:9
       |
    4  |         self
       |         ^^^^ not available in static method
    ...
    17 |         print_ok_and_return_self!()
       |         --------------------------- in this macro invocation
       |
       = note: maybe a `self` argument is missing?
    

    宏不能假设其范围中存在变量,因此您需要将 self 作为参数传递:

    macro_rules! print_ok_and_return_value {
        ($v:expr) => {{
            println!("OK");
            $v
        }}
    }
    

    并且调用变为:

    impl A {
        fn a(self) -> Self {
            print_ok_and_return_value!(self)
        }
    }
    

相关问题