Long story short - macro_rules! acts like let variables, but at module level, so there can be many of them having the same name in a single module and shadowing each other.
For use module::my_macro to work with local macro_rules! we need to decide what my_macro exactly it refers to (probably the last one) and how to do it without causing import resolution to stuck.
#[macro_export] macro_rules! on another hand defines two names actually, one usual let-like macro_rules and one item-like name in the root module that can be imported with use.
That's why you can't define multiple #[macro_export] macro_rules! with the same name in the same crate.
With uniform paths on 2018 edition there's a way to make macro_rules! item modularized explicitly
macro_rules! foo { () => () } // `let`-like macro
pub(crate) use foo; // item-like reexport of the `let`-like macro
Perhaps there's a way to add this reexport automatically, but this certainly cannot be done naively because it will break the multiple shadowing macro_rules! in the same module.
@petrochenkov Thanks for the explanation! Do you think some condensed version of this belongs in the edition guide (even a one-liner about shadowing issues)?
This clarified my mental model a lot, thank you! What about #[macro_use] on a mod item? Does it expand the let-like scope to “continue” in the rest of the parent module, and later sibling modules?
Probably yes, because the question arises regularly.
Yes, by default the closing brace } on module or block terminates macro_rules scopes, but #[macro_use] on mod opts-out of this default and lets the scopes continue further.
Unlike let variables macro_rules don't have any runtime behavior/lifetimes/destructors attached to the scope end, so letting them out doesn't cause any issues.