about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan DPC <dylan.dpc@gmail.com>2021-02-23 16:10:23 +0100
committerGitHub <noreply@github.com>2021-02-23 16:10:23 +0100
commite2561c58a41023a14e0e583113dcf55e1ecb236a (patch)
treeb4f78b67c2cf8052c90b91d734ed4b02e1a1edd7
parent2982ba50fc4bb629b8fe4108a81cb2f9b053510b (diff)
parentb3000ec0cdb35b305bfe954db4b14ce32cbc255b (diff)
downloadrust-e2561c58a41023a14e0e583113dcf55e1ecb236a.tar.gz
rust-e2561c58a41023a14e0e583113dcf55e1ecb236a.zip
Rollup merge of #82296 - spastorino:pubrules, r=nikomatsakis
Support `pub` on `macro_rules`

This rebases and updates `since` version of #78166 from ``@petrochenkov``

r? ``@nikomatsakis``
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs1
-rw-r--r--compiler/rustc_feature/src/active.rs3
-rw-r--r--compiler/rustc_parse/src/parser/item.rs10
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs9
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--src/test/ui/did_you_mean/pub-macro-rules.rs16
-rw-r--r--src/test/ui/did_you_mean/pub-macro-rules.stderr8
-rw-r--r--src/test/ui/feature-gates/feature-gate-pub_macro_rules.rs10
-rw-r--r--src/test/ui/feature-gates/feature-gate-pub_macro_rules.stderr39
-rw-r--r--src/test/ui/macros/macro-export-on-modularized-macros.rs11
-rw-r--r--src/test/ui/macros/macro-export-on-modularized-macros.stderr14
-rw-r--r--src/test/ui/macros/pub-macro-rules-fail.rs28
-rw-r--r--src/test/ui/macros/pub-macro-rules-fail.stderr48
-rw-r--r--src/test/ui/macros/pub-macro-rules.rs20
14 files changed, 183 insertions, 35 deletions
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 6514de2b813..474ec2b589b 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -665,6 +665,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
         // involved, so we only emit errors where there are no other parsing errors.
         gate_all!(destructuring_assignment, "destructuring assignments are unstable");
     }
+    gate_all!(pub_macro_rules, "`pub` on `macro_rules` items is unstable");
 
     // All uses of `gate_all!` below this point were added in #65742,
     // and subsequently disabled (with the non-early gating readded).
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 2d0009c225c..3f484ab5686 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -638,6 +638,9 @@ declare_features! (
     /// Allows macro attributes to observe output of `#[derive]`.
     (active, macro_attributes_in_derive_output, "1.51.0", Some(81119), None),
 
+    /// Allows `pub` on `macro_rules` items.
+    (active, pub_macro_rules, "1.52.0", Some(78855), None),
+
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
     // -------------------------------------------------------------------------
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index f3f5fc9af64..073a2d8bd51 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -1475,15 +1475,7 @@ impl<'a> Parser<'a> {
         let vstr = pprust::vis_to_string(vis);
         let vstr = vstr.trim_end();
         if macro_rules {
-            let msg = format!("can't qualify macro_rules invocation with `{}`", vstr);
-            self.struct_span_err(vis.span, &msg)
-                .span_suggestion(
-                    vis.span,
-                    "try exporting the macro",
-                    "#[macro_export]".to_owned(),
-                    Applicability::MaybeIncorrect, // speculative
-                )
-                .emit();
+            self.sess.gated_spans.gate(sym::pub_macro_rules, vis.span);
         } else {
             self.struct_span_err(vis.span, "can't qualify macro invocation with `pub`")
                 .span_suggestion(
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 79ed0b5308d..65e5b0dddea 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -1230,13 +1230,13 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
         };
 
         let res = Res::Def(DefKind::Macro(ext.macro_kind()), def_id.to_def_id());
+        let is_macro_export = self.r.session.contains_name(&item.attrs, sym::macro_export);
         self.r.macro_map.insert(def_id.to_def_id(), ext);
         self.r.local_macro_def_scopes.insert(def_id, parent_scope.module);
 
-        if macro_rules {
+        if macro_rules && matches!(item.vis.kind, ast::VisibilityKind::Inherited) {
             let ident = ident.normalize_to_macros_2_0();
             self.r.macro_names.insert(ident);
-            let is_macro_export = self.r.session.contains_name(&item.attrs, sym::macro_export);
             let vis = if is_macro_export {
                 ty::Visibility::Public
             } else {
@@ -1261,6 +1261,11 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                 }),
             ))
         } else {
+            if is_macro_export {
+                let what = if macro_rules { "`macro_rules` with `pub`" } else { "`macro` items" };
+                let msg = format!("`#[macro_export]` cannot be used on {what}");
+                self.r.session.span_err(item.span, &msg);
+            }
             let module = parent_scope.module;
             let vis = match item.kind {
                 // Visibilities must not be resolved non-speculatively twice
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 01820656c37..b112402ffe3 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -881,6 +881,7 @@ symbols! {
         ptr_guaranteed_eq,
         ptr_guaranteed_ne,
         ptr_offset_from,
+        pub_macro_rules,
         pub_restricted,
         pure,
         pushpop_unsafe,
diff --git a/src/test/ui/did_you_mean/pub-macro-rules.rs b/src/test/ui/did_you_mean/pub-macro-rules.rs
deleted file mode 100644
index c5393703f70..00000000000
--- a/src/test/ui/did_you_mean/pub-macro-rules.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-#[macro_use] mod bleh {
-    pub macro_rules! foo { //~ ERROR can't qualify macro_rules invocation
-        ($n:ident) => (
-            fn $n () -> i32 {
-                1
-            }
-        )
-    }
-
-}
-
-foo!(meh);
-
-fn main() {
-    println!("{}", meh());
-}
diff --git a/src/test/ui/did_you_mean/pub-macro-rules.stderr b/src/test/ui/did_you_mean/pub-macro-rules.stderr
deleted file mode 100644
index 0bde5783b8c..00000000000
--- a/src/test/ui/did_you_mean/pub-macro-rules.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: can't qualify macro_rules invocation with `pub`
-  --> $DIR/pub-macro-rules.rs:2:5
-   |
-LL |     pub macro_rules! foo {
-   |     ^^^ help: try exporting the macro: `#[macro_export]`
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/feature-gates/feature-gate-pub_macro_rules.rs b/src/test/ui/feature-gates/feature-gate-pub_macro_rules.rs
new file mode 100644
index 00000000000..5504ec317ae
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-pub_macro_rules.rs
@@ -0,0 +1,10 @@
+pub macro_rules! m1 { () => {} } //~ ERROR `pub` on `macro_rules` items is unstable
+
+#[cfg(FALSE)]
+pub macro_rules! m2 { () => {} } //~ ERROR `pub` on `macro_rules` items is unstable
+
+pub(crate) macro_rules! m3 { () => {} } //~ ERROR `pub` on `macro_rules` items is unstable
+
+pub(in self) macro_rules! m4 { () => {} } //~ ERROR `pub` on `macro_rules` items is unstable
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-pub_macro_rules.stderr b/src/test/ui/feature-gates/feature-gate-pub_macro_rules.stderr
new file mode 100644
index 00000000000..bfaec398d9a
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-pub_macro_rules.stderr
@@ -0,0 +1,39 @@
+error[E0658]: `pub` on `macro_rules` items is unstable
+  --> $DIR/feature-gate-pub_macro_rules.rs:1:1
+   |
+LL | pub macro_rules! m1 { () => {} }
+   | ^^^
+   |
+   = note: see issue #78855 <https://github.com/rust-lang/rust/issues/78855> for more information
+   = help: add `#![feature(pub_macro_rules)]` to the crate attributes to enable
+
+error[E0658]: `pub` on `macro_rules` items is unstable
+  --> $DIR/feature-gate-pub_macro_rules.rs:4:1
+   |
+LL | pub macro_rules! m2 { () => {} }
+   | ^^^
+   |
+   = note: see issue #78855 <https://github.com/rust-lang/rust/issues/78855> for more information
+   = help: add `#![feature(pub_macro_rules)]` to the crate attributes to enable
+
+error[E0658]: `pub` on `macro_rules` items is unstable
+  --> $DIR/feature-gate-pub_macro_rules.rs:6:1
+   |
+LL | pub(crate) macro_rules! m3 { () => {} }
+   | ^^^^^^^^^^
+   |
+   = note: see issue #78855 <https://github.com/rust-lang/rust/issues/78855> for more information
+   = help: add `#![feature(pub_macro_rules)]` to the crate attributes to enable
+
+error[E0658]: `pub` on `macro_rules` items is unstable
+  --> $DIR/feature-gate-pub_macro_rules.rs:8:1
+   |
+LL | pub(in self) macro_rules! m4 { () => {} }
+   | ^^^^^^^^^^^^
+   |
+   = note: see issue #78855 <https://github.com/rust-lang/rust/issues/78855> for more information
+   = help: add `#![feature(pub_macro_rules)]` to the crate attributes to enable
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/macros/macro-export-on-modularized-macros.rs b/src/test/ui/macros/macro-export-on-modularized-macros.rs
new file mode 100644
index 00000000000..467c6ba7b78
--- /dev/null
+++ b/src/test/ui/macros/macro-export-on-modularized-macros.rs
@@ -0,0 +1,11 @@
+#![feature(decl_macro)]
+#![feature(pub_macro_rules)]
+
+#[macro_export]
+macro m1() {} //~ ERROR `#[macro_export]` cannot be used on `macro` items
+
+#[macro_export]
+pub macro_rules! m2 { () => {} }
+//~^ ERROR `#[macro_export]` cannot be used on `macro_rules` with `pub`
+
+fn main() {}
diff --git a/src/test/ui/macros/macro-export-on-modularized-macros.stderr b/src/test/ui/macros/macro-export-on-modularized-macros.stderr
new file mode 100644
index 00000000000..8bb031e12cb
--- /dev/null
+++ b/src/test/ui/macros/macro-export-on-modularized-macros.stderr
@@ -0,0 +1,14 @@
+error: `#[macro_export]` cannot be used on `macro` items
+  --> $DIR/macro-export-on-modularized-macros.rs:5:1
+   |
+LL | macro m1() {}
+   | ^^^^^^^^^^^^^
+
+error: `#[macro_export]` cannot be used on `macro_rules` with `pub`
+  --> $DIR/macro-export-on-modularized-macros.rs:8:1
+   |
+LL | pub macro_rules! m2 { () => {} }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/macros/pub-macro-rules-fail.rs b/src/test/ui/macros/pub-macro-rules-fail.rs
new file mode 100644
index 00000000000..bdb4c73f18b
--- /dev/null
+++ b/src/test/ui/macros/pub-macro-rules-fail.rs
@@ -0,0 +1,28 @@
+#![feature(pub_macro_rules)]
+
+#[macro_use]
+mod m {
+    pub macro_rules! mac { () => {} }
+
+    // `pub` `macro_rules` cannot be redefined in the same module.
+    pub macro_rules! mac { () => {} } //~ ERROR the name `mac` is defined multiple times
+
+    pub(self) macro_rules! private_mac { () => {} }
+}
+
+const _: () = {
+    pub macro_rules! block_mac { () => {} }
+};
+
+mod n {
+    // Scope of `pub` `macro_rules` is not extended by `#[macro_use]`.
+    mac!(); //~ ERROR cannot find macro `mac` in this scope
+
+    // `pub` `macro_rules` doesn't put the macro into the root module, unlike `#[macro_export]`.
+    crate::mac!(); //~ ERROR failed to resolve: maybe a missing crate `mac`
+    crate::block_mac!(); //~ ERROR failed to resolve: maybe a missing crate `block_mac`
+
+    crate::m::private_mac!(); //~ ERROR macro `private_mac` is private
+}
+
+fn main() {}
diff --git a/src/test/ui/macros/pub-macro-rules-fail.stderr b/src/test/ui/macros/pub-macro-rules-fail.stderr
new file mode 100644
index 00000000000..588d79dd76a
--- /dev/null
+++ b/src/test/ui/macros/pub-macro-rules-fail.stderr
@@ -0,0 +1,48 @@
+error[E0428]: the name `mac` is defined multiple times
+  --> $DIR/pub-macro-rules-fail.rs:8:5
+   |
+LL |     pub macro_rules! mac { () => {} }
+   |     -------------------- previous definition of the macro `mac` here
+...
+LL |     pub macro_rules! mac { () => {} }
+   |     ^^^^^^^^^^^^^^^^^^^^ `mac` redefined here
+   |
+   = note: `mac` must be defined only once in the macro namespace of this module
+
+error[E0433]: failed to resolve: maybe a missing crate `mac`?
+  --> $DIR/pub-macro-rules-fail.rs:22:12
+   |
+LL |     crate::mac!();
+   |            ^^^ maybe a missing crate `mac`?
+
+error[E0433]: failed to resolve: maybe a missing crate `block_mac`?
+  --> $DIR/pub-macro-rules-fail.rs:23:12
+   |
+LL |     crate::block_mac!();
+   |            ^^^^^^^^^ maybe a missing crate `block_mac`?
+
+error: cannot find macro `mac` in this scope
+  --> $DIR/pub-macro-rules-fail.rs:19:5
+   |
+LL |     mac!();
+   |     ^^^
+   |
+   = note: consider importing this macro:
+           m::mac
+
+error[E0603]: macro `private_mac` is private
+  --> $DIR/pub-macro-rules-fail.rs:25:15
+   |
+LL |     crate::m::private_mac!();
+   |               ^^^^^^^^^^^ private macro
+   |
+note: the macro `private_mac` is defined here
+  --> $DIR/pub-macro-rules-fail.rs:10:5
+   |
+LL |     pub(self) macro_rules! private_mac { () => {} }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0428, E0433, E0603.
+For more information about an error, try `rustc --explain E0428`.
diff --git a/src/test/ui/macros/pub-macro-rules.rs b/src/test/ui/macros/pub-macro-rules.rs
new file mode 100644
index 00000000000..cd4a845f7c0
--- /dev/null
+++ b/src/test/ui/macros/pub-macro-rules.rs
@@ -0,0 +1,20 @@
+// check-pass
+
+#![feature(pub_macro_rules)]
+
+mod m {
+    // `pub` `macro_rules` can be used earlier in item order than they are defined.
+    foo!();
+
+    pub macro_rules! foo { () => {} }
+
+    // `pub(...)` works too.
+    pub(super) macro_rules! bar { () => {} }
+}
+
+// `pub` `macro_rules` are available by module path.
+m::foo!();
+
+m::bar!();
+
+fn main() {}