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

Unable to use self in macro because the macro expansion ignores token `self`

我想编写一个宏,在方法中打印 "OK" 然后 returns 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!()
  |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^

快速查看文档后,我知道这不仅仅是文本替换,但我仍然不知道如何使其工作。

连续出现两个错误,我们修正第一个吧。

宏臂的语法是:

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

这意味着您的宏扩展为:

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)
    }
}