12

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.

1 Answer 1

19

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) } } 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.