Search code examples
rustrust-macrosrust-proc-macros

Cannot call a function-like procedural macro: cannot be expanded to statements


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


Solution

  • 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.