expand: Feature gate out-of-line modules in proc macro input
This commit is contained in:
parent
cba9368537
commit
e7cedc9972
7 changed files with 182 additions and 16 deletions
|
@ -17,9 +17,10 @@ use syntax::parse::token;
|
||||||
use syntax::parse::parser::Parser;
|
use syntax::parse::parser::Parser;
|
||||||
use syntax::print::pprust;
|
use syntax::print::pprust;
|
||||||
use syntax::ptr::P;
|
use syntax::ptr::P;
|
||||||
|
use syntax::sess::ParseSess;
|
||||||
use syntax::symbol::{sym, Symbol};
|
use syntax::symbol::{sym, Symbol};
|
||||||
use syntax::tokenstream::{TokenStream, TokenTree};
|
use syntax::tokenstream::{TokenStream, TokenTree};
|
||||||
use syntax::visit::Visitor;
|
use syntax::visit::{self, Visitor};
|
||||||
use syntax::util::map_in_place::MapInPlace;
|
use syntax::util::map_in_place::MapInPlace;
|
||||||
|
|
||||||
use errors::{Applicability, FatalError};
|
use errors::{Applicability, FatalError};
|
||||||
|
@ -615,6 +616,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||||
}
|
}
|
||||||
InvocationKind::Attr { attr, mut item, .. } => match ext {
|
InvocationKind::Attr { attr, mut item, .. } => match ext {
|
||||||
SyntaxExtensionKind::Attr(expander) => {
|
SyntaxExtensionKind::Attr(expander) => {
|
||||||
|
self.gate_proc_macro_input(&item);
|
||||||
self.gate_proc_macro_attr_item(span, &item);
|
self.gate_proc_macro_attr_item(span, &item);
|
||||||
let item_tok = TokenTree::token(token::Interpolated(Lrc::new(match item {
|
let item_tok = TokenTree::token(token::Interpolated(Lrc::new(match item {
|
||||||
Annotatable::Item(item) => token::NtItem(item),
|
Annotatable::Item(item) => token::NtItem(item),
|
||||||
|
@ -664,6 +666,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||||
if !item.derive_allowed() {
|
if !item.derive_allowed() {
|
||||||
return fragment_kind.dummy(span);
|
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 meta = ast::MetaItem { kind: ast::MetaItemKind::Word, span, path };
|
||||||
let items = expander.expand(self.cx, span, &meta, item);
|
let items = expander.expand(self.cx, span, &meta, item);
|
||||||
fragment_kind.expect_from_annotatables(items)
|
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) {
|
fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) {
|
||||||
let (kind, gate) = match *item {
|
let kind = match item {
|
||||||
Annotatable::Item(ref item) => {
|
Annotatable::Item(item) => match &item.kind {
|
||||||
match item.kind {
|
ItemKind::Mod(m) if m.inline => "modules",
|
||||||
ItemKind::Mod(_) if self.cx.ecfg.proc_macro_hygiene() => return,
|
_ => return,
|
||||||
ItemKind::Mod(_) => ("modules", sym::proc_macro_hygiene),
|
|
||||||
_ => return,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Annotatable::TraitItem(_) => return,
|
Annotatable::TraitItem(_)
|
||||||
Annotatable::ImplItem(_) => return,
|
| Annotatable::ImplItem(_)
|
||||||
Annotatable::ForeignItem(_) => return,
|
| Annotatable::ForeignItem(_) => return,
|
||||||
Annotatable::Stmt(_) |
|
Annotatable::Stmt(_) => "statements",
|
||||||
Annotatable::Expr(_) if self.cx.ecfg.proc_macro_hygiene() => return,
|
Annotatable::Expr(_) => "expressions",
|
||||||
Annotatable::Stmt(_) => ("statements", sym::proc_macro_hygiene),
|
|
||||||
Annotatable::Expr(_) => ("expressions", sym::proc_macro_hygiene),
|
|
||||||
Annotatable::Arm(..)
|
Annotatable::Arm(..)
|
||||||
| Annotatable::Field(..)
|
| Annotatable::Field(..)
|
||||||
| Annotatable::FieldPat(..)
|
| Annotatable::FieldPat(..)
|
||||||
|
@ -716,15 +716,49 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||||
| Annotatable::Variant(..)
|
| Annotatable::Variant(..)
|
||||||
=> panic!("unexpected annotatable"),
|
=> panic!("unexpected annotatable"),
|
||||||
};
|
};
|
||||||
|
if self.cx.ecfg.proc_macro_hygiene() {
|
||||||
|
return
|
||||||
|
}
|
||||||
emit_feature_err(
|
emit_feature_err(
|
||||||
self.cx.parse_sess,
|
self.cx.parse_sess,
|
||||||
gate,
|
sym::proc_macro_hygiene,
|
||||||
span,
|
span,
|
||||||
GateIssue::Language,
|
GateIssue::Language,
|
||||||
&format!("custom attributes cannot be applied to {}", kind),
|
&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) {
|
fn gate_proc_macro_expansion_kind(&self, span: Span, kind: AstFragmentKind) {
|
||||||
let kind = match kind {
|
let kind = match kind {
|
||||||
AstFragmentKind::Expr |
|
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…
Add table
Add a link
Reference in a new issue