0
votes

I have a small reproduction project which fails to compile. The project can be downloaded here: https://github.com/Jasperav/proc_macro_collision. The error is:

error[E0659]: `proc_macro_call` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)

I have 3 libraries and 1 executable in the project:

  • Lib 1 - parser - parses the proc macro call
  • Lib 2 - proc_two - returns the literal string as a proc macro call
  • Lib 3 - proc_one - forwards the macro to proc_two (although it does not have a dependency on proc_two). This is like proc_two also a proc macro.

Relevant code for proc_one:

#[proc_macro_hack]
pub fn one(input: TokenStream) -> TokenStream {
    let parse = parse_macro_input!(input as Parser);
    let r = parse.lit;

    let x = quote! {
        two!(#r) // This is the problem I guess...
    };

    x.into()
}
  • Executable: calls proc_one (gives compile error).

Relevant code:

use proc_macro_hack::proc_macro_hack;
extern crate proc_one;
extern crate proc_two;

#[proc_macro_hack]
use proc_one::one;
#[proc_macro_hack]
use proc_two::two;

fn main() {
    let hi: &'static str = one!("hi");

    assert_eq!("hi", hi);
}

I don't understand why the call in the executable is ambiguous, lib 2 and 3 do not dependent on each other. This is the full error:

error[E0659]: `proc_macro_call` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
  --> src\main.rs:10:1
   |
10 | #[proc_macro_hack]
   | ^^^^^^^^^^^^^^^^^^ ambiguous name
...
14 |     let hi: &'static str = one!("hi");
   |                            ---------- in this macro invocation
   |
note: `proc_macro_call` could refer to the macro defined here
  --> src\main.rs:11:15
   |
11 | use proc_two::two;
   |               ^^^
...
14 |     let hi: &'static str = one!("hi");
   |                            ---------- in this macro invocation
note: `proc_macro_call` could also refer to the macro defined here
  --> src\main.rs:9:15
   |
9  | use proc_one::one;
   |               ^^^
...
14 |     let hi: &'static str = one!("hi");
   |                            ---------- in this macro invocation
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
1

1 Answers

1
votes

According to proc_macro_hack documentation nested invocations are not supported:

By default, nested invocations are not supported i.e. the code emitted by a proc-macro-hack macro invocation cannot contain recursive calls to the same proc-macro-hack macro nor calls to any other proc-macro-hack macros. Use proc-macro-nested if you require support for nested invocations.

Therefore the code marked by you is the real issue:

let x = quote! {
    two!(#r) // This is the problem
};

And there is a suggestion to look at proc-macro-nested "if you require support for nested invocations".