2018 edition macro ergonomics

When trying 2018 preview, one thing that bothers me is that now I have to include every single internal macro that the macro I'm using pulls in.

Eg.

use lazy_static::{__lazy_static_create, __lazy_static_internal, lazy_static};

Is there anything that macro authors can do, that would make the following work in 2018 edition?

use lazy_static::lazy_static; // internal macros not required
5 Likes

I published lazy_static 1.0.2 with a fix. Importing the private helper macros should not be required and those names are subject to change anyway, so code that does import them is liable to break.

Macro authors should use a $crate:: prefix to refer to local helper macros. This is similar to how macro authors should already be using $crate:: to refer to local types and functions.

#[macro_export]
macro_rules! demo {
    () => {
        $crate::demo_helper!(/* ... */);
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! demo_helper {
    /* ... */
}

Alternatively, libraries that would like to support pre-2018 compilers should use the local_inner_macros modifier like in rust-lang-nursery/lazy-static.rs/pull#107 to resolve all macro invocations within $crate implicitly. The modifier is ignored by old compilers and the macro will continue to work through #[macro_use] as before.

#[macro_export(local_inner_macros)]
macro_rules! demo {
    () => {
        demo_helper!(/* ... */);
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! demo_helper {
    /* ... */
}
12 Likes

This could really do to be in the 2018 edition guide for macros.

I’d love a PR!

1 Like

Here it is: https://github.com/rust-lang-nursery/edition-guide/pull/117 :smiley:

2 Likes