See also:
https://stackoverflow.com/questions/26731243/how-do-i-use-a-macro-across-module-files/67140319#67140319
mod foo {
macro_rules! bar {() => ()}
pub(crate) use bar;
}
foo::bar!(); // Works!
Regarding the discussion about decl_macro
s, the feature has to do with

It has the advantage that when you call a macro
macro, a caller knows the kind of items that may be affected by it. That's the whole point of hygiene:
struct S;
mod foo {
use super::*;
::some_crate::some_macro!();
fn foo (s: S) {} // <- no matter what `some_macro!` expands to, thanks
// to hygiene, we *know* `S` refers to what we wanted.
}
This is the whole point of hygiene. Current macros, be it procedural ones, or macro_rules!
ones, can't guarantee this, and thus one ends up writing a lot of __VAR
code, and ::core::result::Result::Ok
kind of paths, again, because of hygiene. And let's not forget those very pretty #[doc(hidden)] pub mod __ {
modules to provide internal helpers to one's macros.
All these things are solved by the proper hygiene of macro
macros.
macro m {( $StructName:ident ) => (
struct $StructName;
)}
m!(S);
const _: () = {
let _: S; // OK
};
Just Works
, and so does:
pub
macro m {() => (
const _: () = {
// ...
let _: private::MacroHelper;
};
)}
// private! No need to `#[doc(hidden)] pub`
mod private {
pub
struct MacroHelper;
}
So, granted, sometimes we still want unhygienic behavior. At that point it is unfair to criticize a partially implemented feature: there is indeed currently no way to opt-out of the full hygiene it imbues its defined elements with (except by making the macro take extra identifier parameters, as showcased above), but there will likely be a way:
/// Imaginary syntax
macro m {() => (
struct #S;
)}
// or, another possible syntax:
match! (S) {( $S:ident ) => (
macro m {() => (
struct $S;
)}
)}
All in all, macro
macros improve the situation quite a bit.
Their only drawback, right now, is that their shorthand sugar macro m() { ... }
, which, you may have noticed, I have tried not to use, does not wrap the expanded stuff in extra braces. So they will still be quite confusing for beginners trying to write:
macro m() {
let x = 42;
x
}
let y = m!(); // Error
instead of:
macro m {() => ({
let x = 42;
x
})}