Proc_macro attribute in cargo build

Hi guys,

I was working on a custom proc_macro attribute, and I have code like this:

#[attribute]
mod mod_name {
   pub fn fn_name(args);
}

The syntax here is that the function only has a signature but no body, which should be an error if you compile. The body will later be populated in my attribute, in which I parse the token stream and rewrite the function with a body.

However, when I compile with cargo build, the free body error is still reported.

Is it that the #[attribute] is not resolved and called in cargo build? Therefore I have to give a body in the function? Or is there a workaround so that I can keep the syntax but compile it successfully?

Thank you so much!

The input to attribute and derive macros needs to be syntactically valid Rust code, so you can't omit the function body like that. Function-like macros (mac!(...)) do not have this restriction.

Actually, fn fun(…) -> …; and thus

mod mod_name {
    pub
    fn fn_name (_: args);
}

is syntactically valid code.

  • (the only issue is that fn fn_name (args)… is not syntactically valid code, even with a function's body, since a function's input needs to be made of self and/or <pat>: <ty> elements)

Btw, for those not knowing about this trick: to know what kind of input is valid to a proc-macro attribute, it suffices to use #[cfg(any())] as a dummy proc-macro placeholder (it "acts" as the empty-expansion / eraser proc-macro attribute). Since the empty expansion is always valid, syntactically, it's an easy way to identify whether a compile error issue lies within the input to the proc-macro being invalid (in which case it would fail even with #[cfg(any())]), or with the output of the proc-macro being invalid (e.g., because it did not amend the code well enough).

  • And for function-like macros (proc_macro! { … }), #[cfg(any())] stringify! { … } does the job. But function-like macros will actually accept any input which can be lexed and which has balanced parenthesis / braces / brackets inside it:

    • some_macro! { ) } :x:

    • some_macro! { ` } :x:

In this instance, thus, the issue necessarily lies within the expansion of your #[attribute]. Try to run cargo expand or println!("{}", ret); (where ret would be the TokenStream about to be returned / emitted by the #[proc_macro_attribute]) to try and identify the culprit:

Since I suspect this to be the problematic step, could you share the code that does this, or the output of such expanded code?

3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.