I'm trying to get my head around function-like procedural macros and struggling with the basics.
For a starter, I tried to create a macro that just prints all the tokens and does nothing:
extern crate proc_macro;
extern crate syn;
use proc_macro::TokenStream;
#[proc_macro]
pub fn my_macro(input: TokenStream) -> TokenStream {
println!( "{:?}", input );
TokenStream::new()
}
I then tried to use it in another binary:
extern crate rust_procmacro_test;
fn main() {
rust_procmacro_test::my_macro!( aaa );
}
When I do cargo build
I get this:
Compiling rust_procmacro_test v0.1.0
Compiling procmacro_user v0.1.0
error[E0658]: procedural macros cannot be expanded to statements (see issue #54727)
--> src\main.rs:5:5
|
5 | rust_procmacro_test::my_macro!( aaa );
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TokenStream [Ident { ident: "aaa", span: #0 bytes(114..117) }]
error: aborting due to previous error
It tells me that this cannot be compiled, but println
inside the macro works. What is happening?
Issue #54727 is very broad and I'm not sure how it relates to this.
I'm using stable-i686-pc-windows-gnu, rustc 1.31.1 (b6c32da9b 2018-12-18).
What is happening?
While it's possible to define a function-like procedural macro in stable Rust, it's not yet possible to call one as an expression / statement. This is because there are concerns about how hygiene should be applied. There are other locations, such as in item position, where it is available:
extern crate rust_procmacro_test;
rust_procmacro_test::my_macro!( aaa );
fn main() {}
but
println
inside the macro works
This is probably just some laziness in the implementation — the macro is eagerly evaluated and then the feature gate is checked later. While this might be inefficient at the moment, once the feature is fully stabilized it won't matter.