about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2021-01-17 16:05:02 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2021-02-07 20:08:45 +0300
commitf6caae52c1622a3c4f154eadaad615b577ceb6a8 (patch)
treef12c1b7f31102b6f27d96f8d7944e7a4a6e0bfec
parentdbdbd30bf2cb0d48c8bbce83c2458592664dbb18 (diff)
downloadrust-f6caae52c1622a3c4f154eadaad615b577ceb6a8.tar.gz
rust-f6caae52c1622a3c4f154eadaad615b577ceb6a8.zip
Feature gate macro attributes in `#[derive]` output
-rw-r--r--compiler/rustc_feature/src/active.rs4
-rw-r--r--compiler/rustc_resolve/src/macros.rs30
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--src/test/ui/proc-macro/attribute-after-derive-feature-gate.rs28
-rw-r--r--src/test/ui/proc-macro/attribute-after-derive-feature-gate.stderr30
-rw-r--r--src/test/ui/proc-macro/attribute-after-derive.rs2
-rw-r--r--src/test/ui/proc-macro/attribute-after-derive.stdout58
7 files changed, 124 insertions, 29 deletions
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 4f38e060023..2d0009c225c 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -634,6 +634,10 @@ declare_features! (
 
     /// Lessens the requirements for structs to implement `Unsize`.
     (active, relaxed_struct_unsize, "1.51.0", Some(1), None),
+
+    /// Allows macro attributes to observe output of `#[derive]`.
+    (active, macro_attributes_in_derive_output, "1.51.0", Some(81119), None),
+
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
     // -------------------------------------------------------------------------
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 6d3fde33f4d..f7010ca94bd 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -280,6 +280,36 @@ impl<'a> ResolverExpand for Resolver<'a> {
         if let Res::Def(_, _) = res {
             let normal_module_def_id = self.macro_def_scope(invoc_id).nearest_parent_mod;
             self.definitions.add_parent_module_of_macro_def(invoc_id, normal_module_def_id);
+
+            // Gate macro attributes in `#[derive]` output.
+            if !self.session.features_untracked().macro_attributes_in_derive_output
+                && kind == MacroKind::Attr
+                && ext.builtin_name != Some(sym::derive)
+            {
+                let mut expn_id = parent_scope.expansion;
+                loop {
+                    // Helper attr table is a quick way to determine whether the attr is `derive`.
+                    if self.helper_attrs.contains_key(&expn_id) {
+                        feature_err(
+                            &self.session.parse_sess,
+                            sym::macro_attributes_in_derive_output,
+                            path.span,
+                            "macro attributes in `#[derive]` output are unstable",
+                        )
+                        .emit();
+                        break;
+                    } else {
+                        let expn_data = expn_id.expn_data();
+                        match expn_data.kind {
+                            ExpnKind::Root
+                            | ExpnKind::Macro(MacroKind::Bang | MacroKind::Derive, _) => {
+                                break;
+                            }
+                            _ => expn_id = expn_data.parent,
+                        }
+                    }
+                }
+            }
         }
 
         Ok(ext)
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 86f8061a24a..20e4f7262ac 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -679,6 +679,7 @@ symbols! {
         loop_break_value,
         lt,
         macro_at_most_once_rep,
+        macro_attributes_in_derive_output,
         macro_escape,
         macro_export,
         macro_lifetime_matcher,
diff --git a/src/test/ui/proc-macro/attribute-after-derive-feature-gate.rs b/src/test/ui/proc-macro/attribute-after-derive-feature-gate.rs
new file mode 100644
index 00000000000..74751a23d79
--- /dev/null
+++ b/src/test/ui/proc-macro/attribute-after-derive-feature-gate.rs
@@ -0,0 +1,28 @@
+// gate-test-macro_attributes_in_derive_output
+// aux-build: test-macros.rs
+
+#![feature(proc_macro_hygiene)]
+#![feature(stmt_expr_attributes)]
+
+#[macro_use]
+extern crate test_macros;
+
+#[derive(Empty)]
+#[empty_attr] //~ ERROR macro attributes in `#[derive]` output are unstable
+struct S1 {
+    field: [u8; 10],
+}
+
+#[derive(Empty)]
+#[empty_helper]
+#[empty_attr] //~ ERROR macro attributes in `#[derive]` output are unstable
+struct S2 {
+    field: [u8; 10],
+}
+
+#[derive(Empty)]
+struct S3 {
+    field: [u8; #[identity_attr] 10], //~ ERROR macro attributes in `#[derive]` output are unstable
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/attribute-after-derive-feature-gate.stderr b/src/test/ui/proc-macro/attribute-after-derive-feature-gate.stderr
new file mode 100644
index 00000000000..74cace628b9
--- /dev/null
+++ b/src/test/ui/proc-macro/attribute-after-derive-feature-gate.stderr
@@ -0,0 +1,30 @@
+error[E0658]: macro attributes in `#[derive]` output are unstable
+  --> $DIR/attribute-after-derive-feature-gate.rs:11:3
+   |
+LL | #[empty_attr]
+   |   ^^^^^^^^^^
+   |
+   = note: see issue #81119 <https://github.com/rust-lang/rust/issues/81119> for more information
+   = help: add `#![feature(macro_attributes_in_derive_output)]` to the crate attributes to enable
+
+error[E0658]: macro attributes in `#[derive]` output are unstable
+  --> $DIR/attribute-after-derive-feature-gate.rs:18:3
+   |
+LL | #[empty_attr]
+   |   ^^^^^^^^^^
+   |
+   = note: see issue #81119 <https://github.com/rust-lang/rust/issues/81119> for more information
+   = help: add `#![feature(macro_attributes_in_derive_output)]` to the crate attributes to enable
+
+error[E0658]: macro attributes in `#[derive]` output are unstable
+  --> $DIR/attribute-after-derive-feature-gate.rs:25:19
+   |
+LL |     field: [u8; #[identity_attr] 10],
+   |                   ^^^^^^^^^^^^^
+   |
+   = note: see issue #81119 <https://github.com/rust-lang/rust/issues/81119> for more information
+   = help: add `#![feature(macro_attributes_in_derive_output)]` to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/proc-macro/attribute-after-derive.rs b/src/test/ui/proc-macro/attribute-after-derive.rs
index 0f0f27bff97..ac3f28b6ef3 100644
--- a/src/test/ui/proc-macro/attribute-after-derive.rs
+++ b/src/test/ui/proc-macro/attribute-after-derive.rs
@@ -5,6 +5,8 @@
 // compile-flags: -Z span-debug
 // aux-build: test-macros.rs
 
+#![feature(macro_attributes_in_derive_output)]
+
 #![no_std] // Don't load unnecessary hygiene information from std
 extern crate std;
 
diff --git a/src/test/ui/proc-macro/attribute-after-derive.stdout b/src/test/ui/proc-macro/attribute-after-derive.stdout
index 78c58c0a32f..11f49235327 100644
--- a/src/test/ui/proc-macro/attribute-after-derive.stdout
+++ b/src/test/ui/proc-macro/attribute-after-derive.stdout
@@ -3,35 +3,35 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
     Punct {
         ch: '#',
         spacing: Alone,
-        span: $DIR/attribute-after-derive.rs:15:1: 15:2 (#0),
+        span: $DIR/attribute-after-derive.rs:17:1: 17:2 (#0),
     },
     Group {
         delimiter: Bracket,
         stream: TokenStream [
             Ident {
                 ident: "derive",
-                span: $DIR/attribute-after-derive.rs:15:3: 15:9 (#0),
+                span: $DIR/attribute-after-derive.rs:17:3: 17:9 (#0),
             },
             Group {
                 delimiter: Parenthesis,
                 stream: TokenStream [
                     Ident {
                         ident: "Print",
-                        span: $DIR/attribute-after-derive.rs:15:10: 15:15 (#0),
+                        span: $DIR/attribute-after-derive.rs:17:10: 17:15 (#0),
                     },
                 ],
-                span: $DIR/attribute-after-derive.rs:15:9: 15:16 (#0),
+                span: $DIR/attribute-after-derive.rs:17:9: 17:16 (#0),
             },
         ],
-        span: $DIR/attribute-after-derive.rs:15:2: 15:17 (#0),
+        span: $DIR/attribute-after-derive.rs:17:2: 17:17 (#0),
     },
     Ident {
         ident: "struct",
-        span: $DIR/attribute-after-derive.rs:16:1: 16:7 (#0),
+        span: $DIR/attribute-after-derive.rs:18:1: 18:7 (#0),
     },
     Ident {
         ident: "AttributeDerive",
-        span: $DIR/attribute-after-derive.rs:16:8: 16:23 (#0),
+        span: $DIR/attribute-after-derive.rs:18:8: 18:23 (#0),
     },
     Group {
         delimiter: Brace,
@@ -39,80 +39,80 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
             Punct {
                 ch: '#',
                 spacing: Alone,
-                span: $DIR/attribute-after-derive.rs:17:5: 17:6 (#0),
+                span: $DIR/attribute-after-derive.rs:19:5: 19:6 (#0),
             },
             Group {
                 delimiter: Bracket,
                 stream: TokenStream [
                     Ident {
                         ident: "cfg",
-                        span: $DIR/attribute-after-derive.rs:17:7: 17:10 (#0),
+                        span: $DIR/attribute-after-derive.rs:19:7: 19:10 (#0),
                     },
                     Group {
                         delimiter: Parenthesis,
                         stream: TokenStream [
                             Ident {
                                 ident: "FALSE",
-                                span: $DIR/attribute-after-derive.rs:17:11: 17:16 (#0),
+                                span: $DIR/attribute-after-derive.rs:19:11: 19:16 (#0),
                             },
                         ],
-                        span: $DIR/attribute-after-derive.rs:17:10: 17:17 (#0),
+                        span: $DIR/attribute-after-derive.rs:19:10: 19:17 (#0),
                     },
                 ],
-                span: $DIR/attribute-after-derive.rs:17:6: 17:18 (#0),
+                span: $DIR/attribute-after-derive.rs:19:6: 19:18 (#0),
             },
             Ident {
                 ident: "field",
-                span: $DIR/attribute-after-derive.rs:18:5: 18:10 (#0),
+                span: $DIR/attribute-after-derive.rs:20:5: 20:10 (#0),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: $DIR/attribute-after-derive.rs:18:10: 18:11 (#0),
+                span: $DIR/attribute-after-derive.rs:20:10: 20:11 (#0),
             },
             Ident {
                 ident: "u8",
-                span: $DIR/attribute-after-derive.rs:18:12: 18:14 (#0),
+                span: $DIR/attribute-after-derive.rs:20:12: 20:14 (#0),
             },
             Punct {
                 ch: ',',
                 spacing: Alone,
-                span: $DIR/attribute-after-derive.rs:18:14: 18:15 (#0),
+                span: $DIR/attribute-after-derive.rs:20:14: 20:15 (#0),
             },
         ],
-        span: $DIR/attribute-after-derive.rs:16:24: 19:2 (#0),
+        span: $DIR/attribute-after-derive.rs:18:24: 21:2 (#0),
     },
 ]
 PRINT-DERIVE INPUT (DISPLAY): struct AttributeDerive { }
 PRINT-DERIVE INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
-        span: $DIR/attribute-after-derive.rs:16:1: 19:2 (#0),
+        span: $DIR/attribute-after-derive.rs:18:1: 21:2 (#0),
     },
     Ident {
         ident: "AttributeDerive",
-        span: $DIR/attribute-after-derive.rs:16:1: 19:2 (#0),
+        span: $DIR/attribute-after-derive.rs:18:1: 21:2 (#0),
     },
     Group {
         delimiter: Brace,
         stream: TokenStream [],
-        span: $DIR/attribute-after-derive.rs:16:1: 19:2 (#0),
+        span: $DIR/attribute-after-derive.rs:18:1: 21:2 (#0),
     },
 ]
 PRINT-ATTR INPUT (DISPLAY): struct DeriveAttribute { }
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
-        span: $DIR/attribute-after-derive.rs:23:1: 26:2 (#0),
+        span: $DIR/attribute-after-derive.rs:25:1: 28:2 (#0),
     },
     Ident {
         ident: "DeriveAttribute",
-        span: $DIR/attribute-after-derive.rs:23:1: 26:2 (#0),
+        span: $DIR/attribute-after-derive.rs:25:1: 28:2 (#0),
     },
     Group {
         delimiter: Brace,
         stream: TokenStream [],
-        span: $DIR/attribute-after-derive.rs:23:1: 26:2 (#0),
+        span: $DIR/attribute-after-derive.rs:25:1: 28:2 (#0),
     },
 ]
 PRINT-DERIVE INPUT (DISPLAY): #[print_attr] struct DeriveAttribute { }
@@ -120,29 +120,29 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
     Punct {
         ch: '#',
         spacing: Alone,
-        span: $DIR/attribute-after-derive.rs:23:1: 26:2 (#0),
+        span: $DIR/attribute-after-derive.rs:25:1: 28:2 (#0),
     },
     Group {
         delimiter: Bracket,
         stream: TokenStream [
             Ident {
                 ident: "print_attr",
-                span: $DIR/attribute-after-derive.rs:23:1: 26:2 (#0),
+                span: $DIR/attribute-after-derive.rs:25:1: 28:2 (#0),
             },
         ],
-        span: $DIR/attribute-after-derive.rs:23:1: 26:2 (#0),
+        span: $DIR/attribute-after-derive.rs:25:1: 28:2 (#0),
     },
     Ident {
         ident: "struct",
-        span: $DIR/attribute-after-derive.rs:23:1: 26:2 (#0),
+        span: $DIR/attribute-after-derive.rs:25:1: 28:2 (#0),
     },
     Ident {
         ident: "DeriveAttribute",
-        span: $DIR/attribute-after-derive.rs:23:1: 26:2 (#0),
+        span: $DIR/attribute-after-derive.rs:25:1: 28:2 (#0),
     },
     Group {
         delimiter: Brace,
         stream: TokenStream [],
-        span: $DIR/attribute-after-derive.rs:23:1: 26:2 (#0),
+        span: $DIR/attribute-after-derive.rs:25:1: 28:2 (#0),
     },
 ]