diff --git a/src/librustc_expand/base.rs b/src/librustc_expand/base.rs
index 9258b59f79be8..f15e626c2783b 100644
--- a/src/librustc_expand/base.rs
+++ b/src/librustc_expand/base.rs
@@ -4,7 +4,7 @@ use rustc_ast::ast::{self, Attribute, Name, NodeId, PatKind};
 use rustc_ast::mut_visit::{self, MutVisitor};
 use rustc_ast::ptr::P;
 use rustc_ast::token;
-use rustc_ast::tokenstream::{self, TokenStream};
+use rustc_ast::tokenstream::{self, TokenStream, TokenTree};
 use rustc_ast::visit::{AssocCtxt, Visitor};
 use rustc_attr::{self as attr, Deprecation, HasAttrs, Stability};
 use rustc_data_structures::fx::FxHashMap;
@@ -118,6 +118,31 @@ impl Annotatable {
         }
     }
 
+    crate fn into_tokens(self) -> TokenStream {
+        // `Annotatable` can be converted into tokens directly, but we
+        // are packing it into a nonterminal as a piece of AST to make
+        // the produced token stream look nicer in pretty-printed form.
+        let nt = match self {
+            Annotatable::Item(item) => token::NtItem(item),
+            Annotatable::TraitItem(item) | Annotatable::ImplItem(item) => {
+                token::NtItem(P(item.and_then(ast::AssocItem::into_item)))
+            }
+            Annotatable::ForeignItem(item) => {
+                token::NtItem(P(item.and_then(ast::ForeignItem::into_item)))
+            }
+            Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()),
+            Annotatable::Expr(expr) => token::NtExpr(expr),
+            Annotatable::Arm(..)
+            | Annotatable::Field(..)
+            | Annotatable::FieldPat(..)
+            | Annotatable::GenericParam(..)
+            | Annotatable::Param(..)
+            | Annotatable::StructField(..)
+            | Annotatable::Variant(..) => panic!("unexpected annotatable"),
+        };
+        TokenTree::token(token::Interpolated(Lrc::new(nt)), DUMMY_SP).into()
+    }
+
     pub fn expect_item(self) -> P<ast::Item> {
         match self {
             Annotatable::Item(i) => i,
diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs
index b16659725db73..effa89e8bfb21 100644
--- a/src/librustc_expand/expand.rs
+++ b/src/librustc_expand/expand.rs
@@ -10,12 +10,11 @@ use rustc_ast::ast::{ItemKind, MacArgs, MacStmtStyle, StmtKind};
 use rustc_ast::mut_visit::*;
 use rustc_ast::ptr::P;
 use rustc_ast::token;
-use rustc_ast::tokenstream::{TokenStream, TokenTree};
+use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::util::map_in_place::MapInPlace;
 use rustc_ast::visit::{self, AssocCtxt, Visitor};
 use rustc_ast_pretty::pprust;
 use rustc_attr::{self as attr, is_builtin_attr, HasAttrs};
-use rustc_data_structures::sync::Lrc;
 use rustc_errors::{Applicability, FatalError, PResult};
 use rustc_feature::Features;
 use rustc_parse::configure;
@@ -668,38 +667,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                 SyntaxExtensionKind::Attr(expander) => {
                     self.gate_proc_macro_input(&item);
                     self.gate_proc_macro_attr_item(span, &item);
-                    // `Annotatable` can be converted into tokens directly, but we are packing it
-                    // into a nonterminal as a piece of AST to make the produced token stream
-                    // look nicer in pretty-printed form. This may be no longer necessary.
-                    let item_tok = TokenTree::token(
-                        token::Interpolated(Lrc::new(match item {
-                            Annotatable::Item(item) => token::NtItem(item),
-                            Annotatable::TraitItem(item) | Annotatable::ImplItem(item) => {
-                                token::NtItem(P(item.and_then(ast::AssocItem::into_item)))
-                            }
-                            Annotatable::ForeignItem(item) => {
-                                token::NtItem(P(item.and_then(ast::ForeignItem::into_item)))
-                            }
-                            Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()),
-                            Annotatable::Expr(expr) => token::NtExpr(expr),
-                            Annotatable::Arm(..)
-                            | Annotatable::Field(..)
-                            | Annotatable::FieldPat(..)
-                            | Annotatable::GenericParam(..)
-                            | Annotatable::Param(..)
-                            | Annotatable::StructField(..)
-                            | Annotatable::Variant(..) => panic!("unexpected annotatable"),
-                        })),
-                        DUMMY_SP,
-                    )
-                    .into();
-                    let item = attr.unwrap_normal_item();
-                    if let MacArgs::Eq(..) = item.args {
+                    let tokens = item.into_tokens();
+                    let attr_item = attr.unwrap_normal_item();
+                    if let MacArgs::Eq(..) = attr_item.args {
                         self.cx.span_err(span, "key-value macro attributes are not supported");
                     }
                     let tok_result =
-                        expander.expand(self.cx, span, item.args.inner_tokens(), item_tok);
-                    self.parse_ast_fragment(tok_result, fragment_kind, &item.path, span)
+                        expander.expand(self.cx, span, attr_item.args.inner_tokens(), tokens);
+                    self.parse_ast_fragment(tok_result, fragment_kind, &attr_item.path, span)
                 }
                 SyntaxExtensionKind::LegacyAttr(expander) => {
                     match validate_attr::parse_meta(self.cx.parse_sess, &attr) {