Templates inside modules

When you define a template, derive-deftly turns it into a definition of a macro_rules! macro. In the example above, that would be derive_deftly_template_HelloWorld.

Unfortunately, Rust's rules for scoping of macro_rules! macros are awkward and confusing. In general, there are two ways to expose a macro; we'll go over how to use each one for a derive-deftly template.

With path-scoped macros

With modern versions of Rust (Rust 2018 and later), you can use path-based scope to define the scope of a macro. With this method, you use pub use (or pub(crate) use, etc) to define the scope for a macro, and allow it to be accessed by its path.

pub mod hello_world {
    use derive_deftly::define_derive_deftly;
    define_derive_deftly! {
        HelloWorld: /* ... */
    }
    pub(crate) use derive_deftly_template_HelloWorld;
}

mod caller {
    use derive_deftly::Deftly;
    use super::hello_world::derive_deftly_template_HelloWorld;

    #[derive(Deftly)]
    #[derive_deftly(HelloWorld)]
    pub struct MyStruct;

    // Alternatively, you use the path, and avoid having to say "use":
    #[derive(Deftly)]
    #[derive_deftly(super::hello_world::HelloWorld)]
    pub struct MyOtherStruct;
}
fn main() {} // so that the above is not wrapped in fn main().

This is generally the better method to use.

Using #[macro_use]

We can also expose a macro using textual scope and macro_use: We prefix that module's mod statement with #[macro_use]. If you do this, the module defining the macro must come before the module where you use the macro. (Also, the macro's name is never scoped within the module.)

#![allow(unused)]
fn main() {
#[macro_use] // make HelloWorld visible outside the module (within the crate)
mod hello_world {
    use derive_deftly::define_derive_deftly;
    define_derive_deftly! {
        HelloWorld: /* ... */
    }
}
mod caller { // must come after mod hello_world
    use derive_deftly::Deftly;
    #[derive(Deftly)]
    #[derive_deftly(HelloWorld)] // not hello_world::HelloWorld
    pub struct MyStruct;
}
}