I'm looking for the equivalent of file!()
& module_path!()
in a procedural macro context.
For example, the following doesn't work:
file.rs
:
#[some_attribute]
const A: bool = true;
macro.rs
:
#[proc_macro_attribute]
pub fn some_attribute(attr: TokenStream, input: TokenStream) -> TokenStream {
println!("{}", file!());
input
}
This prints macro.rs
which makes sense, but what I want is file.rs
. Is there a way to achieve this? Is there also a similar way for module_path!()
?
A requirement of this is that has to happen at compile-time.
I'm trying to create a file in the OUT_DIR
containing constant values where the attribute is added with the module and the file that they are in.
I had the same problem and found out that Rust added a new experimential API to Rust macros (#54725) which allows exactly what you want:
#![feature(proc_macro_span)]
#[proc_macro]
pub(crate) fn do_something(item: TokenStream) -> TokenStream {
let span = Span::call_site();
let source = span.source_file();
format!("println!(r#\"Path: {}\"#)", source.path().to_str().unwrap())
.parse()
.unwrap()
}
use my_macro_crate::*;
fn main() {
println!("Hello, world!");
do_something!();
}
Will output:
Hello, world!
Path: src\main.rs
Apart from this API being experimential, the path might not be a real OS path. This can be the case if the Span
was generated by a macro. Visit the documentation here.