Skip to content

Commit 2477e24

Browse files
committed
Auto merge of #66078 - petrochenkov:gateout, r=Centril
expand: Feature gate out-of-line modules in proc macro input Extracted from #64273. We are currently gating attributes applied directly to `mod` items because there are unresolved questions about out-of-line modules and their behavior is very likely to change. However, you can sneak an out-of-line module into an attribute macro input using modules nested into other items like ```rust #[my_attr] fn m() { #[path = "zzz.rs"] mod n; // what tokens does the `my_attr` macro see? } ``` This PR prevents that and emits a feature gate error for this case as well. r? @Centril It would be great to land this before beta.
2 parents ab6e478 + e7cedc9 commit 2477e24

7 files changed

+182
-16
lines changed

src/libsyntax_expand/expand.rs

+50-16
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@ use syntax::parse::token;
1717
use syntax::parse::parser::Parser;
1818
use syntax::print::pprust;
1919
use syntax::ptr::P;
20+
use syntax::sess::ParseSess;
2021
use syntax::symbol::{sym, Symbol};
2122
use syntax::tokenstream::{TokenStream, TokenTree};
22-
use syntax::visit::Visitor;
23+
use syntax::visit::{self, Visitor};
2324
use syntax::util::map_in_place::MapInPlace;
2425

2526
use errors::{Applicability, FatalError};
@@ -615,6 +616,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
615616
}
616617
InvocationKind::Attr { attr, mut item, .. } => match ext {
617618
SyntaxExtensionKind::Attr(expander) => {
619+
self.gate_proc_macro_input(&item);
618620
self.gate_proc_macro_attr_item(span, &item);
619621
let item_tok = TokenTree::token(token::Interpolated(Lrc::new(match item {
620622
Annotatable::Item(item) => token::NtItem(item),
@@ -664,6 +666,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
664666
if !item.derive_allowed() {
665667
return fragment_kind.dummy(span);
666668
}
669+
if let SyntaxExtensionKind::Derive(..) = ext {
670+
self.gate_proc_macro_input(&item);
671+
}
667672
let meta = ast::MetaItem { kind: ast::MetaItemKind::Word, span, path };
668673
let items = expander.expand(self.cx, span, &meta, item);
669674
fragment_kind.expect_from_annotatables(items)
@@ -692,21 +697,16 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
692697
}
693698

694699
fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) {
695-
let (kind, gate) = match *item {
696-
Annotatable::Item(ref item) => {
697-
match item.kind {
698-
ItemKind::Mod(_) if self.cx.ecfg.proc_macro_hygiene() => return,
699-
ItemKind::Mod(_) => ("modules", sym::proc_macro_hygiene),
700-
_ => return,
701-
}
700+
let kind = match item {
701+
Annotatable::Item(item) => match &item.kind {
702+
ItemKind::Mod(m) if m.inline => "modules",
703+
_ => return,
702704
}
703-
Annotatable::TraitItem(_) => return,
704-
Annotatable::ImplItem(_) => return,
705-
Annotatable::ForeignItem(_) => return,
706-
Annotatable::Stmt(_) |
707-
Annotatable::Expr(_) if self.cx.ecfg.proc_macro_hygiene() => return,
708-
Annotatable::Stmt(_) => ("statements", sym::proc_macro_hygiene),
709-
Annotatable::Expr(_) => ("expressions", sym::proc_macro_hygiene),
705+
Annotatable::TraitItem(_)
706+
| Annotatable::ImplItem(_)
707+
| Annotatable::ForeignItem(_) => return,
708+
Annotatable::Stmt(_) => "statements",
709+
Annotatable::Expr(_) => "expressions",
710710
Annotatable::Arm(..)
711711
| Annotatable::Field(..)
712712
| Annotatable::FieldPat(..)
@@ -716,15 +716,49 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
716716
| Annotatable::Variant(..)
717717
=> panic!("unexpected annotatable"),
718718
};
719+
if self.cx.ecfg.proc_macro_hygiene() {
720+
return
721+
}
719722
emit_feature_err(
720723
self.cx.parse_sess,
721-
gate,
724+
sym::proc_macro_hygiene,
722725
span,
723726
GateIssue::Language,
724727
&format!("custom attributes cannot be applied to {}", kind),
725728
);
726729
}
727730

731+
fn gate_proc_macro_input(&self, annotatable: &Annotatable) {
732+
struct GateProcMacroInput<'a> {
733+
parse_sess: &'a ParseSess,
734+
}
735+
736+
impl<'ast, 'a> Visitor<'ast> for GateProcMacroInput<'a> {
737+
fn visit_item(&mut self, item: &'ast ast::Item) {
738+
match &item.kind {
739+
ast::ItemKind::Mod(module) if !module.inline => {
740+
emit_feature_err(
741+
self.parse_sess,
742+
sym::proc_macro_hygiene,
743+
item.span,
744+
GateIssue::Language,
745+
"non-inline modules in proc macro input are unstable",
746+
);
747+
}
748+
_ => {}
749+
}
750+
751+
visit::walk_item(self, item);
752+
}
753+
754+
fn visit_mac(&mut self, _: &'ast ast::Mac) {}
755+
}
756+
757+
if !self.cx.ecfg.proc_macro_hygiene() {
758+
annotatable.visit_with(&mut GateProcMacroInput { parse_sess: self.cx.parse_sess });
759+
}
760+
}
761+
728762
fn gate_proc_macro_expansion_kind(&self, span: Span, kind: AstFragmentKind) {
729763
let kind = match kind {
730764
AstFragmentKind::Expr |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// aux-build:test-macros.rs
2+
3+
#[macro_use]
4+
extern crate test_macros;
5+
6+
#[identity_attr] //~ ERROR custom attributes cannot be applied to modules
7+
mod m {
8+
pub struct X;
9+
10+
type A = Y; //~ ERROR cannot find type `Y` in this scope
11+
}
12+
13+
struct Y;
14+
type A = X; //~ ERROR cannot find type `X` in this scope
15+
16+
#[derive(Copy)] //~ ERROR `derive` may only be applied to structs, enums and unions
17+
mod n {}
18+
19+
#[empty_attr]
20+
mod module; //~ ERROR non-inline modules in proc macro input are unstable
21+
22+
#[empty_attr] //~ ERROR custom attributes cannot be applied to modules
23+
mod outer {
24+
mod inner; //~ ERROR non-inline modules in proc macro input are unstable
25+
26+
mod inner_inline {} // OK
27+
}
28+
29+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
error[E0658]: custom attributes cannot be applied to modules
2+
--> $DIR/attributes-on-modules-fail.rs:6:1
3+
|
4+
LL | #[identity_attr]
5+
| ^^^^^^^^^^^^^^^^
6+
|
7+
= note: for more information, see https://github.com/rust-lang/rust/issues/54727
8+
= help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
9+
10+
error: `derive` may only be applied to structs, enums and unions
11+
--> $DIR/attributes-on-modules-fail.rs:16:1
12+
|
13+
LL | #[derive(Copy)]
14+
| ^^^^^^^^^^^^^^^
15+
16+
error[E0658]: non-inline modules in proc macro input are unstable
17+
--> $DIR/attributes-on-modules-fail.rs:20:1
18+
|
19+
LL | mod module;
20+
| ^^^^^^^^^^^
21+
|
22+
= note: for more information, see https://github.com/rust-lang/rust/issues/54727
23+
= help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
24+
25+
error[E0658]: non-inline modules in proc macro input are unstable
26+
--> $DIR/attributes-on-modules-fail.rs:24:5
27+
|
28+
LL | mod inner;
29+
| ^^^^^^^^^^
30+
|
31+
= note: for more information, see https://github.com/rust-lang/rust/issues/54727
32+
= help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
33+
34+
error[E0658]: custom attributes cannot be applied to modules
35+
--> $DIR/attributes-on-modules-fail.rs:22:1
36+
|
37+
LL | #[empty_attr]
38+
| ^^^^^^^^^^^^^
39+
|
40+
= note: for more information, see https://github.com/rust-lang/rust/issues/54727
41+
= help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
42+
43+
error[E0412]: cannot find type `Y` in this scope
44+
--> $DIR/attributes-on-modules-fail.rs:10:14
45+
|
46+
LL | type A = Y;
47+
| ---------^- similarly named type alias `A` defined here
48+
|
49+
help: a type alias with a similar name exists
50+
|
51+
LL | type A = A;
52+
| ^
53+
help: possible candidate is found in another module, you can import it into scope
54+
|
55+
LL | use Y;
56+
|
57+
58+
error[E0412]: cannot find type `X` in this scope
59+
--> $DIR/attributes-on-modules-fail.rs:14:10
60+
|
61+
LL | type A = X;
62+
| ---------^- similarly named type alias `A` defined here
63+
|
64+
help: a type alias with a similar name exists
65+
|
66+
LL | type A = A;
67+
| ^
68+
help: possible candidate is found in another module, you can import it into scope
69+
|
70+
LL | use m::X;
71+
|
72+
73+
error: aborting due to 7 previous errors
74+
75+
Some errors have detailed explanations: E0412, E0658.
76+
For more information about an error, try `rustc --explain E0412`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// aux-build:test-macros.rs
2+
3+
#[macro_use]
4+
extern crate test_macros;
5+
6+
#[identity_attr] //~ ERROR custom attributes cannot be applied to modules
7+
mod m {
8+
pub struct S;
9+
}
10+
11+
fn main() {
12+
let s = m::S;
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0658]: custom attributes cannot be applied to modules
2+
--> $DIR/attributes-on-modules.rs:6:1
3+
|
4+
LL | #[identity_attr]
5+
| ^^^^^^^^^^^^^^^^
6+
|
7+
= note: for more information, see https://github.com/rust-lang/rust/issues/54727
8+
= help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0658`.

src/test/ui/proc-macro/module.rs

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
// ignore-test

src/test/ui/proc-macro/outer/inner.rs

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
// ignore-test

0 commit comments

Comments
 (0)