I want to write a macro that prints "OK" then returns self in a method. It's my first macro, so I tried this, thinking it will just make something like a text replacement, but it fails:
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:
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!()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
After a quick look at the documentation, I know it's not just text replacement, but I still don't know how to make it work.
There are two errors in a row, let's fix the first one.
The syntax for a macro arm is:
(...) => {
...
}
which means that what your macro expands to is:
println!("OK");
self
which is not OK (two statements).
Instead, it should expand to an expression (in this case), which you get by enclosing it within {}
:
macro_rules! print_ok_and_return_self {
() => {
{
println!("OK");
self
}
}
}
This leads to the second error:
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?
A macro cannot assume the existence of a variable in its scope, so you need to pass self
as an argument:
macro_rules! print_ok_and_return_value {
($v:expr) => {{
println!("OK");
$v
}}
}
and the invocation becomes:
impl A {
fn a(self) -> Self {
print_ok_and_return_value!(self)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With