I'm trying to understand best practices regarding publicly accessible macros. Consider I have a crate a
with this module:
pub mod some_module {
#[macro_export]
macro_rules! some_macro {
{} => { println!("Hello!"); }
}
}
Then that crate will export the macro as a::some_macro
.
If I now have a crate b
, which does:
use a::some_module::*;
fn main() {
some_macro!();
}
Then this will fail to compile:
error: cannot find macro `some_macro` in this scope
--> src/main.rs:4:5
|
4 | some_macro!();
| ^^^^^^^^^^
|
= note: consider importing this macro:
a::some_macro
I can fix this either by importing the macro from the crate-level module (use a::some_macro
instead of use a::some_module::*
), or I can modify crate a
as follows:
pub mod some_module {
#[macro_export]
macro_rules! some_macro {
{} => { println!("Hello!"); }
}
+ pub use crate::some_macro;
}
Thus, it's possible to export the macro as a::some_module::some_macro
in addition to the crate-level export.
My question: Is it reasonable to re-export macros where they are defined? For example, this would allow users of the crate to import all items from a submodule (including macros) when doing use a::some_module::*;
.
I have seen that std
also has some macros that aren't at the crate-level, e.g. std::ptr::addr_of
. In that case, the macro doesn't even exist at the root-level (Playground).
I would like to understand better when and where to export macros, and how to achieve it. What's the usual practice; and does std
something magic that ordinary crates cannot or should not do?
P.S.: I have a use-case where I re-export a macro in a prelude
module: radiorust::prelude
. Is this idiomatic?