expand: Feature gate out-of-line modules in proc macro input
This commit is contained in:
parent
cba9368537
commit
e7cedc9972
@ -17,9 +17,10 @@ use syntax::parse::token;
|
||||
use syntax::parse::parser::Parser;
|
||||
use syntax::print::pprust;
|
||||
use syntax::ptr::P;
|
||||
use syntax::sess::ParseSess;
|
||||
use syntax::symbol::{sym, Symbol};
|
||||
use syntax::tokenstream::{TokenStream, TokenTree};
|
||||
use syntax::visit::Visitor;
|
||||
use syntax::visit::{self, Visitor};
|
||||
use syntax::util::map_in_place::MapInPlace;
|
||||
|
||||
use errors::{Applicability, FatalError};
|
||||
@ -615,6 +616,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
}
|
||||
InvocationKind::Attr { attr, mut item, .. } => match ext {
|
||||
SyntaxExtensionKind::Attr(expander) => {
|
||||
self.gate_proc_macro_input(&item);
|
||||
self.gate_proc_macro_attr_item(span, &item);
|
||||
let item_tok = TokenTree::token(token::Interpolated(Lrc::new(match item {
|
||||
Annotatable::Item(item) => token::NtItem(item),
|
||||
@ -664,6 +666,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
if !item.derive_allowed() {
|
||||
return fragment_kind.dummy(span);
|
||||
}
|
||||
if let SyntaxExtensionKind::Derive(..) = ext {
|
||||
self.gate_proc_macro_input(&item);
|
||||
}
|
||||
let meta = ast::MetaItem { kind: ast::MetaItemKind::Word, span, path };
|
||||
let items = expander.expand(self.cx, span, &meta, item);
|
||||
fragment_kind.expect_from_annotatables(items)
|
||||
@ -692,21 +697,16 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
}
|
||||
|
||||
fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) {
|
||||
let (kind, gate) = match *item {
|
||||
Annotatable::Item(ref item) => {
|
||||
match item.kind {
|
||||
ItemKind::Mod(_) if self.cx.ecfg.proc_macro_hygiene() => return,
|
||||
ItemKind::Mod(_) => ("modules", sym::proc_macro_hygiene),
|
||||
_ => return,
|
||||
}
|
||||
let kind = match item {
|
||||
Annotatable::Item(item) => match &item.kind {
|
||||
ItemKind::Mod(m) if m.inline => "modules",
|
||||
_ => return,
|
||||
}
|
||||
Annotatable::TraitItem(_) => return,
|
||||
Annotatable::ImplItem(_) => return,
|
||||
Annotatable::ForeignItem(_) => return,
|
||||
Annotatable::Stmt(_) |
|
||||
Annotatable::Expr(_) if self.cx.ecfg.proc_macro_hygiene() => return,
|
||||
Annotatable::Stmt(_) => ("statements", sym::proc_macro_hygiene),
|
||||
Annotatable::Expr(_) => ("expressions", sym::proc_macro_hygiene),
|
||||
Annotatable::TraitItem(_)
|
||||
| Annotatable::ImplItem(_)
|
||||
| Annotatable::ForeignItem(_) => return,
|
||||
Annotatable::Stmt(_) => "statements",
|
||||
Annotatable::Expr(_) => "expressions",
|
||||
Annotatable::Arm(..)
|
||||
| Annotatable::Field(..)
|
||||
| Annotatable::FieldPat(..)
|
||||
@ -716,15 +716,49 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
| Annotatable::Variant(..)
|
||||
=> panic!("unexpected annotatable"),
|
||||
};
|
||||
if self.cx.ecfg.proc_macro_hygiene() {
|
||||
return
|
||||
}
|
||||
emit_feature_err(
|
||||
self.cx.parse_sess,
|
||||
gate,
|
||||
sym::proc_macro_hygiene,
|
||||
span,
|
||||
GateIssue::Language,
|
||||
&format!("custom attributes cannot be applied to {}", kind),
|
||||
);
|
||||
}
|
||||
|
||||
fn gate_proc_macro_input(&self, annotatable: &Annotatable) {
|
||||
struct GateProcMacroInput<'a> {
|
||||
parse_sess: &'a ParseSess,
|
||||
}
|
||||
|
||||
impl<'ast, 'a> Visitor<'ast> for GateProcMacroInput<'a> {
|
||||
fn visit_item(&mut self, item: &'ast ast::Item) {
|
||||
match &item.kind {
|
||||
ast::ItemKind::Mod(module) if !module.inline => {
|
||||
emit_feature_err(
|
||||
self.parse_sess,
|
||||
sym::proc_macro_hygiene,
|
||||
item.span,
|
||||
GateIssue::Language,
|
||||
"non-inline modules in proc macro input are unstable",
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
visit::walk_item(self, item);
|
||||
}
|
||||
|
||||
fn visit_mac(&mut self, _: &'ast ast::Mac) {}
|
||||
}
|
||||
|
||||
if !self.cx.ecfg.proc_macro_hygiene() {
|
||||
annotatable.visit_with(&mut GateProcMacroInput { parse_sess: self.cx.parse_sess });
|
||||
}
|
||||
}
|
||||
|
||||
fn gate_proc_macro_expansion_kind(&self, span: Span, kind: AstFragmentKind) {
|
||||
let kind = match kind {
|
||||
AstFragmentKind::Expr |
|
||||
|
29
src/test/ui/proc-macro/attributes-on-modules-fail.rs
Normal file
29
src/test/ui/proc-macro/attributes-on-modules-fail.rs
Normal file
@ -0,0 +1,29 @@
|
||||
// aux-build:test-macros.rs
|
||||
|
||||
#[macro_use]
|
||||
extern crate test_macros;
|
||||
|
||||
#[identity_attr] //~ ERROR custom attributes cannot be applied to modules
|
||||
mod m {
|
||||
pub struct X;
|
||||
|
||||
type A = Y; //~ ERROR cannot find type `Y` in this scope
|
||||
}
|
||||
|
||||
struct Y;
|
||||
type A = X; //~ ERROR cannot find type `X` in this scope
|
||||
|
||||
#[derive(Copy)] //~ ERROR `derive` may only be applied to structs, enums and unions
|
||||
mod n {}
|
||||
|
||||
#[empty_attr]
|
||||
mod module; //~ ERROR non-inline modules in proc macro input are unstable
|
||||
|
||||
#[empty_attr] //~ ERROR custom attributes cannot be applied to modules
|
||||
mod outer {
|
||||
mod inner; //~ ERROR non-inline modules in proc macro input are unstable
|
||||
|
||||
mod inner_inline {} // OK
|
||||
}
|
||||
|
||||
fn main() {}
|
76
src/test/ui/proc-macro/attributes-on-modules-fail.stderr
Normal file
76
src/test/ui/proc-macro/attributes-on-modules-fail.stderr
Normal file
@ -0,0 +1,76 @@
|
||||
error[E0658]: custom attributes cannot be applied to modules
|
||||
--> $DIR/attributes-on-modules-fail.rs:6:1
|
||||
|
|
||||
LL | #[identity_attr]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/54727
|
||||
= help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
|
||||
|
||||
error: `derive` may only be applied to structs, enums and unions
|
||||
--> $DIR/attributes-on-modules-fail.rs:16:1
|
||||
|
|
||||
LL | #[derive(Copy)]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0658]: non-inline modules in proc macro input are unstable
|
||||
--> $DIR/attributes-on-modules-fail.rs:20:1
|
||||
|
|
||||
LL | mod module;
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/54727
|
||||
= help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: non-inline modules in proc macro input are unstable
|
||||
--> $DIR/attributes-on-modules-fail.rs:24:5
|
||||
|
|
||||
LL | mod inner;
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/54727
|
||||
= help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: custom attributes cannot be applied to modules
|
||||
--> $DIR/attributes-on-modules-fail.rs:22:1
|
||||
|
|
||||
LL | #[empty_attr]
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/54727
|
||||
= help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
|
||||
|
||||
error[E0412]: cannot find type `Y` in this scope
|
||||
--> $DIR/attributes-on-modules-fail.rs:10:14
|
||||
|
|
||||
LL | type A = Y;
|
||||
| ---------^- similarly named type alias `A` defined here
|
||||
|
|
||||
help: a type alias with a similar name exists
|
||||
|
|
||||
LL | type A = A;
|
||||
| ^
|
||||
help: possible candidate is found in another module, you can import it into scope
|
||||
|
|
||||
LL | use Y;
|
||||
|
|
||||
|
||||
error[E0412]: cannot find type `X` in this scope
|
||||
--> $DIR/attributes-on-modules-fail.rs:14:10
|
||||
|
|
||||
LL | type A = X;
|
||||
| ---------^- similarly named type alias `A` defined here
|
||||
|
|
||||
help: a type alias with a similar name exists
|
||||
|
|
||||
LL | type A = A;
|
||||
| ^
|
||||
help: possible candidate is found in another module, you can import it into scope
|
||||
|
|
||||
LL | use m::X;
|
||||
|
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0412, E0658.
|
||||
For more information about an error, try `rustc --explain E0412`.
|
13
src/test/ui/proc-macro/attributes-on-modules.rs
Normal file
13
src/test/ui/proc-macro/attributes-on-modules.rs
Normal file
@ -0,0 +1,13 @@
|
||||
// aux-build:test-macros.rs
|
||||
|
||||
#[macro_use]
|
||||
extern crate test_macros;
|
||||
|
||||
#[identity_attr] //~ ERROR custom attributes cannot be applied to modules
|
||||
mod m {
|
||||
pub struct S;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let s = m::S;
|
||||
}
|
12
src/test/ui/proc-macro/attributes-on-modules.stderr
Normal file
12
src/test/ui/proc-macro/attributes-on-modules.stderr
Normal file
@ -0,0 +1,12 @@
|
||||
error[E0658]: custom attributes cannot be applied to modules
|
||||
--> $DIR/attributes-on-modules.rs:6:1
|
||||
|
|
||||
LL | #[identity_attr]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/54727
|
||||
= help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
1
src/test/ui/proc-macro/module.rs
Normal file
1
src/test/ui/proc-macro/module.rs
Normal file
@ -0,0 +1 @@
|
||||
// ignore-test
|
1
src/test/ui/proc-macro/outer/inner.rs
Normal file
1
src/test/ui/proc-macro/outer/inner.rs
Normal file
@ -0,0 +1 @@
|
||||
// ignore-test
|
Loading…
x
Reference in New Issue
Block a user