Closed
Description
The following expression compiles if macro_rules! m
is generated by a macro_rules macro, but not if macro_rules! m
is generated by a procedural macro. I believe it should compile in both cases. The invocation of m!
should resolve to the innermost one, as happens for all other types of items.
{
macro_rules! m { ... }
{
macro_rules! m { ... }
m!()
}
}
Repro:
src/main.rs
#![allow(unused_macros)]
macro_rules! eval_with_m {
($e:expr) => {{
macro_rules! m {
() => {
println!("success");
};
}
$e
}};
}
macro_rules! eval_with_m_derived {
($e:expr) => {{
#[derive(repro::M)]
struct S;
$e
}};
}
fn main() {
// Expanded code looks like:
//
// {
// macro_rules! m { ... }
// {
// macro_rules! m { ... }
// m!()
// }
// }
//
eval_with_m! {
eval_with_m! {
m!()
}
}
// Expanded code is the same but fails to compile.
//
// error[E0659]: `m` is ambiguous (macro-expanded name vs less
// macro-expanded name from outer scope during import/macro resolution)
//
eval_with_m_derived! {
eval_with_m_derived! {
m!()
}
}
}
src/lib.rs
extern crate proc_macro;
use proc_macro::TokenStream;
use quote::quote;
#[proc_macro_derive(M)]
pub fn emit_m(_input: TokenStream) -> TokenStream {
TokenStream::from(quote! {
macro_rules! m {
() => {
println!("success");
};
}
})
}
Mentioning @petrochenkov who worked on #52841 and fixed #53205.
Mentioning @cramertj who hit this using proc-macro-hack in futures.