about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNicholas Nethercote <nnethercote@mozilla.com>2019-12-12 16:41:18 +1100
committerNicholas Nethercote <nnethercote@mozilla.com>2020-01-30 11:18:56 +1100
commit0d69fe8308a76630a104504c14e1d3d74e2a3f15 (patch)
tree8539fc7552335e7298ae1b556c32286671d1fadf
parenteed12bcd0cb281979c4c9ed956b9e41fda2bfaeb (diff)
downloadrust-0d69fe8308a76630a104504c14e1d3d74e2a3f15.tar.gz
rust-0d69fe8308a76630a104504c14e1d3d74e2a3f15.zip
Use `P` for `NtTraitItem`, `NtImplItem`, and `NtForeignItem`.
This commit reduces the size of `Nonterminal` from a whopping 240 bytes
to 72 bytes (on x86-64), which gets it below the `memcpy` threshold.

It also removes some impedance mismatches with `Annotatable`, which
already uses `P` for these variants.
-rw-r--r--src/librustc_builtin_macros/deriving/generic/mod.rs15
-rw-r--r--src/librustc_expand/base.rs36
-rw-r--r--src/librustc_expand/expand.rs84
-rw-r--r--src/librustc_expand/placeholders.rs37
-rw-r--r--src/librustc_interface/util.rs4
-rw-r--r--src/librustc_parse/config.rs4
-rw-r--r--src/librustc_parse/parser/item.rs34
-rw-r--r--src/librustc_resolve/late.rs4
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs4
-rw-r--r--src/libsyntax/ast.rs6
-rw-r--r--src/libsyntax/mut_visit.rs18
-rw-r--r--src/libsyntax/token.rs10
12 files changed, 138 insertions, 118 deletions
diff --git a/src/librustc_builtin_macros/deriving/generic/mod.rs b/src/librustc_builtin_macros/deriving/generic/mod.rs
index f8918016c1b..9377f194dcd 100644
--- a/src/librustc_builtin_macros/deriving/generic/mod.rs
+++ b/src/librustc_builtin_macros/deriving/generic/mod.rs
@@ -531,13 +531,13 @@ impl<'a> TraitDef<'a> {
         type_ident: Ident,
         generics: &Generics,
         field_tys: Vec<P<ast::Ty>>,
-        methods: Vec<ast::AssocItem>,
+        methods: Vec<P<ast::AssocItem>>,
     ) -> P<ast::Item> {
         let trait_path = self.path.to_path(cx, self.span, type_ident, generics);
 
         // Transform associated types from `deriving::ty::Ty` into `ast::AssocItem`
-        let associated_types =
-            self.associated_types.iter().map(|&(ident, ref type_def)| ast::AssocItem {
+        let associated_types = self.associated_types.iter().map(|&(ident, ref type_def)| {
+            P(ast::AssocItem {
                 id: ast::DUMMY_NODE_ID,
                 span: self.span,
                 ident,
@@ -550,7 +550,8 @@ impl<'a> TraitDef<'a> {
                     Some(type_def.to_ty(cx, self.span, type_ident, generics)),
                 ),
                 tokens: None,
-            });
+            })
+        });
 
         let Generics { mut params, mut where_clause, span } =
             self.generics.to_generics(cx, self.span, type_ident, generics);
@@ -938,7 +939,7 @@ impl<'a> MethodDef<'a> {
         explicit_self: Option<ast::ExplicitSelf>,
         arg_types: Vec<(Ident, P<ast::Ty>)>,
         body: P<Expr>,
-    ) -> ast::AssocItem {
+    ) -> P<ast::AssocItem> {
         // Create the generics that aren't for `Self`.
         let fn_generics = self.generics.to_generics(cx, trait_.span, type_ident, generics);
 
@@ -968,7 +969,7 @@ impl<'a> MethodDef<'a> {
         };
 
         // Create the method.
-        ast::AssocItem {
+        P(ast::AssocItem {
             id: ast::DUMMY_NODE_ID,
             attrs: self.attributes.clone(),
             generics: fn_generics,
@@ -978,7 +979,7 @@ impl<'a> MethodDef<'a> {
             ident: method_ident,
             kind: ast::AssocItemKind::Fn(sig, Some(body_block)),
             tokens: None,
-        }
+        })
     }
 
     /// ```
diff --git a/src/librustc_expand/base.rs b/src/librustc_expand/base.rs
index 52ba14dbc3d..9debae19fa5 100644
--- a/src/librustc_expand/base.rs
+++ b/src/librustc_expand/base.rs
@@ -136,23 +136,23 @@ impl Annotatable {
         }
     }
 
-    pub fn expect_trait_item(self) -> ast::AssocItem {
+    pub fn expect_trait_item(self) -> P<ast::AssocItem> {
         match self {
-            Annotatable::TraitItem(i) => i.into_inner(),
+            Annotatable::TraitItem(i) => i,
             _ => panic!("expected Item"),
         }
     }
 
-    pub fn expect_impl_item(self) -> ast::AssocItem {
+    pub fn expect_impl_item(self) -> P<ast::AssocItem> {
         match self {
-            Annotatable::ImplItem(i) => i.into_inner(),
+            Annotatable::ImplItem(i) => i,
             _ => panic!("expected Item"),
         }
     }
 
-    pub fn expect_foreign_item(self) -> ast::ForeignItem {
+    pub fn expect_foreign_item(self) -> P<ast::ForeignItem> {
         match self {
-            Annotatable::ForeignItem(i) => i.into_inner(),
+            Annotatable::ForeignItem(i) => i,
             _ => panic!("expected foreign item"),
         }
     }
@@ -382,17 +382,17 @@ pub trait MacResult {
     }
 
     /// Creates zero or more impl items.
-    fn make_impl_items(self: Box<Self>) -> Option<SmallVec<[ast::AssocItem; 1]>> {
+    fn make_impl_items(self: Box<Self>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
         None
     }
 
     /// Creates zero or more trait items.
-    fn make_trait_items(self: Box<Self>) -> Option<SmallVec<[ast::AssocItem; 1]>> {
+    fn make_trait_items(self: Box<Self>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
         None
     }
 
     /// Creates zero or more items in an `extern {}` block
-    fn make_foreign_items(self: Box<Self>) -> Option<SmallVec<[ast::ForeignItem; 1]>> {
+    fn make_foreign_items(self: Box<Self>) -> Option<SmallVec<[P<ast::ForeignItem>; 1]>> {
         None
     }
 
@@ -470,9 +470,9 @@ make_MacEager! {
     expr: P<ast::Expr>,
     pat: P<ast::Pat>,
     items: SmallVec<[P<ast::Item>; 1]>,
-    impl_items: SmallVec<[ast::AssocItem; 1]>,
-    trait_items: SmallVec<[ast::AssocItem; 1]>,
-    foreign_items: SmallVec<[ast::ForeignItem; 1]>,
+    impl_items: SmallVec<[P<ast::AssocItem>; 1]>,
+    trait_items: SmallVec<[P<ast::AssocItem>; 1]>,
+    foreign_items: SmallVec<[P<ast::ForeignItem>; 1]>,
     stmts: SmallVec<[ast::Stmt; 1]>,
     ty: P<ast::Ty>,
 }
@@ -486,15 +486,15 @@ impl MacResult for MacEager {
         self.items
     }
 
-    fn make_impl_items(self: Box<Self>) -> Option<SmallVec<[ast::AssocItem; 1]>> {
+    fn make_impl_items(self: Box<Self>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
         self.impl_items
     }
 
-    fn make_trait_items(self: Box<Self>) -> Option<SmallVec<[ast::AssocItem; 1]>> {
+    fn make_trait_items(self: Box<Self>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
         self.trait_items
     }
 
-    fn make_foreign_items(self: Box<Self>) -> Option<SmallVec<[ast::ForeignItem; 1]>> {
+    fn make_foreign_items(self: Box<Self>) -> Option<SmallVec<[P<ast::ForeignItem>; 1]>> {
         self.foreign_items
     }
 
@@ -586,15 +586,15 @@ impl MacResult for DummyResult {
         Some(SmallVec::new())
     }
 
-    fn make_impl_items(self: Box<DummyResult>) -> Option<SmallVec<[ast::AssocItem; 1]>> {
+    fn make_impl_items(self: Box<DummyResult>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
         Some(SmallVec::new())
     }
 
-    fn make_trait_items(self: Box<DummyResult>) -> Option<SmallVec<[ast::AssocItem; 1]>> {
+    fn make_trait_items(self: Box<DummyResult>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
         Some(SmallVec::new())
     }
 
-    fn make_foreign_items(self: Box<Self>) -> Option<SmallVec<[ast::ForeignItem; 1]>> {
+    fn make_foreign_items(self: Box<Self>) -> Option<SmallVec<[P<ast::ForeignItem>; 1]>> {
         Some(SmallVec::new())
     }
 
diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs
index f915f44c17a..ea459064b09 100644
--- a/src/librustc_expand/expand.rs
+++ b/src/librustc_expand/expand.rs
@@ -152,13 +152,13 @@ ast_fragments! {
     Items(SmallVec<[P<ast::Item>; 1]>) {
         "item"; many fn flat_map_item; fn visit_item; fn make_items;
     }
-    TraitItems(SmallVec<[ast::AssocItem; 1]>) {
+    TraitItems(SmallVec<[P<ast::AssocItem>; 1]>) {
         "trait item"; many fn flat_map_trait_item; fn visit_trait_item; fn make_trait_items;
     }
-    ImplItems(SmallVec<[ast::AssocItem; 1]>) {
+    ImplItems(SmallVec<[P<ast::AssocItem>; 1]>) {
         "impl item"; many fn flat_map_impl_item; fn visit_impl_item; fn make_impl_items;
     }
-    ForeignItems(SmallVec<[ast::ForeignItem; 1]>) {
+    ForeignItems(SmallVec<[P<ast::ForeignItem>; 1]>) {
         "foreign item";
         many fn flat_map_foreign_item;
         fn visit_foreign_item;
@@ -554,15 +554,15 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         // we know that fold result vector will contain exactly one element
         match item {
             Annotatable::Item(item) => Annotatable::Item(cfg.flat_map_item(item).pop().unwrap()),
-            Annotatable::TraitItem(item) => Annotatable::TraitItem(
-                item.map(|item| cfg.flat_map_trait_item(item).pop().unwrap()),
-            ),
+            Annotatable::TraitItem(item) => {
+                Annotatable::TraitItem(cfg.flat_map_trait_item(item).pop().unwrap())
+            }
             Annotatable::ImplItem(item) => {
-                Annotatable::ImplItem(item.map(|item| cfg.flat_map_impl_item(item).pop().unwrap()))
+                Annotatable::ImplItem(cfg.flat_map_impl_item(item).pop().unwrap())
+            }
+            Annotatable::ForeignItem(item) => {
+                Annotatable::ForeignItem(cfg.flat_map_foreign_item(item).pop().unwrap())
             }
-            Annotatable::ForeignItem(item) => Annotatable::ForeignItem(
-                item.map(|item| cfg.flat_map_foreign_item(item).pop().unwrap()),
-            ),
             Annotatable::Stmt(stmt) => {
                 Annotatable::Stmt(stmt.map(|stmt| cfg.flat_map_stmt(stmt).pop().unwrap()))
             }
@@ -643,11 +643,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                     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::TraitItem(item) => token::NtTraitItem(item),
+                            Annotatable::ImplItem(item) => token::NtImplItem(item),
+                            Annotatable::ForeignItem(item) => token::NtForeignItem(item),
                             Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()),
                             Annotatable::Expr(expr) => token::NtExpr(expr),
                             Annotatable::Arm(..)
@@ -1411,7 +1409,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
         }
     }
 
-    fn flat_map_trait_item(&mut self, item: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> {
+    fn flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
         let mut item = configure!(self, item);
 
         let (attr, traits, after_derive) = self.classify_item(&mut item);
@@ -1420,7 +1418,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
                 .collect_attr(
                     attr,
                     traits,
-                    Annotatable::TraitItem(P(item)),
+                    Annotatable::TraitItem(item),
                     AstFragmentKind::TraitItems,
                     after_derive,
                 )
@@ -1428,16 +1426,20 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
         }
 
         match item.kind {
-            ast::AssocItemKind::Macro(mac) => {
-                let ast::AssocItem { attrs, span, .. } = item;
-                self.check_attributes(&attrs);
-                self.collect_bang(mac, span, AstFragmentKind::TraitItems).make_trait_items()
+            ast::AssocItemKind::Macro(..) => {
+                self.check_attributes(&item.attrs);
+                item.and_then(|item| match item.kind {
+                    ast::AssocItemKind::Macro(mac) => self
+                        .collect_bang(mac, item.span, AstFragmentKind::TraitItems)
+                        .make_trait_items(),
+                    _ => unreachable!(),
+                })
             }
             _ => noop_flat_map_assoc_item(item, self),
         }
     }
 
-    fn flat_map_impl_item(&mut self, item: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> {
+    fn flat_map_impl_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
         let mut item = configure!(self, item);
 
         let (attr, traits, after_derive) = self.classify_item(&mut item);
@@ -1446,7 +1448,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
                 .collect_attr(
                     attr,
                     traits,
-                    Annotatable::ImplItem(P(item)),
+                    Annotatable::ImplItem(item),
                     AstFragmentKind::ImplItems,
                     after_derive,
                 )
@@ -1454,10 +1456,14 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
         }
 
         match item.kind {
-            ast::AssocItemKind::Macro(mac) => {
-                let ast::AssocItem { attrs, span, .. } = item;
-                self.check_attributes(&attrs);
-                self.collect_bang(mac, span, AstFragmentKind::ImplItems).make_impl_items()
+            ast::AssocItemKind::Macro(..) => {
+                self.check_attributes(&item.attrs);
+                item.and_then(|item| match item.kind {
+                    ast::AssocItemKind::Macro(mac) => self
+                        .collect_bang(mac, item.span, AstFragmentKind::ImplItems)
+                        .make_impl_items(),
+                    _ => unreachable!(),
+                })
             }
             _ => noop_flat_map_assoc_item(item, self),
         }
@@ -1482,8 +1488,8 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
 
     fn flat_map_foreign_item(
         &mut self,
-        mut foreign_item: ast::ForeignItem,
-    ) -> SmallVec<[ast::ForeignItem; 1]> {
+        mut foreign_item: P<ast::ForeignItem>,
+    ) -> SmallVec<[P<ast::ForeignItem>; 1]> {
         let (attr, traits, after_derive) = self.classify_item(&mut foreign_item);
 
         if attr.is_some() || !traits.is_empty() {
@@ -1491,21 +1497,25 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
                 .collect_attr(
                     attr,
                     traits,
-                    Annotatable::ForeignItem(P(foreign_item)),
+                    Annotatable::ForeignItem(foreign_item),
                     AstFragmentKind::ForeignItems,
                     after_derive,
                 )
                 .make_foreign_items();
         }
 
-        if let ast::ForeignItemKind::Macro(mac) = foreign_item.kind {
-            self.check_attributes(&foreign_item.attrs);
-            return self
-                .collect_bang(mac, foreign_item.span, AstFragmentKind::ForeignItems)
-                .make_foreign_items();
+        match foreign_item.kind {
+            ast::ForeignItemKind::Macro(..) => {
+                self.check_attributes(&foreign_item.attrs);
+                foreign_item.and_then(|item| match item.kind {
+                    ast::ForeignItemKind::Macro(mac) => self
+                        .collect_bang(mac, item.span, AstFragmentKind::ForeignItems)
+                        .make_foreign_items(),
+                    _ => unreachable!(),
+                })
+            }
+            _ => noop_flat_map_foreign_item(foreign_item, self),
         }
-
-        noop_flat_map_foreign_item(foreign_item, self)
     }
 
     fn visit_item_kind(&mut self, item: &mut ast::ItemKind) {
diff --git a/src/librustc_expand/placeholders.rs b/src/librustc_expand/placeholders.rs
index 8b18a5dc4bb..6bcb8f45f00 100644
--- a/src/librustc_expand/placeholders.rs
+++ b/src/librustc_expand/placeholders.rs
@@ -51,7 +51,7 @@ pub fn placeholder(
             kind: ast::ItemKind::Mac(mac_placeholder()),
             tokens: None,
         })]),
-        AstFragmentKind::TraitItems => AstFragment::TraitItems(smallvec![ast::AssocItem {
+        AstFragmentKind::TraitItems => AstFragment::TraitItems(smallvec![P(ast::AssocItem {
             id,
             span,
             ident,
@@ -61,8 +61,8 @@ pub fn placeholder(
             kind: ast::AssocItemKind::Macro(mac_placeholder()),
             defaultness: ast::Defaultness::Final,
             tokens: None,
-        }]),
-        AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![ast::AssocItem {
+        })]),
+        AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![P(ast::AssocItem {
             id,
             span,
             ident,
@@ -72,16 +72,18 @@ pub fn placeholder(
             kind: ast::AssocItemKind::Macro(mac_placeholder()),
             defaultness: ast::Defaultness::Final,
             tokens: None,
-        }]),
-        AstFragmentKind::ForeignItems => AstFragment::ForeignItems(smallvec![ast::ForeignItem {
-            id,
-            span,
-            ident,
-            vis,
-            attrs,
-            kind: ast::ForeignItemKind::Macro(mac_placeholder()),
-            tokens: None,
-        }]),
+        })]),
+        AstFragmentKind::ForeignItems => {
+            AstFragment::ForeignItems(smallvec![P(ast::ForeignItem {
+                id,
+                span,
+                ident,
+                vis,
+                attrs,
+                kind: ast::ForeignItemKind::Macro(mac_placeholder()),
+                tokens: None,
+            })])
+        }
         AstFragmentKind::Pat => {
             AstFragment::Pat(P(ast::Pat { id, span, kind: ast::PatKind::Mac(mac_placeholder()) }))
         }
@@ -250,21 +252,24 @@ impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> {
         noop_flat_map_item(item, self)
     }
 
-    fn flat_map_trait_item(&mut self, item: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> {
+    fn flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
         match item.kind {
             ast::AssocItemKind::Macro(_) => self.remove(item.id).make_trait_items(),
             _ => noop_flat_map_assoc_item(item, self),
         }
     }
 
-    fn flat_map_impl_item(&mut self, item: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> {
+    fn flat_map_impl_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
         match item.kind {
             ast::AssocItemKind::Macro(_) => self.remove(item.id).make_impl_items(),
             _ => noop_flat_map_assoc_item(item, self),
         }
     }
 
-    fn flat_map_foreign_item(&mut self, item: ast::ForeignItem) -> SmallVec<[ast::ForeignItem; 1]> {
+    fn flat_map_foreign_item(
+        &mut self,
+        item: P<ast::ForeignItem>,
+    ) -> SmallVec<[P<ast::ForeignItem>; 1]> {
         match item.kind {
             ast::ForeignItemKind::Macro(_) => self.remove(item.id).make_foreign_items(),
             _ => noop_flat_map_foreign_item(item, self),
diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs
index 3e65da9c47b..00528eca923 100644
--- a/src/librustc_interface/util.rs
+++ b/src/librustc_interface/util.rs
@@ -682,7 +682,7 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> {
         self.run(is_const, |s| noop_visit_item_kind(i, s))
     }
 
-    fn flat_map_trait_item(&mut self, i: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> {
+    fn flat_map_trait_item(&mut self, i: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
         let is_const = match i.kind {
             ast::AssocItemKind::Const(..) => true,
             ast::AssocItemKind::Fn(ref sig, _) => Self::is_sig_const(sig),
@@ -691,7 +691,7 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> {
         self.run(is_const, |s| noop_flat_map_assoc_item(i, s))
     }
 
-    fn flat_map_impl_item(&mut self, i: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> {
+    fn flat_map_impl_item(&mut self, i: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
         self.flat_map_trait_item(i)
     }
 
diff --git a/src/librustc_parse/config.rs b/src/librustc_parse/config.rs
index bf696faf2f3..da158e17f25 100644
--- a/src/librustc_parse/config.rs
+++ b/src/librustc_parse/config.rs
@@ -531,11 +531,11 @@ impl<'a> MutVisitor for StripUnconfigured<'a> {
         noop_flat_map_item(configure!(self, item), self)
     }
 
-    fn flat_map_impl_item(&mut self, item: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> {
+    fn flat_map_impl_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
         noop_flat_map_assoc_item(configure!(self, item), self)
     }
 
-    fn flat_map_trait_item(&mut self, item: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> {
+    fn flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
         noop_flat_map_assoc_item(configure!(self, item), self)
     }
 
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index 31db7fc5f75..f170abac73a 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -661,7 +661,7 @@ impl<'a> Parser<'a> {
         Ok((Ident::invalid(), item_kind, Some(attrs)))
     }
 
-    fn parse_impl_body(&mut self) -> PResult<'a, (Vec<AssocItem>, Vec<Attribute>)> {
+    fn parse_impl_body(&mut self) -> PResult<'a, (Vec<P<AssocItem>>, Vec<Attribute>)> {
         self.expect(&token::OpenDelim(token::Brace))?;
         let attrs = self.parse_inner_attributes()?;
 
@@ -786,12 +786,12 @@ impl<'a> Parser<'a> {
         }
     }
 
-    pub fn parse_impl_item(&mut self, at_end: &mut bool) -> PResult<'a, AssocItem> {
+    pub fn parse_impl_item(&mut self, at_end: &mut bool) -> PResult<'a, P<AssocItem>> {
         maybe_whole!(self, NtImplItem, |x| x);
         self.parse_assoc_item(at_end, |_| true)
     }
 
-    pub fn parse_trait_item(&mut self, at_end: &mut bool) -> PResult<'a, AssocItem> {
+    pub fn parse_trait_item(&mut self, at_end: &mut bool) -> PResult<'a, P<AssocItem>> {
         maybe_whole!(self, NtTraitItem, |x| x);
         // This is somewhat dubious; We don't want to allow
         // param names to be left off if there is a definition...
@@ -805,7 +805,7 @@ impl<'a> Parser<'a> {
         &mut self,
         at_end: &mut bool,
         is_name_required: fn(&token::Token) -> bool,
-    ) -> PResult<'a, AssocItem> {
+    ) -> PResult<'a, P<AssocItem>> {
         let attrs = self.parse_outer_attributes()?;
         let mut unclosed_delims = vec![];
         let (mut item, tokens) = self.collect_tokens(|this| {
@@ -818,7 +818,7 @@ impl<'a> Parser<'a> {
         if !item.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) {
             item.tokens = Some(tokens);
         }
-        Ok(item)
+        Ok(P(item))
     }
 
     fn parse_assoc_item_(
@@ -1064,7 +1064,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses a foreign item.
-    pub fn parse_foreign_item(&mut self, extern_sp: Span) -> PResult<'a, ForeignItem> {
+    pub fn parse_foreign_item(&mut self, extern_sp: Span) -> PResult<'a, P<ForeignItem>> {
         maybe_whole!(self, NtForeignItem, |ni| ni);
 
         let attrs = self.parse_outer_attributes()?;
@@ -1112,7 +1112,7 @@ impl<'a> Parser<'a> {
         }
 
         match self.parse_assoc_macro_invoc("extern", Some(&visibility), &mut false)? {
-            Some(mac) => Ok(ForeignItem {
+            Some(mac) => Ok(P(ForeignItem {
                 ident: Ident::invalid(),
                 span: lo.to(self.prev_span),
                 id: DUMMY_NODE_ID,
@@ -1120,7 +1120,7 @@ impl<'a> Parser<'a> {
                 vis: visibility,
                 kind: ForeignItemKind::Macro(mac),
                 tokens: None,
-            }),
+            })),
             None => {
                 if !attrs.is_empty() {
                     self.expected_item_err(&attrs)?;
@@ -1138,14 +1138,14 @@ impl<'a> Parser<'a> {
         vis: ast::Visibility,
         lo: Span,
         attrs: Vec<Attribute>,
-    ) -> PResult<'a, ForeignItem> {
+    ) -> PResult<'a, P<ForeignItem>> {
         let mutbl = self.parse_mutability();
         let ident = self.parse_ident()?;
         self.expect(&token::Colon)?;
         let ty = self.parse_ty()?;
         let hi = self.token.span;
         self.expect_semi()?;
-        Ok(ForeignItem {
+        Ok(P(ForeignItem {
             ident,
             attrs,
             kind: ForeignItemKind::Static(ty, mutbl),
@@ -1153,7 +1153,7 @@ impl<'a> Parser<'a> {
             span: lo.to(hi),
             vis,
             tokens: None,
-        })
+        }))
     }
 
     /// Parses a type from a foreign module.
@@ -1162,13 +1162,13 @@ impl<'a> Parser<'a> {
         vis: ast::Visibility,
         lo: Span,
         attrs: Vec<Attribute>,
-    ) -> PResult<'a, ForeignItem> {
+    ) -> PResult<'a, P<ForeignItem>> {
         self.expect_keyword(kw::Type)?;
 
         let ident = self.parse_ident()?;
         let hi = self.token.span;
         self.expect_semi()?;
-        Ok(ast::ForeignItem {
+        Ok(P(ast::ForeignItem {
             ident,
             attrs,
             kind: ForeignItemKind::Ty,
@@ -1176,7 +1176,7 @@ impl<'a> Parser<'a> {
             span: lo.to(hi),
             vis,
             tokens: None,
-        })
+        }))
     }
 
     fn is_static_global(&mut self) -> bool {
@@ -1740,13 +1740,13 @@ impl<'a> Parser<'a> {
         lo: Span,
         attrs: Vec<Attribute>,
         extern_sp: Span,
-    ) -> PResult<'a, ForeignItem> {
+    ) -> PResult<'a, P<ForeignItem>> {
         self.expect_keyword(kw::Fn)?;
         let (ident, decl, generics) =
             self.parse_fn_sig(ParamCfg { is_self_allowed: false, is_name_required: |_| true })?;
         let span = lo.to(self.token.span);
         self.parse_semi_or_incorrect_foreign_fn_body(&ident, extern_sp)?;
-        Ok(ast::ForeignItem {
+        Ok(P(ast::ForeignItem {
             ident,
             attrs,
             kind: ForeignItemKind::Fn(decl, generics),
@@ -1754,7 +1754,7 @@ impl<'a> Parser<'a> {
             span,
             vis,
             tokens: None,
-        })
+        }))
     }
 
     fn parse_assoc_fn(
diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs
index faa9eb3bc2f..f1622af130e 100644
--- a/src/librustc_resolve/late.rs
+++ b/src/librustc_resolve/late.rs
@@ -1007,7 +1007,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
     /// When evaluating a `trait` use its associated types' idents for suggestionsa in E0412.
     fn with_trait_items<T>(
         &mut self,
-        trait_items: &Vec<AssocItem>,
+        trait_items: &Vec<P<AssocItem>>,
         f: impl FnOnce(&mut Self) -> T,
     ) -> T {
         let trait_assoc_types = replace(
@@ -1084,7 +1084,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
         opt_trait_reference: &'ast Option<TraitRef>,
         self_type: &'ast Ty,
         item_id: NodeId,
-        impl_items: &'ast [AssocItem],
+        impl_items: &'ast [P<AssocItem>],
     ) {
         debug!("resolve_implementation");
         // If applicable, create a rib for the type parameters.
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index d252fc542c3..2e3e06c36f2 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -650,7 +650,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
         generics: &'l ast::Generics,
         trait_ref: &'l Option<ast::TraitRef>,
         typ: &'l ast::Ty,
-        impl_items: &'l [ast::AssocItem],
+        impl_items: &'l [P<ast::AssocItem>],
     ) {
         if let Some(impl_data) = self.save_ctxt.get_item_data(item) {
             if !self.span.filter_generated(item.span) {
@@ -681,7 +681,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
         item: &'l ast::Item,
         generics: &'l ast::Generics,
         trait_refs: &'l ast::GenericBounds,
-        methods: &'l [ast::AssocItem],
+        methods: &'l [P<ast::AssocItem>],
     ) {
         let name = item.ident.to_string();
         let qualname = format!(
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 5c64cc440ce..db4fd53fe16 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -2243,7 +2243,7 @@ pub struct Mod {
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct ForeignMod {
     pub abi: Option<StrLit>,
-    pub items: Vec<ForeignItem>,
+    pub items: Vec<P<ForeignItem>>,
 }
 
 /// Global inline assembly.
@@ -2605,7 +2605,7 @@ pub enum ItemKind {
     /// A trait declaration (`trait`).
     ///
     /// E.g., `trait Foo { .. }`, `trait Foo<T> { .. }` or `auto trait Foo {}`.
-    Trait(IsAuto, Unsafety, Generics, GenericBounds, Vec<AssocItem>),
+    Trait(IsAuto, Unsafety, Generics, GenericBounds, Vec<P<AssocItem>>),
     /// Trait alias
     ///
     /// E.g., `trait Foo = Bar + Quux;`.
@@ -2624,7 +2624,7 @@ pub enum ItemKind {
         of_trait: Option<TraitRef>,
 
         self_ty: P<Ty>,
-        items: Vec<AssocItem>,
+        items: Vec<P<AssocItem>>,
     },
     /// A macro invocation.
     ///
diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs
index 4a460c5d7b2..e9e1675b9b0 100644
--- a/src/libsyntax/mut_visit.rs
+++ b/src/libsyntax/mut_visit.rs
@@ -82,7 +82,7 @@ pub trait MutVisitor: Sized {
         noop_visit_use_tree(use_tree, self);
     }
 
-    fn flat_map_foreign_item(&mut self, ni: ForeignItem) -> SmallVec<[ForeignItem; 1]> {
+    fn flat_map_foreign_item(&mut self, ni: P<ForeignItem>) -> SmallVec<[P<ForeignItem>; 1]> {
         noop_flat_map_foreign_item(ni, self)
     }
 
@@ -102,11 +102,11 @@ pub trait MutVisitor: Sized {
         noop_visit_item_kind(i, self);
     }
 
-    fn flat_map_trait_item(&mut self, i: AssocItem) -> SmallVec<[AssocItem; 1]> {
+    fn flat_map_trait_item(&mut self, i: P<AssocItem>) -> SmallVec<[P<AssocItem>; 1]> {
         noop_flat_map_assoc_item(i, self)
     }
 
-    fn flat_map_impl_item(&mut self, i: AssocItem) -> SmallVec<[AssocItem; 1]> {
+    fn flat_map_impl_item(&mut self, i: P<AssocItem>) -> SmallVec<[P<AssocItem>; 1]> {
         noop_flat_map_assoc_item(i, self)
     }
 
@@ -947,11 +947,11 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
 }
 
 pub fn noop_flat_map_assoc_item<T: MutVisitor>(
-    mut item: AssocItem,
+    mut item: P<AssocItem>,
     visitor: &mut T,
-) -> SmallVec<[AssocItem; 1]> {
+) -> SmallVec<[P<AssocItem>; 1]> {
     let AssocItem { id, ident, vis, defaultness: _, attrs, generics, kind, span, tokens: _ } =
-        &mut item;
+        item.deref_mut();
     visitor.visit_id(id);
     visitor.visit_ident(ident);
     visitor.visit_vis(vis);
@@ -1036,10 +1036,10 @@ pub fn noop_flat_map_item<T: MutVisitor>(
 }
 
 pub fn noop_flat_map_foreign_item<T: MutVisitor>(
-    mut item: ForeignItem,
+    mut item: P<ForeignItem>,
     visitor: &mut T,
-) -> SmallVec<[ForeignItem; 1]> {
-    let ForeignItem { ident, attrs, id, kind, vis, span, tokens: _ } = &mut item;
+) -> SmallVec<[P<ForeignItem>; 1]> {
+    let ForeignItem { ident, attrs, id, kind, vis, span, tokens: _ } = item.deref_mut();
     visitor.visit_ident(ident);
     visit_attrs(attrs, visitor);
     match kind {
diff --git a/src/libsyntax/token.rs b/src/libsyntax/token.rs
index 14279561cbb..c826b728f80 100644
--- a/src/libsyntax/token.rs
+++ b/src/libsyntax/token.rs
@@ -680,11 +680,15 @@ pub enum Nonterminal {
     // Used only for passing items to proc macro attributes (they are not
     // strictly necessary for that, `Annotatable` can be converted into
     // tokens directly, but doing that naively regresses pretty-printing).
-    NtTraitItem(ast::AssocItem),
-    NtImplItem(ast::AssocItem),
-    NtForeignItem(ast::ForeignItem),
+    NtTraitItem(P<ast::AssocItem>),
+    NtImplItem(P<ast::AssocItem>),
+    NtForeignItem(P<ast::ForeignItem>),
 }
 
+// `Nonterminal` is used a lot. Make sure it doesn't unintentionally get bigger.
+#[cfg(target_arch = "x86_64")]
+rustc_data_structures::static_assert_size!(Nonterminal, 72);
+
 impl PartialEq for Nonterminal {
     fn eq(&self, rhs: &Self) -> bool {
         match (self, rhs) {