3
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.
General Grievance
  • 4,555
  • 31
  • 31
  • 45
Siiir
  • 210
  • 6

1 Answers1

6

#[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.

Chayim Friedman
  • 47,971
  • 5
  • 48
  • 77
  • is there a way to avoid exporting from the crate root but export from the current module in a way that other crates can use? I have a secenario where exporting at the crate root will cause conflicts between several modules – Sam Johnson Jan 26 '23 at 16:33
  • 1
    @SamJohnson Not with `macro_rules`, unfortunately (only with macros 2.0). But you can use a trick: export a macro with `#[doc(hidden)]` mangled name (e.g. `module__macro`), then reexport it with public name from the module. – Chayim Friedman Jan 26 '23 at 16:38
  • 1
    @SamJohnson E.g. `#[macro_export] #[doc(hidden)] macro_rules! foo__bar { ... } pub use foo_bar as bar;`. – Chayim Friedman Jan 26 '23 at 16:40