Auto merge of #40501 - jseyfried:shadow_builtin_macros, r=nrc

Allow `use` macro imports to shadow global macros

Terminology:
 - global scope: builtin macros, macros from the prelude, `#[macro_use]`, or `#![plugin(..)]`.
 - legacy scope: crate-local `macro_rules!`.
 - modern scope: `use` macro imports, `macro` (once implemented).

Today, the legacy scope can shadow the global scope (modulo RFC 1560 expanded shadowing restrictions). However, the modern scope cannot shadow or be shadowed by either the global or legacy scopes, leading to ambiguity errors.

This PR allows the modern scope to shadow the global scope (subject to some restrictions).
More specifically, a name in the global scope is as shadowable as a glob import in the module `self`. In other words, we imagine a special, implicit glob import in each module item:
```rust
mod foo {
    #[lexical_only] // Not accessible via `foo::<name>`, like pre-RFC 1560 `use` imports.
    #[shadowable_by_legacy_scope] // for back-compat
    use <global_macros>::*;
}
```

r? @nrc
This commit is contained in:
bors 2017-03-26 11:45:13 +00:00
commit bcfd5c48b7
5 changed files with 175 additions and 71 deletions

View file

@ -0,0 +1,72 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// aux-build:two_macros.rs
#![feature(use_extern_macros)]
mod foo {
extern crate two_macros;
pub use self::two_macros::m as panic;
}
mod m1 {
use foo::panic; // ok
fn f() { panic!(); }
}
mod m2 {
use foo::*; //~ NOTE `panic` could refer to the name imported here
fn f() { panic!(); } //~ ERROR ambiguous
//~| NOTE `panic` is also a builtin macro
//~| NOTE consider adding an explicit import of `panic` to disambiguate
}
mod m3 {
::two_macros::m!(use foo::panic;); //~ NOTE `panic` could refer to the name imported here
//~| NOTE in this expansion
fn f() { panic!(); } //~ ERROR ambiguous
//~| NOTE `panic` is also a builtin macro
//~| NOTE macro-expanded macro imports do not shadow
}
mod m4 {
macro_rules! panic { () => {} } // ok
panic!();
}
mod m5 {
macro_rules! m { () => {
macro_rules! panic { () => {} } //~ ERROR `panic` is already in scope
//~| NOTE macro-expanded `macro_rules!`s may not shadow existing macros
} }
m!(); //~ NOTE in this expansion
//~| NOTE in this expansion
panic!();
}
#[macro_use(n)] //~ NOTE `n` could also refer to the name imported here
extern crate two_macros;
mod bar {
pub use two_macros::m as n;
}
mod m6 {
use bar::n; // ok
n!();
}
mod m7 {
use bar::*; //~ NOTE `n` could refer to the name imported here
n!(); //~ ERROR ambiguous
//~| NOTE consider adding an explicit import of `n` to disambiguate
}
fn main() {}