'How should I use `macro_export` for a custom module

I have the following structure:

enter image description here

Inside queues.rs I have a #[macro_export],

#[macro_export]
macro_rules! queue {...}

but I am not sure how to import it in lib.rs.

What I have looks like this:

use crate::utils::queues::*;

// use it here
let mut service_queue: Queue<isize> = queue![];

This throws an error

error: cannot find macro `queue` in this scope
  --> src/broker.rs:54:51
   |
54 |             let mut service_queue: Queue<isize> = queue![];
   |                                                   ^^^^^
   |
   = note: consider importing this macro:
           crate::queue
   = help: have you added the `#[macro_use]` on the module/import?

What is the correct way to type #[macro_use] here, and import my custom macros from utils?



Solution 1:[1]

You can use the queue! macro from lib.rs using the #[macro_use] attribute (playground):

#[macro_use]
mod utils {
    #[macro_use]
    mod queues {
        macro_rules! queue {
            () => { vec![] };
        }
    }
}

pub fn foo() {
    let _service_queue: Vec<isize> = queue![];
}

In your existing code you are using #[macro_export] which means it is declared in the crate root scope and not in the utils::queues module. In your error message you can see the compile is suggesting to consider importing this macro: crate::queue.

To access it in this case (playground):

mod utils {
    mod queues {
        #[macro_export]
        macro_rules! queue {
            () => { vec![] };
        }
    }
}

pub fn foo() {
    let _service_queue: Vec<isize> = queue![];
}

Note that in either case the use crate::utils::queues::*; statement does not help, in fact you'll get an unused_imports warning (unless you happen to have other items declared in that module).

There is also this trick (playground):

pub mod utils {
    pub mod queues {
        macro_rules! queue {
            () => { vec![] };
        }
        pub(crate) use queue;
    }
}

pub fn foo() {
    let _service_queue: Vec<isize> = crate::utils::queues::queue![];
}

Aside: if you plan to use the macro in other crates and you wish to retain the module hierarchy (i.e. access from my_crate::utils::queues::queue! from my_other_crate) there is a (convoluted) way to do that.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1