How to Get the Macro Called File Path in a Rust Procedural Macro?

I am working on a Rust project that involves writing a procedural macro, which need to get the relative file path where the macro is invoked. For example, let's say I have the following code structure:


// /src/some_file/mod.rs

use other_crate::my_proc_macro;

my_proc_macro!(file1);

In this case, I want my_proc_macro could detect the calling path /src/some_file/mod.rs during the macro parsing.

I found std::env::current_dir().unwrap().join(file!()) could get the path of a file, but it's the procedural macro file path, not the user code caller's file path.

How can I get the caller's file path in a Rust procedural macro? Is it not feasible yet?

(You may wonder why needs this path info. In my case, there is more than 1 macros, the information of the caller's file path from 1 macro is used to determine another macro's behavior--- this mechanism is somehow used in enum_dispatch)

Hacky, but you could have wrapper macro that calls my_proc_macro with file!(), sth like this

macro_rules! wrapper {($f:ident)=>{my_proc_macro!($f, file!())}};

1 Like

Thanks your feedback, but I guess this is not suitable in my case. What I want is that , 1 macor(say Macro_a) would produce some code for a hidden trait. Anthor trait (say Macro_b) would be used like #[Macro_b(hidden_trait_name)].

Usually but not always, the Macro_b would be used in another file, compared with the Macro_a, and I want the hidden trait totally transparent to users, which means users should not add use .... hidden_trait_name; explicitly---That is why I want to know the caller file path.

If this is not feasible, I wonder if there is a way that could make a trait available to the whole crate just like #[macro_export] does for a declarative macro.

This is the correct way to do so, which should be done like this:

#[proc_macro]
pub fn example_macro(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    // Get the `Span` where the macro was called
    let span = proc_macro::Span::call_site();

    // Use the `Span` to get the `SourceFile`
    let source_file = span.source_file();

    // Get the path of the `SourceFile`
    let path: PathBuf = source_file.path();

    // Now you can use the file path for further processing
    // ...

    // Return the original input for this example
    input
}

But since fn source_file is not stable both for proc_macro and proc_macro2, I finally take a workaround as this github comment said.

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.