From b003dd6d9badf0e66b6e90af2052fefef94d4a43 Mon Sep 17 00:00:00 2001
From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
Date: Sun, 7 Jul 2019 18:55:29 +0300
Subject: [PATCH] expand: Merge `expand_{bang,attr,derive}_invoc` into a single
 function

It's more convenient to have all this highly related stuff together on one screen (for future refactorings).
The `expand_invoc` function is compact enough now, after all the previous refactorings.
---
 src/libsyntax/ext/expand.rs           | 198 +++++++++++---------------
 src/test/ui/macros/macro-error.stderr |   2 +-
 2 files changed, 81 insertions(+), 119 deletions(-)

diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 85a31b8b7e8..f1235e7174f 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -327,7 +327,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
 
             // FIXME(jseyfried): Refactor out the following logic
             let (expanded_fragment, new_invocations) = if let Some(ext) = ext {
-                let fragment = self.expand_invoc(invoc, &ext);
+                let fragment = self.expand_invoc(invoc, &ext.kind);
                 self.collect_invocations(fragment, &[])
             } else if let InvocationKind::Attr { attr: None, traits, item, .. } = invoc.kind {
                 if !item.derive_allowed() {
@@ -474,12 +474,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         }
     }
 
-    fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtension) -> AstFragment {
-        if invoc.fragment_kind == AstFragmentKind::ForeignItems &&
-           !self.cx.ecfg.macros_in_extern() {
-            if let SyntaxExtensionKind::NonMacroAttr { .. } = ext.kind {} else {
+    fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtensionKind) -> AstFragment {
+        let (fragment_kind, span) = (invoc.fragment_kind, invoc.span());
+        if fragment_kind == AstFragmentKind::ForeignItems && !self.cx.ecfg.macros_in_extern() {
+            if let SyntaxExtensionKind::NonMacroAttr { .. } = ext {} else {
                 emit_feature_err(&self.cx.parse_sess, sym::macros_in_extern,
-                                 invoc.span(), GateIssue::Language,
+                                 span, GateIssue::Language,
                                  "macro invocations in `extern {}` blocks are experimental");
             }
         }
@@ -499,58 +499,84 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         }
 
         match invoc.kind {
-            InvocationKind::Bang { .. } => self.expand_bang_invoc(invoc, ext),
-            InvocationKind::Attr { .. } => self.expand_attr_invoc(invoc, ext),
-            InvocationKind::Derive { .. } => self.expand_derive_invoc(invoc, ext),
-        }
-    }
-
-    fn expand_attr_invoc(&mut self,
-                         invoc: Invocation,
-                         ext: &SyntaxExtension)
-                         -> AstFragment {
-        let (attr, mut item) = match invoc.kind {
-            InvocationKind::Attr { attr: Some(attr), item, .. } => (attr, item),
-            _ => unreachable!(),
-        };
-
-        match &ext.kind {
-            SyntaxExtensionKind::NonMacroAttr { mark_used } => {
-                attr::mark_known(&attr);
-                if *mark_used {
-                    attr::mark_used(&attr);
+            InvocationKind::Bang { mac, .. } => match ext {
+                SyntaxExtensionKind::Bang(expander) => {
+                    self.gate_proc_macro_expansion_kind(span, fragment_kind);
+                    let tok_result = expander.expand(self.cx, span, mac.node.stream());
+                    let result =
+                        self.parse_ast_fragment(tok_result, fragment_kind, &mac.node.path, span);
+                    self.gate_proc_macro_expansion(span, &result);
+                    result
                 }
-                item.visit_attrs(|attrs| attrs.push(attr));
-                invoc.fragment_kind.expect_from_annotatables(iter::once(item))
-            }
-            SyntaxExtensionKind::LegacyAttr(expander) => {
-                match attr.parse_meta(self.cx.parse_sess) {
-                    Ok(meta) => {
-                        let item = expander.expand(self.cx, attr.span, &meta, item);
-                        invoc.fragment_kind.expect_from_annotatables(item)
-                    }
-                    Err(mut err) => {
-                        err.emit();
-                        invoc.fragment_kind.dummy(attr.span)
+                SyntaxExtensionKind::LegacyBang(expander) => {
+                    let tok_result = expander.expand(self.cx, span, mac.node.stream());
+                    if let Some(result) = fragment_kind.make_from(tok_result) {
+                        result
+                    } else {
+                        let msg = format!("non-{kind} macro in {kind} position: {path}",
+                                          kind = fragment_kind.name(), path = mac.node.path);
+                        self.cx.span_err(span, &msg);
+                        self.cx.trace_macros_diag();
+                        fragment_kind.dummy(span)
                     }
                 }
+                _ => unreachable!()
             }
-            SyntaxExtensionKind::Attr(expander) => {
-                self.gate_proc_macro_attr_item(attr.span, &item);
-                let item_tok = TokenTree::token(token::Interpolated(Lrc::new(match item {
-                    Annotatable::Item(item) => token::NtItem(item),
-                    Annotatable::TraitItem(item) => token::NtTraitItem(item.into_inner()),
-                    Annotatable::ImplItem(item) => token::NtImplItem(item.into_inner()),
-                    Annotatable::ForeignItem(item) => token::NtForeignItem(item.into_inner()),
-                    Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()),
-                    Annotatable::Expr(expr) => token::NtExpr(expr),
-                })), DUMMY_SP).into();
-                let input = self.extract_proc_macro_attr_input(attr.tokens, attr.span);
-                let tok_result = expander.expand(self.cx, attr.span, input, item_tok);
-                let res = self.parse_ast_fragment(tok_result, invoc.fragment_kind,
-                                                  &attr.path, attr.span);
-                self.gate_proc_macro_expansion(attr.span, &res);
-                res
+            InvocationKind::Attr { attr: Some(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 {
+                        Annotatable::Item(item) => token::NtItem(item),
+                        Annotatable::TraitItem(item) => token::NtTraitItem(item.into_inner()),
+                        Annotatable::ImplItem(item) => token::NtImplItem(item.into_inner()),
+                        Annotatable::ForeignItem(item) => token::NtForeignItem(item.into_inner()),
+                        Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()),
+                        Annotatable::Expr(expr) => token::NtExpr(expr),
+                    })), DUMMY_SP).into();
+                    let input = self.extract_proc_macro_attr_input(attr.tokens, span);
+                    let tok_result = expander.expand(self.cx, span, input, item_tok);
+                    let res = self.parse_ast_fragment(tok_result, fragment_kind, &attr.path, span);
+                    self.gate_proc_macro_expansion(span, &res);
+                    res
+                }
+                SyntaxExtensionKind::LegacyAttr(expander) => {
+                    match attr.parse_meta(self.cx.parse_sess) {
+                        Ok(meta) => {
+                            let item = expander.expand(self.cx, span, &meta, item);
+                            fragment_kind.expect_from_annotatables(item)
+                        }
+                        Err(mut err) => {
+                            err.emit();
+                            fragment_kind.dummy(span)
+                        }
+                    }
+                }
+                SyntaxExtensionKind::NonMacroAttr { mark_used } => {
+                    attr::mark_known(&attr);
+                    if *mark_used {
+                        attr::mark_used(&attr);
+                    }
+                    item.visit_attrs(|attrs| attrs.push(attr));
+                    fragment_kind.expect_from_annotatables(iter::once(item))
+                }
+                _ => unreachable!()
+            }
+            InvocationKind::Derive { path, item, item_with_markers } => match ext {
+                SyntaxExtensionKind::Derive(expander) |
+                SyntaxExtensionKind::LegacyDerive(expander) => {
+                    let (path, item) = match ext {
+                        SyntaxExtensionKind::LegacyDerive(..) => (path, item_with_markers),
+                        _ => (path, item),
+                    };
+                    if !item.derive_allowed() {
+                        return fragment_kind.dummy(span);
+                    }
+                    let meta = ast::MetaItem { node: ast::MetaItemKind::Word, span, path };
+                    let span = span.with_ctxt(self.cx.backtrace());
+                    let items = expander.expand(self.cx, span, &meta, item);
+                    fragment_kind.expect_from_annotatables(items)
+                }
+                _ => unreachable!()
             }
             _ => unreachable!()
         }
@@ -634,42 +660,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         }
     }
 
-    /// Expand a macro invocation. Returns the resulting expanded AST fragment.
-    fn expand_bang_invoc(&mut self,
-                         invoc: Invocation,
-                         ext: &SyntaxExtension)
-                         -> AstFragment {
-        let kind = invoc.fragment_kind;
-        let (mac, span) = match invoc.kind {
-            InvocationKind::Bang { mac, span } => (mac, span),
-            _ => unreachable!(),
-        };
-        let path = &mac.node.path;
-
-        match &ext.kind {
-            SyntaxExtensionKind::Bang(expander) => {
-                self.gate_proc_macro_expansion_kind(span, kind);
-                let tok_result = expander.expand(self.cx, span, mac.node.stream());
-                let result = self.parse_ast_fragment(tok_result, kind, path, span);
-                self.gate_proc_macro_expansion(span, &result);
-                result
-            }
-            SyntaxExtensionKind::LegacyBang(expander) => {
-                let tok_result = expander.expand(self.cx, span, mac.node.stream());
-                if let Some(result) = kind.make_from(tok_result) {
-                    result
-                } else {
-                    let msg = format!("non-{kind} macro in {kind} position: {name}",
-                                    name = path.segments[0].ident.name, kind = kind.name());
-                    self.cx.span_err(path.span, &msg);
-                    self.cx.trace_macros_diag();
-                    kind.dummy(span)
-                }
-            }
-            _ => unreachable!()
-        }
-    }
-
     fn gate_proc_macro_expansion_kind(&self, span: Span, kind: AstFragmentKind) {
         let kind = match kind {
             AstFragmentKind::Expr => "expressions",
@@ -694,34 +684,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         );
     }
 
-    /// Expand a derive invocation. Returns the resulting expanded AST fragment.
-    fn expand_derive_invoc(&mut self,
-                           invoc: Invocation,
-                           ext: &SyntaxExtension)
-                           -> AstFragment {
-        let (path, item) = match invoc.kind {
-            InvocationKind::Derive { path, item, item_with_markers } => match ext.kind {
-                SyntaxExtensionKind::LegacyDerive(..) => (path, item_with_markers),
-                _ => (path, item),
-            }
-            _ => unreachable!(),
-        };
-        if !item.derive_allowed() {
-            return invoc.fragment_kind.dummy(path.span);
-        }
-
-        match &ext.kind {
-            SyntaxExtensionKind::Derive(expander) |
-            SyntaxExtensionKind::LegacyDerive(expander) => {
-                let meta = ast::MetaItem { node: ast::MetaItemKind::Word, span: path.span, path };
-                let span = meta.span.with_ctxt(self.cx.backtrace());
-                let items = expander.expand(self.cx, span, &meta, item);
-                invoc.fragment_kind.expect_from_annotatables(items)
-            }
-            _ => unreachable!()
-        }
-    }
-
     fn parse_ast_fragment(&mut self,
                           toks: TokenStream,
                           kind: AstFragmentKind,
diff --git a/src/test/ui/macros/macro-error.stderr b/src/test/ui/macros/macro-error.stderr
index b3aed8c2cef..2539a6d5156 100644
--- a/src/test/ui/macros/macro-error.stderr
+++ b/src/test/ui/macros/macro-error.stderr
@@ -8,7 +8,7 @@ error: non-type macro in type position: cfg
   --> $DIR/macro-error.rs:8:12
    |
 LL |     let _: cfg!(foo) = ();
-   |            ^^^
+   |            ^^^^^^^^^
 
 error: aborting due to 2 previous errors