[Verified: not a bug]Importing a macro and a trait with the exact same name, potential compiler bug?

I believe that I may have come across a bug -

I have created a runnable sample repo that contains the following module:

// double export of a symbol occurs here

pub use funny_derive::Funny;

mod funny;
pub use self::funny::Funny;

Despite having two symbols that contain the exact same name, it does not appear to have any compilation errors or name conflicts. Is this a bug in the Rust compiler?

Having said that, I know built in macros like Debug also match their trait name. Perhaps this is just some kind of expected special behavior with derive macros. Either way, I’d be curious to hear from someone more knowledgeable about the compiler.

This behavior is expected, because you can’t use a macro where a type/trait/value is expected, and you can’t use a type/trait/value where a macro is expected. So it isn’t possible for them to conflict even if they have the same name.

2 Likes

This is intentionally supported. Rust syntax is such that there couldn’t be an ambiguity between a macro called Funny and a type called Funny in any position in the grammar.

There is a third namespace as well for values, which is also not ambiguous with either of the previous two. For example the following program compiles with a name X present in all three namespaces.

// X in the macro namespace
macro_rules! X {
    () => {};
}

// X in the type namespace (types, traits, modules)
struct X {}

// X in the value namespace (constants, statics, functions, enum variants)
const X: () = ();

fn main() {
    // unambiguously the macro X
    X!();

    // unambiguously the type X
    let _: X;

    // unambiguously the value X
    let _ = X;
}
7 Likes

Thank you for the explanations.

One more question, if you don’t mind: what about the struct definitions? Are they adding the name to two namespaces at once (types and values)?

1 Like

Unit structs ( struct S; ) and tuple structs ( struct S(A, B); ) are both types and values. The value corresponding to a unit struct is like a constant whose value is that unit struct, and the value corresponding to a tuple struct is like a function that takes the tuple elements and returns the tuple struct. Constants and functions are both values.

Braced structs ( struct S { a: A } ) are types only.

8 Likes

Here’s some code (that compiles) that demonstrates this:

enum Bar {
    A(String, i32),
    B(usize, &'static str)
}

struct Foo(usize, usize);

fn main() {
    let _: fn(usize, usize) -> Foo = Foo;
    let _: fn(String, i32) -> Bar = Bar::A;
    let _: fn(usize, &'static str) -> Bar = Bar::B;
}

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.