]> git.lizzy.rs Git - rust.git/commitdiff
expand: Move "derive containers" into a separate `InvocationKind` variant
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Sun, 7 Jul 2019 22:00:43 +0000 (01:00 +0300)
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Wed, 10 Jul 2019 21:12:57 +0000 (00:12 +0300)
`InvocationKind::Attr { attr: None, .. }` meaning something entirely different from a regular attribute was confusing as hell.

src/librustc_resolve/macros.rs
src/libsyntax/ext/expand.rs

index 6f276e04a5a39df3bd30fcd07d14045fd7deedd3..fc1becfe309603045710389c58f79377cf783db3 100644 (file)
@@ -221,14 +221,14 @@ fn resolve_imports(&mut self) {
     fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: Mark, force: bool)
                                 -> Result<Option<Lrc<SyntaxExtension>>, Indeterminate> {
         let (path, kind, derives_in_scope, after_derive) = match invoc.kind {
-            InvocationKind::Attr { attr: None, .. } =>
-                return Ok(None),
-            InvocationKind::Attr { attr: Some(ref attr), ref traits, after_derive, .. } =>
-                (&attr.path, MacroKind::Attr, traits.clone(), after_derive),
+            InvocationKind::Attr { ref attr, ref derives, after_derive, .. } =>
+                (&attr.path, MacroKind::Attr, derives.clone(), after_derive),
             InvocationKind::Bang { ref mac, .. } =>
                 (&mac.node.path, MacroKind::Bang, Vec::new(), false),
             InvocationKind::Derive { ref path, .. } =>
                 (path, MacroKind::Derive, Vec::new(), false),
+            InvocationKind::DeriveContainer { .. } =>
+                return Ok(None),
         };
 
         let parent_scope = self.invoc_parent_scope(invoc_id, derives_in_scope);
index f1235e7174f2c8e9d35ce3d8d20acfa9f40feb9e..7fc62e357c5c4a9b81eb4facfd5d4773c5a62e5b 100644 (file)
@@ -199,9 +199,10 @@ pub enum InvocationKind {
         span: Span,
     },
     Attr {
-        attr: Option<ast::Attribute>,
-        traits: Vec<Path>,
+        attr: ast::Attribute,
         item: Annotatable,
+        // Required for resolving derive helper attributes.
+        derives: Vec<Path>,
         // We temporarily report errors for attribute macros placed after derives
         after_derive: bool,
     },
@@ -210,15 +211,22 @@ pub enum InvocationKind {
         item: Annotatable,
         item_with_markers: Annotatable,
     },
+    /// "Invocation" that contains all derives from an item,
+    /// broken into multiple `Derive` invocations when expanded.
+    /// FIXME: Find a way to remove it.
+    DeriveContainer {
+        derives: Vec<Path>,
+        item: Annotatable,
+    },
 }
 
 impl Invocation {
     pub fn span(&self) -> Span {
-        match self.kind {
-            InvocationKind::Bang { span, .. } => span,
-            InvocationKind::Attr { attr: Some(ref attr), .. } => attr.span,
-            InvocationKind::Attr { attr: None, .. } => DUMMY_SP,
-            InvocationKind::Derive { ref path, .. } => path.span,
+        match &self.kind {
+            InvocationKind::Bang { span, .. } => *span,
+            InvocationKind::Attr { attr, .. } => attr.span,
+            InvocationKind::Derive { path, .. } => path.span,
+            InvocationKind::DeriveContainer { item, .. } => item.span(),
         }
     }
 }
@@ -329,7 +337,7 @@ fn expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment {
             let (expanded_fragment, new_invocations) = if let Some(ext) = ext {
                 let fragment = self.expand_invoc(invoc, &ext.kind);
                 self.collect_invocations(fragment, &[])
-            } else if let InvocationKind::Attr { attr: None, traits, item, .. } = invoc.kind {
+            } else if let InvocationKind::DeriveContainer { derives: traits, item } = invoc.kind {
                 if !item.derive_allowed() {
                     let attr = attr::find_by_name(item.attrs(), sym::derive)
                         .expect("`derive` attribute should exist");
@@ -522,7 +530,7 @@ fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtensionKind) -> AstF
                 }
                 _ => unreachable!()
             }
-            InvocationKind::Attr { attr: Some(attr), mut item, .. } => match ext {
+            InvocationKind::Attr { attr, mut item, .. } => match ext {
                 SyntaxExtensionKind::Attr(expander) => {
                     self.gate_proc_macro_attr_item(span, &item);
                     let item_tok = TokenTree::token(token::Interpolated(Lrc::new(match item {
@@ -578,7 +586,7 @@ fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtensionKind) -> AstF
                 }
                 _ => unreachable!()
             }
-            _ => unreachable!()
+            InvocationKind::DeriveContainer { .. } => unreachable!()
         }
     }
 
@@ -805,10 +813,10 @@ struct InvocationCollector<'a, 'b> {
 impl<'a, 'b> InvocationCollector<'a, 'b> {
     fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> AstFragment {
         // Expansion info for all the collected invocations is set upon their resolution,
-        // with exception of the "derive container" case which is not resolved and can get
+        // with exception of the derive container case which is not resolved and can get
         // its expansion info immediately.
         let expn_info = match &kind {
-            InvocationKind::Attr { attr: None, item, .. } => Some(ExpnInfo::default(
+            InvocationKind::DeriveContainer { item, .. } => Some(ExpnInfo::default(
                 ExpnKind::Macro(MacroKind::Attr, sym::derive),
                 item.span(), self.cx.parse_sess.edition,
             )),
@@ -833,12 +841,15 @@ fn collect_bang(&mut self, mac: ast::Mac, span: Span, kind: AstFragmentKind) ->
 
     fn collect_attr(&mut self,
                     attr: Option<ast::Attribute>,
-                    traits: Vec<Path>,
+                    derives: Vec<Path>,
                     item: Annotatable,
                     kind: AstFragmentKind,
                     after_derive: bool)
                     -> AstFragment {
-        self.collect(kind, InvocationKind::Attr { attr, traits, item, after_derive })
+        self.collect(kind, match attr {
+            Some(attr) => InvocationKind::Attr { attr, item, derives, after_derive },
+            None => InvocationKind::DeriveContainer { derives, item },
+        })
     }
 
     fn find_attr_invoc(&self, attrs: &mut Vec<ast::Attribute>, after_derive: &mut bool)