Skip to content

Commit 7d3bb8b

Browse files
committed
Support pub on macro_rules
1 parent f2ea2f6 commit 7d3bb8b

15 files changed

+184
-35
lines changed

compiler/rustc_ast_passes/src/feature_gate.rs

+1
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
630630
gate_all!(const_trait_impl, "const trait impls are experimental");
631631
gate_all!(half_open_range_patterns, "half-open range patterns are unstable");
632632
gate_all!(inline_const, "inline-const is experimental");
633+
gate_all!(pub_macro_rules, "`pub` on `macro_rules` items is unstable");
633634

634635
// All uses of `gate_all!` below this point were added in #65742,
635636
// and subsequently disabled (with the non-early gating readded).

compiler/rustc_feature/src/active.rs

+3
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,9 @@ declare_features! (
610610
/// Allows unsized fn parameters.
611611
(active, unsized_fn_params, "1.49.0", Some(48055), None),
612612

613+
/// Allows `pub` on `macro_rules` items.
614+
(active, pub_macro_rules, "1.49.0", Some(78855), None),
615+
613616
// -------------------------------------------------------------------------
614617
// feature-group-end: actual feature gates
615618
// -------------------------------------------------------------------------

compiler/rustc_parse/src/parser/item.rs

+1-9
Original file line numberDiff line numberDiff line change
@@ -1406,15 +1406,7 @@ impl<'a> Parser<'a> {
14061406
let vstr = pprust::vis_to_string(vis);
14071407
let vstr = vstr.trim_end();
14081408
if macro_rules {
1409-
let msg = format!("can't qualify macro_rules invocation with `{}`", vstr);
1410-
self.struct_span_err(vis.span, &msg)
1411-
.span_suggestion(
1412-
vis.span,
1413-
"try exporting the macro",
1414-
"#[macro_export]".to_owned(),
1415-
Applicability::MaybeIncorrect, // speculative
1416-
)
1417-
.emit();
1409+
self.sess.gated_spans.gate(sym::pub_macro_rules, vis.span);
14181410
} else {
14191411
self.struct_span_err(vis.span, "can't qualify macro invocation with `pub`")
14201412
.span_suggestion(

compiler/rustc_resolve/src/build_reduced_graph.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -1216,13 +1216,13 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
12161216
};
12171217

12181218
let res = Res::Def(DefKind::Macro(ext.macro_kind()), def_id.to_def_id());
1219+
let is_macro_export = self.r.session.contains_name(&item.attrs, sym::macro_export);
12191220
self.r.macro_map.insert(def_id.to_def_id(), ext);
12201221
self.r.local_macro_def_scopes.insert(def_id, parent_scope.module);
12211222

1222-
if macro_rules {
1223+
if macro_rules && matches!(item.vis.kind, ast::VisibilityKind::Inherited) {
12231224
let ident = ident.normalize_to_macros_2_0();
12241225
self.r.macro_names.insert(ident);
1225-
let is_macro_export = self.r.session.contains_name(&item.attrs, sym::macro_export);
12261226
let vis = if is_macro_export {
12271227
ty::Visibility::Public
12281228
} else {
@@ -1245,6 +1245,11 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
12451245
ident,
12461246
}))
12471247
} else {
1248+
if is_macro_export {
1249+
let what = if macro_rules { "`macro_rules` with `pub`" } else { "`macro` items" };
1250+
let msg = format!("`#[macro_export]` cannot be used on {what}");
1251+
self.r.session.span_err(item.span, &msg);
1252+
}
12481253
let module = parent_scope.module;
12491254
let vis = match item.kind {
12501255
// Visibilities must not be resolved non-speculatively twice

compiler/rustc_resolve/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
1212
#![feature(bool_to_option)]
1313
#![feature(crate_visibility_modifier)]
14+
#![feature(format_args_capture)]
1415
#![feature(nll)]
1516
#![feature(or_patterns)]
1617
#![recursion_limit = "256"]

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -841,6 +841,7 @@ symbols! {
841841
ptr_guaranteed_eq,
842842
ptr_guaranteed_ne,
843843
ptr_offset_from,
844+
pub_macro_rules,
844845
pub_restricted,
845846
pure,
846847
pushpop_unsafe,

src/test/ui/did_you_mean/pub-macro-rules.rs

-16
This file was deleted.

src/test/ui/did_you_mean/pub-macro-rules.stderr

-8
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
pub macro_rules! m1 { () => {} } //~ ERROR `pub` on `macro_rules` items is unstable
2+
3+
#[cfg(FALSE)]
4+
pub macro_rules! m2 { () => {} } //~ ERROR `pub` on `macro_rules` items is unstable
5+
6+
pub(crate) macro_rules! m3 { () => {} } //~ ERROR `pub` on `macro_rules` items is unstable
7+
8+
pub(in self) macro_rules! m4 { () => {} } //~ ERROR `pub` on `macro_rules` items is unstable
9+
10+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
error[E0658]: `pub` on `macro_rules` items is unstable
2+
--> $DIR/feature-gate-pub_macro_rules.rs:1:1
3+
|
4+
LL | pub macro_rules! m1 { () => {} }
5+
| ^^^
6+
|
7+
= note: see issue #78855 <https://github.com/rust-lang/rust/issues/78855> for more information
8+
= help: add `#![feature(pub_macro_rules)]` to the crate attributes to enable
9+
10+
error[E0658]: `pub` on `macro_rules` items is unstable
11+
--> $DIR/feature-gate-pub_macro_rules.rs:4:1
12+
|
13+
LL | pub macro_rules! m2 { () => {} }
14+
| ^^^
15+
|
16+
= note: see issue #78855 <https://github.com/rust-lang/rust/issues/78855> for more information
17+
= help: add `#![feature(pub_macro_rules)]` to the crate attributes to enable
18+
19+
error[E0658]: `pub` on `macro_rules` items is unstable
20+
--> $DIR/feature-gate-pub_macro_rules.rs:6:1
21+
|
22+
LL | pub(crate) macro_rules! m3 { () => {} }
23+
| ^^^^^^^^^^
24+
|
25+
= note: see issue #78855 <https://github.com/rust-lang/rust/issues/78855> for more information
26+
= help: add `#![feature(pub_macro_rules)]` to the crate attributes to enable
27+
28+
error[E0658]: `pub` on `macro_rules` items is unstable
29+
--> $DIR/feature-gate-pub_macro_rules.rs:8:1
30+
|
31+
LL | pub(in self) macro_rules! m4 { () => {} }
32+
| ^^^^^^^^^^^^
33+
|
34+
= note: see issue #78855 <https://github.com/rust-lang/rust/issues/78855> for more information
35+
= help: add `#![feature(pub_macro_rules)]` to the crate attributes to enable
36+
37+
error: aborting due to 4 previous errors
38+
39+
For more information about this error, try `rustc --explain E0658`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#![feature(decl_macro)]
2+
#![feature(pub_macro_rules)]
3+
4+
#[macro_export]
5+
macro m1() {} //~ ERROR `#[macro_export]` cannot be used on `macro` items
6+
7+
#[macro_export]
8+
pub macro_rules! m2 { () => {} }
9+
//~^ ERROR `#[macro_export]` cannot be used on `macro_rules` with `pub`
10+
11+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: `#[macro_export]` cannot be used on `macro` items
2+
--> $DIR/macro-export-on-modularized-macros.rs:5:1
3+
|
4+
LL | macro m1() {}
5+
| ^^^^^^^^^^^^^
6+
7+
error: `#[macro_export]` cannot be used on `macro_rules` with `pub`
8+
--> $DIR/macro-export-on-modularized-macros.rs:8:1
9+
|
10+
LL | pub macro_rules! m2 { () => {} }
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
13+
error: aborting due to 2 previous errors
14+
+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#![feature(pub_macro_rules)]
2+
3+
#[macro_use]
4+
mod m {
5+
pub macro_rules! mac { () => {} }
6+
7+
// `pub` `macro_rules` cannot be redefined in the same module.
8+
pub macro_rules! mac { () => {} } //~ ERROR the name `mac` is defined multiple times
9+
10+
pub(self) macro_rules! private_mac { () => {} }
11+
}
12+
13+
const _: () = {
14+
pub macro_rules! block_mac { () => {} }
15+
};
16+
17+
mod n {
18+
// Scope of `pub` `macro_rules` is not extended by `#[macro_use]`.
19+
mac!(); //~ ERROR cannot find macro `mac` in this scope
20+
21+
// `pub` `macro_rules` doesn't put the macro into the root module, unlike `#[macro_export]`.
22+
crate::mac!(); //~ ERROR failed to resolve: maybe a missing crate `mac`
23+
crate::block_mac!(); //~ ERROR failed to resolve: maybe a missing crate `block_mac`
24+
25+
crate::m::private_mac!(); //~ ERROR macro `private_mac` is private
26+
}
27+
28+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
error[E0428]: the name `mac` is defined multiple times
2+
--> $DIR/pub-macro-rules-fail.rs:8:5
3+
|
4+
LL | pub macro_rules! mac { () => {} }
5+
| -------------------- previous definition of the macro `mac` here
6+
...
7+
LL | pub macro_rules! mac { () => {} }
8+
| ^^^^^^^^^^^^^^^^^^^^ `mac` redefined here
9+
|
10+
= note: `mac` must be defined only once in the macro namespace of this module
11+
12+
error[E0433]: failed to resolve: maybe a missing crate `mac`?
13+
--> $DIR/pub-macro-rules-fail.rs:22:12
14+
|
15+
LL | crate::mac!();
16+
| ^^^ maybe a missing crate `mac`?
17+
18+
error[E0433]: failed to resolve: maybe a missing crate `block_mac`?
19+
--> $DIR/pub-macro-rules-fail.rs:23:12
20+
|
21+
LL | crate::block_mac!();
22+
| ^^^^^^^^^ maybe a missing crate `block_mac`?
23+
24+
error: cannot find macro `mac` in this scope
25+
--> $DIR/pub-macro-rules-fail.rs:19:5
26+
|
27+
LL | mac!();
28+
| ^^^
29+
|
30+
= note: consider importing this macro:
31+
m::mac
32+
33+
error[E0603]: macro `private_mac` is private
34+
--> $DIR/pub-macro-rules-fail.rs:25:15
35+
|
36+
LL | crate::m::private_mac!();
37+
| ^^^^^^^^^^^ private macro
38+
|
39+
note: the macro `private_mac` is defined here
40+
--> $DIR/pub-macro-rules-fail.rs:10:5
41+
|
42+
LL | pub(self) macro_rules! private_mac { () => {} }
43+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
44+
45+
error: aborting due to 5 previous errors
46+
47+
Some errors have detailed explanations: E0428, E0433, E0603.
48+
For more information about an error, try `rustc --explain E0428`.

src/test/ui/macros/pub-macro-rules.rs

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// check-pass
2+
3+
#![feature(pub_macro_rules)]
4+
5+
mod m {
6+
// `pub` `macro_rules` can be used earlier in item order than they are defined.
7+
foo!();
8+
9+
pub macro_rules! foo { () => {} }
10+
11+
// `pub(...)` works too.
12+
pub(super) macro_rules! bar { () => {} }
13+
}
14+
15+
// `pub` `macro_rules` are available by module path.
16+
m::foo!();
17+
18+
m::bar!();
19+
20+
fn main() {}

0 commit comments

Comments
 (0)