about summary refs log tree commit diff
path: root/src/libsyntax_expand
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-11-04 12:16:00 +0000
committerbors <bors@rust-lang.org>2019-11-04 12:16:00 +0000
commit2477e2493e67527fc282c7239e019f7ebd513a1a (patch)
tree69f87eb309163474b2fd45d98ec4dd1413cc4e9d /src/libsyntax_expand
parentab6e47851b51a413db5d721f25d714653e7549fd (diff)
parente7cedc9972ae753402fece658b5b9f580f4fc5f3 (diff)
downloadrust-2477e2493e67527fc282c7239e019f7ebd513a1a.tar.gz
rust-2477e2493e67527fc282c7239e019f7ebd513a1a.zip
Auto merge of #66078 - petrochenkov:gateout, r=Centril
expand: Feature gate out-of-line modules in proc macro input

Extracted from https://github.com/rust-lang/rust/pull/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.
Diffstat (limited to 'src/libsyntax_expand')
-rw-r--r--src/libsyntax_expand/expand.rs66
1 files changed, 50 insertions, 16 deletions
diff --git a/src/libsyntax_expand/expand.rs b/src/libsyntax_expand/expand.rs
index fc521e5edc0..bdb50dbfb4f 100644
--- a/src/libsyntax_expand/expand.rs
+++ b/src/libsyntax_expand/expand.rs
@@ -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 |