Description
I have some macros that mostly just print their inputs:
procedural/src/lib.rs (edition = 2015 or 2018)
extern crate proc_macro;
use proc_macro::TokenStream;
#[proc_macro]
pub fn m(input: TokenStream) -> TokenStream {
println!("PROC MACRO INPUT: {}", input);
input.into_iter().collect()
}
#[proc_macro_attribute]
pub fn a(_args: TokenStream, input: TokenStream) -> TokenStream {
println!("ATTRIBUTE INPUT: {}", input);
input //.into_iter().collect() // emits invalid code if uncommented
}
#[proc_macro_derive(d)]
pub fn d(input: TokenStream) -> TokenStream {
println!("DERIVE INPUT: {}", input);
TokenStream::new()
}
And I invoke them each from a 2018 crate:
repro/src/main.rs (edition = 2018)
#![allow(dead_code)]
type S = bool;
macro_rules! m {
() => {
procedural::m! {
struct M($crate::S);
}
#[procedural::a]
struct A($crate::S);
#[derive(procedural::d)]
struct D($crate::S);
};
}
m!();
fn main() {}
The unexpected output is:
PROC MACRO INPUT: struct M ( $crate :: S ) ;
ATTRIBUTE INPUT: struct A(::S);
DERIVE INPUT: struct D(::S);
The attribute macro and derive macro inputs are missing the $crate. The $crate is missing both from the to_string() representation as well as when iterating over the TokenStream.
If you uncomment the commented half line in procedural::a, the downstream crate fails to compile.
error[E0412]: cannot find type `S` in the crate root
help: possible candidate is found in another module, you can import it into scope
|
1 | use crate::S;
|
error: aborting due to previous error
I think this means procedural macros can't in general emit correct code when invoked from a 2018 edition crate with $crate in the input item.
If we really don't want to pass $crate through in the macro input, then it needs to decay to crate
if it is from a 2018 crate. (You know how in 2015 we have $crate conceptually replaced by either nothing or the crate name, depending on whether the use is from the same crate or from a different crate. In 2018 we need this to be crate
or the crate name.)
Mentioning @jimmycuadra who reported this in serde-rs/serde#1440.
Mentioning @petrochenkov @eddyb @alexcrichton for thoughts.