Search code examples
rustimportmacrosexportvisibility

How to import/use macro from different module in the same crate?


Real life scenario:

I wanted to use crate::app::verbose_trace!("string literal") inside crate::app::args::parse module.

Reproducable scenario:

After an hour of attempts, I came with following simple example. It exposes my misunderstanding of macros.

  #[macro_use]
  mod foo{
      pub fn bar(){
          println!("bar works")
      }
      #[macro_export]
      macro_rules! baz{
          ()=> {println!("baz works")}
      }
  }

  fn main(){
      foo::bar();
      foo::baz!();
      // Following doesn't work either:
      // use foo::baz;
      // baz!();
  }

Compiler complains

  error[E0433]: failed to resolve: could not find `baz` in `foo`
  --> src\main.rs:14:14
  |
  14 |         foo::baz!();
  |              ^^^ could not find `baz` in `foo`

as if it was utterly blind :0

I read:
I would like to see:
  • A compilable version of my example.
  • Explanations why it did failed to compile.
  • Optionally:
    • Some other suggestions how to use marco in submodule/supermodule.

Solution

  • #[macro_export] exports the macro under the crate root. Thus, crate::baz!() will work, but foo::baz!() won't (and you don't need #[macro_use], it is for using the macro in another crates).

    If you want to export the macro in this path, for crate local macros don't use #[macro_export] as all. Instead, export the macro like:

    macro_rules! baz {
        () => {
            println!("baz works")
        };
    }
    pub(crate) use baz;
    

    For exporting the macro for use in other crates you still need #[macro_export]:

    #[macro_export]
    macro_rules! baz {
        () => {
            println!("baz works")
        };
    }
    pub use baz;
    

    This will export the macro both under the crate root and under foo.