It is my pleasure to announce that we have now entered the final countdown for Rust 2018. We’ve just issued a new beta that is chock full of updates and we would dearly love people to spend some time testing it before we announce the final release (which takes place on December 6).
We would like help looking for bugs in this new beta, particularly in two areas:
the module system implementation
the RLS
As before, the best thing is to perform the Rust 2015 -> Rust 2018 migration on your local crates (instructions here) and let us know how it goes (in particular if you hit any problems). If you’ve already migated, then simply executing rustup update beta is already helpful (and working from beta, of course, not nightly)!
Pending for the next release
You may recall from the Preview 2 announcement that we were evaluating two variants for the module system (“anchored paths” vs “uniform paths”). This evaluation continues in the beta, which means that the compiler accepts only code that both variants would accept. You can use #![feature(uniform_paths)] on Nightly to try out the uniform paths variant. Based on the feedback receiver thus far, the current tentative plan is to stabilize uniform paths, but not as part of the initial Rust 2018 release (i.e., not until 1.32.0 at the earliest).
(The main difference between that two variants is that uniform_paths permits you to write use foo::bar to refer to either an external crate named fooor a local module. In other words, you no longer need to write use self::foo::bar (except for cases of ambiguity, where there exists an external crate and a local module). This means that paths in use statements and paths outside of use statements work roughly the same way. Note that this is a pure extension of the current beta behavior, which always requires use self::foo for local modules, but still errors in the case of ambiguity.)
Long story short - macro_rules! acts like let variables, but at module level, so there can be many of them having the same name in a single module and shadowing each other.
For use module::my_macro to work with local macro_rules! we need to decide what my_macro exactly it refers to (probably the last one) and how to do it without causing import resolution to stuck.
#[macro_export] macro_rules! on another hand defines two names actually, one usual let-like macro_rules and one item-like name in the root module that can be imported with use.
That's why you can't define multiple #[macro_export] macro_rules! with the same name in the same crate.
With uniform paths on 2018 edition there's a way to make macro_rules! item modularized explicitly
macro_rules! foo { () => () } // `let`-like macro
pub(crate) use foo; // item-like reexport of the `let`-like macro
Perhaps there's a way to add this reexport automatically, but this certainly cannot be done naively because it will break the multiple shadowing macro_rules! in the same module.
@petrochenkov Thanks for the explanation! Do you think some condensed version of this belongs in the edition guide (even a one-liner about shadowing issues)?
This clarified my mental model a lot, thank you! What about #[macro_use] on a mod item? Does it expand the let-like scope to “continue” in the rest of the parent module, and later sibling modules?
Probably yes, because the question arises regularly.
Yes, by default the closing brace } on module or block terminates macro_rules scopes, but #[macro_use] on mod opts-out of this default and lets the scopes continue further.
Unlike let variables macro_rules don't have any runtime behavior/lifetimes/destructors attached to the scope end, so letting them out doesn't cause any issues.