Skip to content

Commit

Permalink
Auto merge of #66078 - petrochenkov:gateout, r=Centril
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
bors committed Nov 4, 2019
2 parents ab6e478 + e7cedc9 commit 2477e24
Show file tree
Hide file tree
Showing 7 changed files with 182 additions and 16 deletions.
66 changes: 50 additions & 16 deletions src/libsyntax_expand/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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(..)
Expand All @@ -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 |
Expand Down
29 changes: 29 additions & 0 deletions src/test/ui/proc-macro/attributes-on-modules-fail.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 76 additions & 0 deletions src/test/ui/proc-macro/attributes-on-modules-fail.stderr
Original file line number Diff line number Diff line change
@@ -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 changes: 13 additions & 0 deletions src/test/ui/proc-macro/attributes-on-modules.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 12 additions & 0 deletions src/test/ui/proc-macro/attributes-on-modules.stderr
Original file line number Diff line number Diff line change
@@ -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 change: 1 addition & 0 deletions src/test/ui/proc-macro/module.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// ignore-test
1 change: 1 addition & 0 deletions src/test/ui/proc-macro/outer/inner.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// ignore-test

0 comments on commit 2477e24

Please sign in to comment.