about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2018-06-11 14:21:36 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2018-06-27 13:10:16 +0300
commitd347270e0c241823d6e3333060f5ee902fffee6a (patch)
tree0f518049f1d90de27c97d245798ff17df9d9048d /src
parent971f7d34d4e8afa663b3972b58528a069a25b436 (diff)
downloadrust-d347270e0c241823d6e3333060f5ee902fffee6a.tar.gz
rust-d347270e0c241823d6e3333060f5ee902fffee6a.zip
Implement `#[macro_export(local_inner_macros)]`
Diffstat (limited to 'src')
-rw-r--r--src/librustc/hir/lowering.rs1
-rw-r--r--src/librustc/ich/impls_syntax.rs1
-rw-r--r--src/librustc_allocator/expand.rs1
-rw-r--r--src/librustc_plugin/registry.rs3
-rw-r--r--src/librustc_resolve/macros.rs9
-rw-r--r--src/libsyntax/ext/base.rs3
-rw-r--r--src/libsyntax/ext/derive.rs1
-rw-r--r--src/libsyntax/ext/expand.rs10
-rw-r--r--src/libsyntax/ext/tt/macro_rules.rs7
-rw-r--r--src/libsyntax/std_inject.rs1
-rw-r--r--src/libsyntax/test.rs1
-rw-r--r--src/libsyntax_ext/lib.rs2
-rw-r--r--src/libsyntax_ext/proc_macro_registrar.rs1
-rw-r--r--src/libsyntax_pos/hygiene.rs3
-rw-r--r--src/test/run-pass-fulldeps/auxiliary/plugin_args.rs1
-rw-r--r--src/test/ui/hygiene/auxiliary/local_inner_macros.rs29
-rw-r--r--src/test/ui/hygiene/local_inner_macros.rs31
-rw-r--r--src/test/ui/hygiene/local_inner_macros_disabled.rs21
-rw-r--r--src/test/ui/hygiene/local_inner_macros_disabled.stderr10
19 files changed, 134 insertions, 2 deletions
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index a3f86c54283..e14a86eb954 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -616,6 +616,7 @@ impl<'a> LoweringContext<'a> {
             format: codemap::CompilerDesugaring(reason),
             allow_internal_unstable: true,
             allow_internal_unsafe: false,
+            local_inner_macros: false,
             edition: codemap::hygiene::default_edition(),
         });
         span.with_ctxt(SyntaxContext::empty().apply_mark(mark))
diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs
index 935bc4c8c6d..790ef702963 100644
--- a/src/librustc/ich/impls_syntax.rs
+++ b/src/librustc/ich/impls_syntax.rs
@@ -395,6 +395,7 @@ impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnInfo {
     format,
     allow_internal_unstable,
     allow_internal_unsafe,
+    local_inner_macros,
     edition
 });
 
diff --git a/src/librustc_allocator/expand.rs b/src/librustc_allocator/expand.rs
index 60d28d8098b..373ab04de4b 100644
--- a/src/librustc_allocator/expand.rs
+++ b/src/librustc_allocator/expand.rs
@@ -103,6 +103,7 @@ impl<'a> Folder for ExpandAllocatorDirectives<'a> {
             format: MacroAttribute(Symbol::intern(name)),
             allow_internal_unstable: true,
             allow_internal_unsafe: false,
+            local_inner_macros: false,
             edition: hygiene::default_edition(),
         });
 
diff --git a/src/librustc_plugin/registry.rs b/src/librustc_plugin/registry.rs
index ea15f4c75b9..b1ab86674cf 100644
--- a/src/librustc_plugin/registry.rs
+++ b/src/librustc_plugin/registry.rs
@@ -108,6 +108,7 @@ impl<'a> Registry<'a> {
                 def_info: _,
                 allow_internal_unstable,
                 allow_internal_unsafe,
+                local_inner_macros,
                 unstable_feature,
                 edition,
             } => {
@@ -117,6 +118,7 @@ impl<'a> Registry<'a> {
                     def_info: Some((nid, self.krate_span)),
                     allow_internal_unstable,
                     allow_internal_unsafe,
+                    local_inner_macros,
                     unstable_feature,
                     edition,
                 }
@@ -152,6 +154,7 @@ impl<'a> Registry<'a> {
             def_info: None,
             allow_internal_unstable: false,
             allow_internal_unsafe: false,
+            local_inner_macros: false,
             unstable_feature: None,
             edition: hygiene::default_edition(),
         });
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index ebdaa456170..c9d00f80b0b 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -451,11 +451,18 @@ impl<'a> Resolver<'a> {
                                   kind: MacroKind, force: bool)
                                   -> Result<Def, Determinacy> {
         let ast::Path { ref segments, span } = *path;
-        let path: Vec<_> = segments.iter().map(|seg| seg.ident).collect();
+        let mut path: Vec<_> = segments.iter().map(|seg| seg.ident).collect();
         let invocation = self.invocations[&scope];
         let module = invocation.module.get();
         self.current_module = if module.is_trait() { module.parent.unwrap() } else { module };
 
+        // Possibly apply the macro helper hack
+        if self.use_extern_macros && kind == MacroKind::Bang && path.len() == 1 &&
+           path[0].span.ctxt().outer().expn_info().map_or(false, |info| info.local_inner_macros) {
+            let root = Ident::new(keywords::DollarCrate.name(), path[0].span);
+            path.insert(0, root);
+        }
+
         if path.len() > 1 {
             if !self.use_extern_macros && self.gated_errors.insert(span) {
                 let msg = "non-ident macro paths are experimental";
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 16d786dd6ca..9afce74f53c 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -621,6 +621,9 @@ pub enum SyntaxExtension {
         /// Whether the contents of the macro can use `unsafe`
         /// without triggering the `unsafe_code` lint.
         allow_internal_unsafe: bool,
+        /// Enables the macro helper hack (`ident!(...)` -> `$crate::ident!(...)`)
+        /// for a given macro.
+        local_inner_macros: bool,
         /// The macro's feature name if it is unstable, and the stability feature
         unstable_feature: Option<(Symbol, u32)>,
         /// Edition of the crate in which the macro is defined
diff --git a/src/libsyntax/ext/derive.rs b/src/libsyntax/ext/derive.rs
index 940fb6405f1..32ace937ac0 100644
--- a/src/libsyntax/ext/derive.rs
+++ b/src/libsyntax/ext/derive.rs
@@ -64,6 +64,7 @@ pub fn add_derived_markers<T>(cx: &mut ExtCtxt, span: Span, traits: &[ast::Path]
         format: ExpnFormat::MacroAttribute(Symbol::intern(&pretty_name)),
         allow_internal_unstable: true,
         allow_internal_unsafe: false,
+        local_inner_macros: false,
         edition: hygiene::default_edition(),
     });
 
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 69c99c63aaf..23880c1270f 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -542,6 +542,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
             format: MacroAttribute(Symbol::intern(&format!("{}", attr.path))),
             allow_internal_unstable: false,
             allow_internal_unsafe: false,
+            local_inner_macros: false,
             edition: ext.edition(),
         });
 
@@ -695,6 +696,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                                           def_site_span: Option<Span>,
                                           allow_internal_unstable,
                                           allow_internal_unsafe,
+                                          local_inner_macros,
                                           // can't infer this type
                                           unstable_feature: Option<(Symbol, u32)>,
                                           edition| {
@@ -729,6 +731,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                 format: macro_bang_format(path),
                 allow_internal_unstable,
                 allow_internal_unsafe,
+                local_inner_macros,
                 edition,
             });
             Ok(())
@@ -737,7 +740,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         let opt_expanded = match *ext {
             DeclMacro(ref expand, def_span, edition) => {
                 if let Err(dummy_span) = validate_and_set_expn_info(self, def_span.map(|(_, s)| s),
-                                                                    false, false, None,
+                                                                    false, false, false, None,
                                                                     edition) {
                     dummy_span
                 } else {
@@ -750,12 +753,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                 def_info,
                 allow_internal_unstable,
                 allow_internal_unsafe,
+                local_inner_macros,
                 unstable_feature,
                 edition,
             } => {
                 if let Err(dummy_span) = validate_and_set_expn_info(self, def_info.map(|(_, s)| s),
                                                                     allow_internal_unstable,
                                                                     allow_internal_unsafe,
+                                                                    local_inner_macros,
                                                                     unstable_feature,
                                                                     edition) {
                     dummy_span
@@ -777,6 +782,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                         format: macro_bang_format(path),
                         allow_internal_unstable,
                         allow_internal_unsafe: false,
+                        local_inner_macros: false,
                         edition: hygiene::default_edition(),
                     });
 
@@ -816,6 +822,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                         // FIXME probably want to follow macro_rules macros here.
                         allow_internal_unstable,
                         allow_internal_unsafe: false,
+                        local_inner_macros: false,
                         edition,
                     });
 
@@ -890,6 +897,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
             format: MacroAttribute(pretty_name),
             allow_internal_unstable: false,
             allow_internal_unsafe: false,
+            local_inner_macros: false,
             edition: ext.edition(),
         };
 
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index 4ee5357f476..3b3892729d9 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -286,6 +286,12 @@ pub fn compile(sess: &ParseSess, features: &Features, def: &ast::Item, edition:
     if body.legacy {
         let allow_internal_unstable = attr::contains_name(&def.attrs, "allow_internal_unstable");
         let allow_internal_unsafe = attr::contains_name(&def.attrs, "allow_internal_unsafe");
+        let mut local_inner_macros = false;
+        if let Some(macro_export) = attr::find_by_name(&def.attrs, "macro_export") {
+            if let Some(l) = macro_export.meta_item_list() {
+                local_inner_macros = attr::list_contains_name(&l, "local_inner_macros");
+            }
+        }
 
         let unstable_feature = attr::find_stability(&sess.span_diagnostic,
                                                     &def.attrs, def.span).and_then(|stability| {
@@ -301,6 +307,7 @@ pub fn compile(sess: &ParseSess, features: &Features, def: &ast::Item, edition:
             def_info: Some((def.id, def.span)),
             allow_internal_unstable,
             allow_internal_unsafe,
+            local_inner_macros,
             unstable_feature,
             edition,
         }
diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs
index 66e8e0d7a9c..68121d42b69 100644
--- a/src/libsyntax/std_inject.rs
+++ b/src/libsyntax/std_inject.rs
@@ -29,6 +29,7 @@ fn ignored_span(sp: Span) -> Span {
         format: MacroAttribute(Symbol::intern("std_inject")),
         allow_internal_unstable: true,
         allow_internal_unsafe: false,
+        local_inner_macros: false,
         edition: hygiene::default_edition(),
     });
     sp.with_ctxt(SyntaxContext::empty().apply_mark(mark))
diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs
index 141fd122ff5..51fbe34028e 100644
--- a/src/libsyntax/test.rs
+++ b/src/libsyntax/test.rs
@@ -311,6 +311,7 @@ fn generate_test_harness(sess: &ParseSess,
         format: MacroAttribute(Symbol::intern("test")),
         allow_internal_unstable: true,
         allow_internal_unsafe: false,
+        local_inner_macros: false,
         edition: hygiene::default_edition(),
     });
 
diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs
index af3ef181c59..31125183266 100644
--- a/src/libsyntax_ext/lib.rs
+++ b/src/libsyntax_ext/lib.rs
@@ -76,6 +76,7 @@ pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver,
                         def_info: None,
                         allow_internal_unstable: false,
                         allow_internal_unsafe: false,
+                        local_inner_macros: false,
                         unstable_feature: None,
                         edition: hygiene::default_edition(),
                     });
@@ -132,6 +133,7 @@ pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver,
                 def_info: None,
                 allow_internal_unstable: true,
                 allow_internal_unsafe: false,
+                local_inner_macros: false,
                 unstable_feature: None,
                 edition: hygiene::default_edition(),
             });
diff --git a/src/libsyntax_ext/proc_macro_registrar.rs b/src/libsyntax_ext/proc_macro_registrar.rs
index ee343e47bd8..ef29e5a6b02 100644
--- a/src/libsyntax_ext/proc_macro_registrar.rs
+++ b/src/libsyntax_ext/proc_macro_registrar.rs
@@ -368,6 +368,7 @@ fn mk_registrar(cx: &mut ExtCtxt,
         format: MacroAttribute(Symbol::intern("proc_macro")),
         allow_internal_unstable: true,
         allow_internal_unsafe: false,
+        local_inner_macros: false,
         edition: hygiene::default_edition(),
     });
     let span = DUMMY_SP.apply_mark(mark);
diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs
index 3365d595403..d1b9c7a84d1 100644
--- a/src/libsyntax_pos/hygiene.rs
+++ b/src/libsyntax_pos/hygiene.rs
@@ -496,6 +496,9 @@ pub struct ExpnInfo {
     /// Whether the macro is allowed to use `unsafe` internally
     /// even if the user crate has `#![forbid(unsafe_code)]`.
     pub allow_internal_unsafe: bool,
+    /// Enables the macro helper hack (`ident!(...)` -> `$crate::ident!(...)`)
+    /// for a given macro.
+    pub local_inner_macros: bool,
     /// Edition of the crate in which the macro is defined.
     pub edition: Edition,
 }
diff --git a/src/test/run-pass-fulldeps/auxiliary/plugin_args.rs b/src/test/run-pass-fulldeps/auxiliary/plugin_args.rs
index d7ede763838..ac39118c5f1 100644
--- a/src/test/run-pass-fulldeps/auxiliary/plugin_args.rs
+++ b/src/test/run-pass-fulldeps/auxiliary/plugin_args.rs
@@ -54,6 +54,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
             def_info: None,
             allow_internal_unstable: false,
             allow_internal_unsafe: false,
+            local_inner_macros: false,
             unstable_feature: None,
             edition: hygiene::default_edition(),
         });
diff --git a/src/test/ui/hygiene/auxiliary/local_inner_macros.rs b/src/test/ui/hygiene/auxiliary/local_inner_macros.rs
new file mode 100644
index 00000000000..caa2903cc70
--- /dev/null
+++ b/src/test/ui/hygiene/auxiliary/local_inner_macros.rs
@@ -0,0 +1,29 @@
+// Copyright 2018 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.
+
+#[macro_export]
+macro_rules! helper1 {
+    () => ( struct S; )
+}
+
+#[macro_export(local_inner_macros)]
+macro_rules! helper2 {
+    () => ( helper1!(); )
+}
+
+#[macro_export(local_inner_macros)]
+macro_rules! public_macro {
+    () => ( helper2!(); )
+}
+
+#[macro_export(local_inner_macros)]
+macro_rules! public_macro_dynamic {
+    ($helper: ident) => ( $helper!(); )
+}
diff --git a/src/test/ui/hygiene/local_inner_macros.rs b/src/test/ui/hygiene/local_inner_macros.rs
new file mode 100644
index 00000000000..787e2df3ec2
--- /dev/null
+++ b/src/test/ui/hygiene/local_inner_macros.rs
@@ -0,0 +1,31 @@
+// Copyright 2018 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.
+
+// compile-pass
+// aux-build:local_inner_macros.rs
+
+#![feature(use_extern_macros)]
+
+extern crate local_inner_macros;
+
+use local_inner_macros::{public_macro, public_macro_dynamic};
+
+public_macro!();
+
+macro_rules! local_helper {
+    () => ( struct Z; )
+}
+
+public_macro_dynamic!(local_helper);
+
+fn main() {
+    let s = S;
+    let z = Z;
+}
diff --git a/src/test/ui/hygiene/local_inner_macros_disabled.rs b/src/test/ui/hygiene/local_inner_macros_disabled.rs
new file mode 100644
index 00000000000..00b38787db8
--- /dev/null
+++ b/src/test/ui/hygiene/local_inner_macros_disabled.rs
@@ -0,0 +1,21 @@
+// Copyright 2018 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.
+
+// `local_inner_macros` has no effect if `feature(use_extern_macros)` is not enabled
+
+// aux-build:local_inner_macros.rs
+// error-pattern: cannot find macro `helper2!` in this scope
+
+#[macro_use(public_macro)]
+extern crate local_inner_macros;
+
+public_macro!();
+
+fn main() {}
diff --git a/src/test/ui/hygiene/local_inner_macros_disabled.stderr b/src/test/ui/hygiene/local_inner_macros_disabled.stderr
new file mode 100644
index 00000000000..64cb6c400cf
--- /dev/null
+++ b/src/test/ui/hygiene/local_inner_macros_disabled.stderr
@@ -0,0 +1,10 @@
+error: cannot find macro `helper2!` in this scope
+  --> $DIR/local_inner_macros_disabled.rs:19:1
+   |
+LL | public_macro!();
+   | ^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+