ideasman42
ideasman42

Reputation: 48058

How to define some macros as 'private' to a module, when using `macro_use` in Rust?

I have a file which contains shared macros for a Rust project.

Since I want to re-use the macros across the crate (between modules), I declare the module with #[macro_use].

While writing the macros, I split out some shared logic into a macro to avoid repetition, in this case I can't use a private function, it needs to be a macro. If possible, I'd like to hide this shared macro so it can't be used directly by other modules.

Is there a way to make some macros private, so they aren't exposed to other modules in the same crate via #[macro_use]?

Upvotes: 8

Views: 3429

Answers (2)

ideasman42
ideasman42

Reputation: 48058

Currently, the macro namespace bounds can only be constrained across crates.

The only way to make some macros private is to split the module into a crate, then use #[macro_export] to define which macros are exported from that crate.

See Rust's documentation on this topic.


Note: there may be some obscure way to do this, but from reading documentation it seems this feature isn't officially supported, which is why I posted this answer - happy to be proven wrong!

The #rust IRC channel states that this is something which might be supported in Macros 2.0.

Upvotes: 0

Matthieu M.
Matthieu M.

Reputation: 299930

There actually is an idiom in Rust, to hide away "implementation-detail" macros.

Rather than declaring a separate macros, you can instead declare a separate case within the existing macro. The examples I've seen would use the impl keyword for this, and the impl cases are located at the bottom of the macro definition.

Thus, instead of:

macro_rules! hello_impl {
    ($name:expr) => {
        println!("Hello {}!", $name);
    }
}

macro_rules! hello_world {
    () => {
        hello_impl!("world");
    }
}

You use:

macro_rules! hello_world {
    () => {
        hello_world!(impl "world");
    },
    (impl $name:expr) => {
        println!("Hello {}!", $name);
    }
}

This way, there is no implementation macro any longer; and you only have one macro to export.

Upvotes: 11

Related Questions