about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCamille GILLOT <gillot.camille@gmail.com>2019-11-29 19:01:31 +0100
committerCamille GILLOT <gillot.camille@gmail.com>2019-12-26 23:36:12 +0100
commit58b908d09c846b9112fc6a178f832ff84486f8ee (patch)
treeb1c121e5b758d8d5a99f5fed99731f33f4e0380e
parent52e9825ba8f9a5f32c3568ab0ca25dbeb7842c30 (diff)
downloadrust-58b908d09c846b9112fc6a178f832ff84486f8ee.tar.gz
rust-58b908d09c846b9112fc6a178f832ff84486f8ee.zip
Lowering for hir::Expr.
-rw-r--r--src/librustc/arena.rs11
-rw-r--r--src/librustc/hir/lowering.rs149
-rw-r--r--src/librustc/hir/lowering/expr.rs378
-rw-r--r--src/librustc/hir/lowering/item.rs29
-rw-r--r--src/librustc/hir/mod.rs9
5 files changed, 347 insertions, 229 deletions
diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs
index e93cddf5799..f604a66aebc 100644
--- a/src/librustc/arena.rs
+++ b/src/librustc/arena.rs
@@ -125,14 +125,25 @@ macro_rules! arena_types {
 
             // HIR types
             [few] hir_forest: rustc::hir::map::Forest<$tcx>,
+            [] arm: rustc::hir::Arm<$tcx>,
             [] attribute: syntax::ast::Attribute,
+            [] block: rustc::hir::Block<$tcx>,
             [few] global_asm: rustc::hir::GlobalAsm,
+            [] expr: rustc::hir::Expr<$tcx>,
+            [] field: rustc::hir::Field<$tcx>,
+            [] field_pat: rustc::hir::FieldPat<$tcx>,
             [] fn_decl: rustc::hir::FnDecl,
             [] foreign_item: rustc::hir::ForeignItem<$tcx>,
             [] impl_item_ref: rustc::hir::ImplItemRef,
+            [] inline_asm: rustc::hir::InlineAsm<$tcx>,
+            [] local: rustc::hir::Local<$tcx>,
             [few] macro_def: rustc::hir::MacroDef<$tcx>,
             [] param: rustc::hir::Param<$tcx>,
+            [] pat: rustc::hir::Pat<$tcx>,
             [] path: rustc::hir::Path,
+            [] path_segment: rustc::hir::PathSegment,
+            [] qpath: rustc::hir::QPath,
+            [] stmt: rustc::hir::Stmt<$tcx>,
             [] struct_field: rustc::hir::StructField<$tcx>,
             [] trait_item_ref: rustc::hir::TraitItemRef,
             [] ty: rustc::hir::Ty,
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 4bc41c444e6..cb9f08c7600 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -921,7 +921,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
     fn with_new_scopes<T, F>(&mut self, f: F) -> T
     where
-        F: FnOnce(&mut LoweringContext<'_, '_>) -> T,
+        F: FnOnce(&mut Self) -> T,
     {
         let was_in_loop_condition = self.is_in_loop_condition;
         self.is_in_loop_condition = false;
@@ -2031,21 +2031,27 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             }
         }
         let parent_def_id = DefId::local(self.current_hir_id_owner.last().unwrap().0);
+        let ty = l.ty.as_ref().map(|t| {
+            self.lower_ty(
+                t,
+                if self.sess.features_untracked().impl_trait_in_bindings {
+                    ImplTraitContext::OpaqueTy(Some(parent_def_id))
+                } else {
+                    ImplTraitContext::Disallowed(ImplTraitPosition::Binding)
+                },
+            )
+        });
+        let ty = ty.map(|ty| -> &'hir hir::Ty { self.arena.alloc(ty.into_inner()) });
+        let init = l
+            .init
+            .as_ref()
+            .map(|e| -> &'hir hir::Expr<'hir> { self.arena.alloc(self.lower_expr(e)) });
         (
             hir::Local {
                 hir_id: self.lower_node_id(l.id),
-                ty: l.ty.as_ref().map(|t| {
-                    self.lower_ty(
-                        t,
-                        if self.sess.features_untracked().impl_trait_in_bindings {
-                            ImplTraitContext::OpaqueTy(Some(parent_def_id))
-                        } else {
-                            ImplTraitContext::Disallowed(ImplTraitPosition::Binding)
-                        },
-                    )
-                }),
+                ty,
                 pat: self.lower_pat(&l.pat),
-                init: l.init.as_ref().map(|e| P(self.lower_expr(e))),
+                init,
                 span: l.span,
                 attrs: l.attrs.clone(),
                 source: hir::LocalSource::Normal,
@@ -2586,14 +2592,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         bounds.iter().map(|bound| self.lower_param_bound(bound, itctx.reborrow())).collect()
     }
 
-    fn lower_block(&mut self, b: &Block, targeted_by_break: bool) -> P<hir::Block<'hir>> {
+    fn lower_block(&mut self, b: &Block, targeted_by_break: bool) -> &'hir hir::Block<'hir> {
+        self.arena.alloc(self.lower_block_noalloc(b, targeted_by_break))
+    }
+
+    fn lower_block_noalloc(&mut self, b: &Block, targeted_by_break: bool) -> hir::Block<'hir> {
         let mut stmts = vec![];
-        let mut expr = None;
+        let mut expr: Option<&'hir _> = None;
 
         for (index, stmt) in b.stmts.iter().enumerate() {
             if index == b.stmts.len() - 1 {
                 if let StmtKind::Expr(ref e) = stmt.kind {
-                    expr = Some(P(self.lower_expr(e)));
+                    expr = Some(self.arena.alloc(self.lower_expr(e)));
                 } else {
                     stmts.extend(self.lower_stmt(stmt));
                 }
@@ -2602,14 +2612,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             }
         }
 
-        P(hir::Block {
+        hir::Block {
             hir_id: self.lower_node_id(b.id),
-            stmts: stmts.into(),
+            stmts: self.arena.alloc_from_iter(stmts),
             expr,
             rules: self.lower_block_check_mode(&b.rules),
             span: b.span,
             targeted_by_break,
-        })
+        }
     }
 
     /// Lowers a block directly to an expression, presuming that it
@@ -2619,7 +2629,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         self.expr_block(block, AttrVec::new())
     }
 
-    fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat<'hir>> {
+    fn lower_pat(&mut self, p: &Pat) -> &'hir hir::Pat<'hir> {
         let node = match p.kind {
             PatKind::Wild => hir::PatKind::Wild,
             PatKind::Ident(ref binding_mode, ident, ref sub) => {
@@ -2627,7 +2637,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 let node = self.lower_pat_ident(p, binding_mode, ident, lower_sub);
                 node
             }
-            PatKind::Lit(ref e) => hir::PatKind::Lit(P(self.lower_expr(e))),
+            PatKind::Lit(ref e) => hir::PatKind::Lit(self.arena.alloc(self.lower_expr(e))),
             PatKind::TupleStruct(ref path, ref pats) => {
                 let qpath = self.lower_qpath(
                     p.id,
@@ -2640,7 +2650,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 hir::PatKind::TupleStruct(qpath, pats, ddpos)
             }
             PatKind::Or(ref pats) => {
-                hir::PatKind::Or(pats.iter().map(|x| self.lower_pat(x)).collect())
+                hir::PatKind::Or(self.arena.alloc_from_iter(pats.iter().map(|x| self.lower_pat(x))))
             }
             PatKind::Path(ref qself, ref path) => {
                 let qpath = self.lower_qpath(
@@ -2661,16 +2671,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     ImplTraitContext::disallowed(),
                 );
 
-                let fs = fields
-                    .iter()
-                    .map(|f| hir::FieldPat {
-                        hir_id: self.next_id(),
-                        ident: f.ident,
-                        pat: self.lower_pat(&f.pat),
-                        is_shorthand: f.is_shorthand,
-                        span: f.span,
-                    })
-                    .collect();
+                let fs = self.arena.alloc_from_iter(fields.iter().map(|f| hir::FieldPat {
+                    hir_id: self.next_id(),
+                    ident: f.ident,
+                    pat: self.lower_pat(&f.pat),
+                    is_shorthand: f.is_shorthand,
+                    span: f.span,
+                }));
                 hir::PatKind::Struct(qpath, fs, etc)
             }
             PatKind::Tuple(ref pats) => {
@@ -2680,8 +2687,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             PatKind::Box(ref inner) => hir::PatKind::Box(self.lower_pat(inner)),
             PatKind::Ref(ref inner, mutbl) => hir::PatKind::Ref(self.lower_pat(inner), mutbl),
             PatKind::Range(ref e1, ref e2, Spanned { node: ref end, .. }) => hir::PatKind::Range(
-                P(self.lower_expr(e1)),
-                P(self.lower_expr(e2)),
+                self.arena.alloc(self.lower_expr(e1)),
+                self.arena.alloc(self.lower_expr(e2)),
                 self.lower_range_end(end),
             ),
             PatKind::Slice(ref pats) => self.lower_pat_slice(pats),
@@ -2700,7 +2707,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         &mut self,
         pats: &[AstP<Pat>],
         ctx: &str,
-    ) -> (HirVec<P<hir::Pat<'hir>>>, Option<usize>) {
+    ) -> (&'hir [&'hir hir::Pat<'hir>], Option<usize>) {
         let mut elems = Vec::with_capacity(pats.len());
         let mut rest = None;
 
@@ -2728,7 +2735,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             }
         }
 
-        (elems.into(), rest.map(|(ddpos, _)| ddpos))
+        (self.arena.alloc_from_iter(elems), rest.map(|(ddpos, _)| ddpos))
     }
 
     /// Lower a slice pattern of form `[pat_0, ..., pat_n]` into
@@ -2788,7 +2795,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             }
         }
 
-        hir::PatKind::Slice(before.into(), slice, after.into())
+        hir::PatKind::Slice(
+            self.arena.alloc_from_iter(before),
+            slice,
+            self.arena.alloc_from_iter(after),
+        )
     }
 
     fn lower_pat_ident(
@@ -2796,7 +2807,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         p: &Pat,
         binding_mode: &BindingMode,
         ident: Ident,
-        lower_sub: impl FnOnce(&mut Self) -> Option<P<hir::Pat<'hir>>>,
+        lower_sub: impl FnOnce(&mut Self) -> Option<&'hir hir::Pat<'hir>>,
     ) -> hir::PatKind<'hir> {
         match self.resolver.get_partial_res(p.id).map(|d| d.base_res()) {
             // `None` can occur in body-less function signatures
@@ -2824,13 +2835,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         }
     }
 
-    fn pat_wild_with_node_id_of(&mut self, p: &Pat) -> P<hir::Pat<'hir>> {
+    fn pat_wild_with_node_id_of(&mut self, p: &Pat) -> &'hir hir::Pat<'hir> {
         self.pat_with_node_id_of(p, hir::PatKind::Wild)
     }
 
     /// Construct a `Pat` with the `HirId` of `p.id` lowered.
-    fn pat_with_node_id_of(&mut self, p: &Pat, kind: hir::PatKind<'hir>) -> P<hir::Pat<'hir>> {
-        P(hir::Pat { hir_id: self.lower_node_id(p.id), kind, span: p.span })
+    fn pat_with_node_id_of(&mut self, p: &Pat, kind: hir::PatKind<'hir>) -> &'hir hir::Pat<'hir> {
+        self.arena.alloc(hir::Pat { hir_id: self.lower_node_id(p.id), kind, span: p.span })
     }
 
     /// Emit a friendly error for extra `..` patterns in a tuple/tuple struct/slice pattern.
@@ -2883,7 +2894,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 ids.push({
                     hir::Stmt {
                         hir_id: self.lower_node_id(s.id),
-                        kind: hir::StmtKind::Local(P(l)),
+                        kind: hir::StmtKind::Local(self.arena.alloc(l)),
                         span: s.span,
                     }
                 });
@@ -2905,8 +2916,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     })
                     .collect();
             }
-            StmtKind::Expr(ref e) => hir::StmtKind::Expr(P(self.lower_expr(e))),
-            StmtKind::Semi(ref e) => hir::StmtKind::Semi(P(self.lower_expr(e))),
+            StmtKind::Expr(ref e) => hir::StmtKind::Expr(self.arena.alloc(self.lower_expr(e))),
+            StmtKind::Semi(ref e) => hir::StmtKind::Semi(self.arena.alloc(self.lower_expr(e))),
             StmtKind::Mac(..) => panic!("shouldn't exist here"),
         };
         smallvec![hir::Stmt { hir_id: self.lower_node_id(s.id), kind, span: s.span }]
@@ -2949,30 +2960,30 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     }
 
     fn stmt_expr(&mut self, span: Span, expr: hir::Expr<'hir>) -> hir::Stmt<'hir> {
-        self.stmt(span, hir::StmtKind::Expr(P(expr)))
+        self.stmt(span, hir::StmtKind::Expr(self.arena.alloc(expr)))
     }
 
     fn stmt_let_pat(
         &mut self,
         attrs: AttrVec,
         span: Span,
-        init: Option<P<hir::Expr<'hir>>>,
-        pat: P<hir::Pat<'hir>>,
+        init: Option<&'hir hir::Expr<'hir>>,
+        pat: &'hir hir::Pat<'hir>,
         source: hir::LocalSource,
     ) -> hir::Stmt<'hir> {
         let local = hir::Local { attrs, hir_id: self.next_id(), init, pat, source, span, ty: None };
-        self.stmt(span, hir::StmtKind::Local(P(local)))
+        self.stmt(span, hir::StmtKind::Local(self.arena.alloc(local)))
     }
 
-    fn block_expr(&mut self, expr: P<hir::Expr<'hir>>) -> hir::Block<'hir> {
-        self.block_all(expr.span, hir::HirVec::new(), Some(expr))
+    fn block_expr(&mut self, expr: &'hir hir::Expr<'hir>) -> hir::Block<'hir> {
+        self.block_all(expr.span, &[], Some(expr))
     }
 
     fn block_all(
         &mut self,
         span: Span,
-        stmts: hir::HirVec<hir::Stmt<'hir>>,
-        expr: Option<P<hir::Expr<'hir>>>,
+        stmts: &'hir [hir::Stmt<'hir>],
+        expr: Option<&'hir hir::Expr<'hir>>,
     ) -> hir::Block<'hir> {
         hir::Block {
             stmts,
@@ -2985,33 +2996,33 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     }
 
     /// Constructs a `true` or `false` literal pattern.
-    fn pat_bool(&mut self, span: Span, val: bool) -> P<hir::Pat<'hir>> {
+    fn pat_bool(&mut self, span: Span, val: bool) -> &'hir hir::Pat<'hir> {
         let expr = self.expr_bool(span, val);
-        self.pat(span, hir::PatKind::Lit(P(expr)))
+        self.pat(span, hir::PatKind::Lit(self.arena.alloc(expr)))
     }
 
-    fn pat_ok(&mut self, span: Span, pat: P<hir::Pat<'hir>>) -> P<hir::Pat<'hir>> {
-        self.pat_std_enum(span, &[sym::result, sym::Result, sym::Ok], hir_vec![pat])
+    fn pat_ok(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
+        self.pat_std_enum(span, &[sym::result, sym::Result, sym::Ok], arena_vec![self; pat])
     }
 
-    fn pat_err(&mut self, span: Span, pat: P<hir::Pat<'hir>>) -> P<hir::Pat<'hir>> {
-        self.pat_std_enum(span, &[sym::result, sym::Result, sym::Err], hir_vec![pat])
+    fn pat_err(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
+        self.pat_std_enum(span, &[sym::result, sym::Result, sym::Err], arena_vec![self; pat])
     }
 
-    fn pat_some(&mut self, span: Span, pat: P<hir::Pat<'hir>>) -> P<hir::Pat<'hir>> {
-        self.pat_std_enum(span, &[sym::option, sym::Option, sym::Some], hir_vec![pat])
+    fn pat_some(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
+        self.pat_std_enum(span, &[sym::option, sym::Option, sym::Some], arena_vec![self; pat])
     }
 
-    fn pat_none(&mut self, span: Span) -> P<hir::Pat<'hir>> {
-        self.pat_std_enum(span, &[sym::option, sym::Option, sym::None], hir_vec![])
+    fn pat_none(&mut self, span: Span) -> &'hir hir::Pat<'hir> {
+        self.pat_std_enum(span, &[sym::option, sym::Option, sym::None], &[])
     }
 
     fn pat_std_enum(
         &mut self,
         span: Span,
         components: &[Symbol],
-        subpats: hir::HirVec<P<hir::Pat<'hir>>>,
-    ) -> P<hir::Pat<'hir>> {
+        subpats: &'hir [&'hir hir::Pat<'hir>],
+    ) -> &'hir hir::Pat<'hir> {
         let path = self.std_path(span, components, None, true);
         let qpath = hir::QPath::Resolved(None, P(path));
         let pt = if subpats.is_empty() {
@@ -3022,7 +3033,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         self.pat(span, pt)
     }
 
-    fn pat_ident(&mut self, span: Span, ident: Ident) -> (P<hir::Pat<'hir>>, hir::HirId) {
+    fn pat_ident(&mut self, span: Span, ident: Ident) -> (&'hir hir::Pat<'hir>, hir::HirId) {
         self.pat_ident_binding_mode(span, ident, hir::BindingAnnotation::Unannotated)
     }
 
@@ -3031,11 +3042,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         span: Span,
         ident: Ident,
         bm: hir::BindingAnnotation,
-    ) -> (P<hir::Pat<'hir>>, hir::HirId) {
+    ) -> (&'hir hir::Pat<'hir>, hir::HirId) {
         let hir_id = self.next_id();
 
         (
-            P(hir::Pat {
+            self.arena.alloc(hir::Pat {
                 hir_id,
                 kind: hir::PatKind::Binding(bm, hir_id, ident.with_span_pos(span), None),
                 span,
@@ -3044,12 +3055,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         )
     }
 
-    fn pat_wild(&mut self, span: Span) -> P<hir::Pat<'hir>> {
+    fn pat_wild(&mut self, span: Span) -> &'hir hir::Pat<'hir> {
         self.pat(span, hir::PatKind::Wild)
     }
 
-    fn pat(&mut self, span: Span, kind: hir::PatKind<'hir>) -> P<hir::Pat<'hir>> {
-        P(hir::Pat { hir_id: self.next_id(), kind, span })
+    fn pat(&mut self, span: Span, kind: hir::PatKind<'hir>) -> &'hir hir::Pat<'hir> {
+        self.arena.alloc(hir::Pat { hir_id: self.next_id(), kind, span })
     }
 
     /// Given a suffix `["b", "c", "d"]`, returns path `::std::b::c::d` when
diff --git a/src/librustc/hir/lowering/expr.rs b/src/librustc/hir/lowering/expr.rs
index 19a732a864a..bc8a475e8a9 100644
--- a/src/librustc/hir/lowering/expr.rs
+++ b/src/librustc/hir/lowering/expr.rs
@@ -1,7 +1,7 @@
 use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs};
+use crate::hir;
 use crate::hir::def::Res;
 use crate::hir::ptr::P;
-use crate::hir::{self, HirVec};
 
 use rustc_data_structures::thin_vec::ThinVec;
 
@@ -14,26 +14,28 @@ use syntax::symbol::{sym, Symbol};
 use rustc_error_codes::*;
 
 impl<'hir> LoweringContext<'_, 'hir> {
-    fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> HirVec<hir::Expr<'hir>> {
-        exprs.iter().map(|x| self.lower_expr(x)).collect()
+    fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> &'hir [hir::Expr<'hir>] {
+        self.arena.alloc_from_iter(exprs.iter().map(|x| self.lower_expr(x)))
     }
 
     pub(super) fn lower_expr(&mut self, e: &Expr) -> hir::Expr<'hir> {
         let kind = match e.kind {
-            ExprKind::Box(ref inner) => hir::ExprKind::Box(P(self.lower_expr(inner))),
+            ExprKind::Box(ref inner) => {
+                hir::ExprKind::Box(self.arena.alloc(self.lower_expr(inner)))
+            }
             ExprKind::Array(ref exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
             ExprKind::Repeat(ref expr, ref count) => {
-                let expr = P(self.lower_expr(expr));
+                let expr = self.arena.alloc(self.lower_expr(expr));
                 let count = self.lower_anon_const(count);
                 hir::ExprKind::Repeat(expr, count)
             }
             ExprKind::Tup(ref elts) => hir::ExprKind::Tup(self.lower_exprs(elts)),
             ExprKind::Call(ref f, ref args) => {
-                let f = P(self.lower_expr(f));
+                let f = self.arena.alloc(self.lower_expr(f));
                 hir::ExprKind::Call(f, self.lower_exprs(args))
             }
             ExprKind::MethodCall(ref seg, ref args) => {
-                let hir_seg = P(self.lower_path_segment(
+                let hir_seg = self.arena.alloc(self.lower_path_segment(
                     e.span,
                     seg,
                     ParamMode::Optional,
@@ -47,26 +49,28 @@ impl<'hir> LoweringContext<'_, 'hir> {
             }
             ExprKind::Binary(binop, ref lhs, ref rhs) => {
                 let binop = self.lower_binop(binop);
-                let lhs = P(self.lower_expr(lhs));
-                let rhs = P(self.lower_expr(rhs));
+                let lhs = self.arena.alloc(self.lower_expr(lhs));
+                let rhs = self.arena.alloc(self.lower_expr(rhs));
                 hir::ExprKind::Binary(binop, lhs, rhs)
             }
             ExprKind::Unary(op, ref ohs) => {
                 let op = self.lower_unop(op);
-                let ohs = P(self.lower_expr(ohs));
+                let ohs = self.arena.alloc(self.lower_expr(ohs));
                 hir::ExprKind::Unary(op, ohs)
             }
             ExprKind::Lit(ref l) => hir::ExprKind::Lit(respan(l.span, l.kind.clone())),
             ExprKind::Cast(ref expr, ref ty) => {
-                let expr = P(self.lower_expr(expr));
-                hir::ExprKind::Cast(expr, self.lower_ty(ty, ImplTraitContext::disallowed()))
+                let expr = self.arena.alloc(self.lower_expr(expr));
+                let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
+                hir::ExprKind::Cast(expr, self.arena.alloc(ty.into_inner()))
             }
             ExprKind::Type(ref expr, ref ty) => {
-                let expr = P(self.lower_expr(expr));
-                hir::ExprKind::Type(expr, self.lower_ty(ty, ImplTraitContext::disallowed()))
+                let expr = self.arena.alloc(self.lower_expr(expr));
+                let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
+                hir::ExprKind::Type(expr, self.arena.alloc(ty.into_inner()))
             }
             ExprKind::AddrOf(k, m, ref ohs) => {
-                let ohs = P(self.lower_expr(ohs));
+                let ohs = self.arena.alloc(self.lower_expr(ohs));
                 hir::ExprKind::AddrOf(k, m, ohs)
             }
             ExprKind::Let(ref pat, ref scrutinee) => self.lower_expr_let(e.span, pat, scrutinee),
@@ -85,8 +89,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
             }),
             ExprKind::TryBlock(ref body) => self.lower_expr_try_block(body),
             ExprKind::Match(ref expr, ref arms) => hir::ExprKind::Match(
-                P(self.lower_expr(expr)),
-                arms.iter().map(|x| self.lower_arm(x)).collect(),
+                self.arena.alloc(self.lower_expr(expr)),
+                self.arena.alloc_from_iter(arms.iter().map(|x| self.lower_arm(x))),
                 hir::MatchSource::Normal,
             ),
             ExprKind::Async(capture_clause, closure_node_id, ref block) => self.make_async_expr(
@@ -122,18 +126,23 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 self.lower_block(blk, opt_label.is_some()),
                 self.lower_label(opt_label),
             ),
-            ExprKind::Assign(ref el, ref er, span) => {
-                hir::ExprKind::Assign(P(self.lower_expr(el)), P(self.lower_expr(er)), span)
-            }
+            ExprKind::Assign(ref el, ref er, span) => hir::ExprKind::Assign(
+                self.arena.alloc(self.lower_expr(el)),
+                self.arena.alloc(self.lower_expr(er)),
+                span,
+            ),
             ExprKind::AssignOp(op, ref el, ref er) => hir::ExprKind::AssignOp(
                 self.lower_binop(op),
-                P(self.lower_expr(el)),
-                P(self.lower_expr(er)),
+                self.arena.alloc(self.lower_expr(el)),
+                self.arena.alloc(self.lower_expr(er)),
             ),
-            ExprKind::Field(ref el, ident) => hir::ExprKind::Field(P(self.lower_expr(el)), ident),
-            ExprKind::Index(ref el, ref er) => {
-                hir::ExprKind::Index(P(self.lower_expr(el)), P(self.lower_expr(er)))
+            ExprKind::Field(ref el, ident) => {
+                hir::ExprKind::Field(self.arena.alloc(self.lower_expr(el)), ident)
             }
+            ExprKind::Index(ref el, ref er) => hir::ExprKind::Index(
+                self.arena.alloc(self.lower_expr(el)),
+                self.arena.alloc(self.lower_expr(er)),
+            ),
             ExprKind::Range(Some(ref e1), Some(ref e2), RangeLimits::Closed) => {
                 self.lower_expr_range_closed(e.span, e1, e2)
             }
@@ -150,26 +159,38 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 );
                 hir::ExprKind::Path(qpath)
             }
-            ExprKind::Break(opt_label, ref opt_expr) => hir::ExprKind::Break(
-                self.lower_jump_destination(e.id, opt_label),
-                opt_expr.as_ref().map(|x| P(self.lower_expr(x))),
-            ),
+            ExprKind::Break(opt_label, ref opt_expr) => {
+                let opt_expr = opt_expr
+                    .as_ref()
+                    .map(|x| -> &'hir hir::Expr<'hir> { self.arena.alloc(self.lower_expr(x)) });
+                hir::ExprKind::Break(self.lower_jump_destination(e.id, opt_label), opt_expr)
+            }
             ExprKind::Continue(opt_label) => {
                 hir::ExprKind::Continue(self.lower_jump_destination(e.id, opt_label))
             }
-            ExprKind::Ret(ref e) => hir::ExprKind::Ret(e.as_ref().map(|x| P(self.lower_expr(x)))),
+            ExprKind::Ret(ref e) => {
+                let e = e
+                    .as_ref()
+                    .map(|x| -> &'hir hir::Expr<'hir> { self.arena.alloc(self.lower_expr(x)) });
+                hir::ExprKind::Ret(e)
+            }
             ExprKind::InlineAsm(ref asm) => self.lower_expr_asm(asm),
-            ExprKind::Struct(ref path, ref fields, ref maybe_expr) => hir::ExprKind::Struct(
-                P(self.lower_qpath(
-                    e.id,
-                    &None,
-                    path,
-                    ParamMode::Optional,
-                    ImplTraitContext::disallowed(),
-                )),
-                fields.iter().map(|x| self.lower_field(x)).collect(),
-                maybe_expr.as_ref().map(|x| P(self.lower_expr(x))),
-            ),
+            ExprKind::Struct(ref path, ref fields, ref maybe_expr) => {
+                let maybe_expr = maybe_expr
+                    .as_ref()
+                    .map(|x| -> &'hir hir::Expr<'hir> { self.arena.alloc(self.lower_expr(x)) });
+                hir::ExprKind::Struct(
+                    self.arena.alloc(self.lower_qpath(
+                        e.id,
+                        &None,
+                        path,
+                        ParamMode::Optional,
+                        ImplTraitContext::disallowed(),
+                    )),
+                    self.arena.alloc_from_iter(fields.iter().map(|x| self.lower_field(x))),
+                    maybe_expr,
+                )
+            }
             ExprKind::Paren(ref ex) => {
                 let mut ex = self.lower_expr(ex);
                 // Include parens in span, but only if it is a super-span.
@@ -266,16 +287,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let then_arm = {
             let pat = self.lower_pat(pat);
             let expr = self.expr_bool(span, true);
-            self.arm(pat, P(expr))
+            self.arm(pat, self.arena.alloc(expr))
         };
         let else_arm = {
             let pat = self.pat_wild(span);
             let expr = self.expr_bool(span, false);
-            self.arm(pat, P(expr))
+            self.arm(pat, self.arena.alloc(expr))
         };
         hir::ExprKind::Match(
-            P(scrutinee),
-            vec![then_arm, else_arm].into(),
+            self.arena.alloc(scrutinee),
+            arena_vec![self; then_arm, else_arm],
             hir::MatchSource::Normal,
         )
     }
@@ -295,7 +316,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             None => (self.expr_block_empty(span), false),
             Some(els) => (self.lower_expr(els), true),
         };
-        let else_arm = self.arm(else_pat, P(else_expr));
+        let else_arm = self.arm(else_pat, self.arena.alloc(else_expr));
 
         // Handle then + scrutinee:
         let then_expr = self.lower_block_expr(then);
@@ -315,14 +336,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 // Wrap in a construct equivalent to `{ let _t = $cond; _t }`
                 // to preserve drop semantics since `if cond { ... }` does not
                 // let temporaries live outside of `cond`.
-                let cond = self.expr_drop_temps(span_block, P(cond), ThinVec::new());
+                let cond = self.expr_drop_temps(span_block, self.arena.alloc(cond), ThinVec::new());
                 let pat = self.pat_bool(span, true);
                 (pat, cond, hir::MatchSource::IfDesugar { contains_else_clause })
             }
         };
-        let then_arm = self.arm(then_pat, P(then_expr));
+        let then_arm = self.arm(then_pat, self.arena.alloc(then_expr));
 
-        hir::ExprKind::Match(P(scrutinee), vec![then_arm, else_arm].into(), desugar)
+        hir::ExprKind::Match(
+            self.arena.alloc(scrutinee),
+            arena_vec![self; then_arm, else_arm],
+            desugar,
+        )
     }
 
     fn lower_expr_while_in_loop_scope(
@@ -379,20 +404,28 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 // Wrap in a construct equivalent to `{ let _t = $cond; _t }`
                 // to preserve drop semantics since `while cond { ... }` does not
                 // let temporaries live outside of `cond`.
-                let cond = self.expr_drop_temps(span_block, P(cond), ThinVec::new());
+                let cond = self.expr_drop_temps(span_block, self.arena.alloc(cond), ThinVec::new());
                 // `true => <then>`:
                 let pat = self.pat_bool(span, true);
                 (pat, cond, hir::MatchSource::WhileDesugar, hir::LoopSource::While)
             }
         };
-        let then_arm = self.arm(then_pat, P(then_expr));
+        let then_arm = self.arm(then_pat, self.arena.alloc(then_expr));
 
         // `match <scrutinee> { ... }`
-        let match_expr =
-            self.expr_match(scrutinee.span, P(scrutinee), hir_vec![then_arm, else_arm], desugar);
+        let match_expr = self.expr_match(
+            scrutinee.span,
+            self.arena.alloc(scrutinee),
+            arena_vec![self; then_arm, else_arm],
+            desugar,
+        );
 
         // `[opt_ident]: loop { ... }`
-        hir::ExprKind::Loop(P(self.block_expr(P(match_expr))), self.lower_label(opt_label), source)
+        hir::ExprKind::Loop(
+            self.arena.alloc(self.block_expr(self.arena.alloc(match_expr))),
+            self.lower_label(opt_label),
+            source,
+        )
     }
 
     /// Desugar `try { <stmts>; <expr> }` into `{ <stmts>; ::std::ops::Try::from_ok(<expr>) }`,
@@ -400,7 +433,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
     /// and save the block id to use it as a break target for desugaring of the `?` operator.
     fn lower_expr_try_block(&mut self, body: &Block) -> hir::ExprKind<'hir> {
         self.with_catch_scope(body.id, |this| {
-            let mut block = this.lower_block(body, true).into_inner();
+            let mut block = this.lower_block_noalloc(body, true);
 
             let try_span = this.mark_span_with_reason(
                 DesugaringKind::TryBlock,
@@ -410,8 +443,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
             // Final expression of the block (if present) or `()` with span at the end of block
             let tail_expr = block.expr.take().map_or_else(
-                || this.expr_unit(this.sess.source_map().end_point(try_span)),
-                |x: P<hir::Expr<'hir>>| x.into_inner(),
+                || -> &'hir hir::Expr<'hir> {
+                    this.arena.alloc(this.expr_unit(this.sess.source_map().end_point(try_span)))
+                },
+                |x: &'hir hir::Expr<'hir>| x,
             );
 
             let ok_wrapped_span =
@@ -425,7 +460,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 ok_wrapped_span,
             ));
 
-            hir::ExprKind::Block(P(block), None)
+            hir::ExprKind::Block(this.arena.alloc(block), None)
         })
     }
 
@@ -433,24 +468,25 @@ impl<'hir> LoweringContext<'_, 'hir> {
         &mut self,
         method: Symbol,
         method_span: Span,
-        expr: hir::Expr<'hir>,
+        expr: &'hir hir::Expr<'hir>,
         overall_span: Span,
-    ) -> P<hir::Expr<'hir>> {
+    ) -> &'hir hir::Expr<'hir> {
         let path = &[sym::ops, sym::Try, method];
-        let constructor = P(self.expr_std_path(method_span, path, None, ThinVec::new()));
-        P(self.expr_call(overall_span, constructor, hir_vec![expr]))
+        let constructor =
+            self.arena.alloc(self.expr_std_path(method_span, path, None, ThinVec::new()));
+        self.arena.alloc(self.expr_call(overall_span, constructor, std::slice::from_ref(expr)))
     }
 
     fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> {
         hir::Arm {
             hir_id: self.next_id(),
-            attrs: self.lower_attrs(&arm.attrs),
+            attrs: self.lower_attrs_arena(&arm.attrs),
             pat: self.lower_pat(&arm.pat),
             guard: match arm.guard {
-                Some(ref x) => Some(hir::Guard::If(P(self.lower_expr(x)))),
+                Some(ref x) => Some(hir::Guard::If(self.arena.alloc(self.lower_expr(x)))),
                 _ => None,
             },
-            body: P(self.lower_expr(&arm.body)),
+            body: self.arena.alloc(self.lower_expr(&arm.body)),
             span: arm.span,
         }
     }
@@ -469,7 +505,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
             None => FunctionRetTy::Default(span),
         };
         let ast_decl = FnDecl { inputs: vec![], output };
-        let decl = self.lower_fn_decl(&ast_decl, None, /* impl trait allowed */ false, None);
+        let decl = self.arena.alloc(
+            self.lower_fn_decl(&ast_decl, None, /* impl trait allowed */ false, None).into_inner(),
+        );
         let body_id = self.lower_fn_body(&ast_decl, |this| {
             this.generator_kind = Some(hir::GeneratorKind::Async(async_gen_kind));
             body(this)
@@ -501,7 +539,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         );
 
         // `future::from_generator(generator)`:
-        hir::ExprKind::Call(P(gen_future), hir_vec![generator])
+        hir::ExprKind::Call(self.arena.alloc(gen_future), arena_vec![self; generator])
     }
 
     /// Desugar `<expr>.await` into:
@@ -550,7 +588,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         //     ::std::pin::Pin::new_unchecked(&mut pinned)
         // })`
         let poll_expr = {
-            let pinned = P(self.expr_ident(span, pinned_ident, pinned_pat_hid));
+            let pinned = self.arena.alloc(self.expr_ident(span, pinned_ident, pinned_pat_hid));
             let ref_mut_pinned = self.expr_mut_addr_of(span, pinned);
             let pin_ty_id = self.next_id();
             let new_unchecked_expr_kind = self.expr_call_std_assoc_fn(
@@ -558,14 +596,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 span,
                 &[sym::pin, sym::Pin],
                 "new_unchecked",
-                hir_vec![ref_mut_pinned],
+                arena_vec![self; ref_mut_pinned],
             );
-            let new_unchecked = P(self.expr(span, new_unchecked_expr_kind, ThinVec::new()));
+            let new_unchecked =
+                self.arena.alloc(self.expr(span, new_unchecked_expr_kind, ThinVec::new()));
             let unsafe_expr = self.expr_unsafe(new_unchecked);
-            P(self.expr_call_std_path(
+            self.arena.alloc(self.expr_call_std_path(
                 gen_future_span,
                 &[sym::future, sym::poll_with_tls_context],
-                hir_vec![unsafe_expr],
+                arena_vec![self; unsafe_expr],
             ))
         };
 
@@ -575,22 +614,24 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let ready_arm = {
             let x_ident = Ident::with_dummy_span(sym::result);
             let (x_pat, x_pat_hid) = self.pat_ident(span, x_ident);
-            let x_expr = P(self.expr_ident(span, x_ident, x_pat_hid));
-            let ready_pat =
-                self.pat_std_enum(span, &[sym::task, sym::Poll, sym::Ready], hir_vec![x_pat]);
-            let break_x = self.with_loop_scope(loop_node_id, |this| {
+            let x_expr = self.arena.alloc(self.expr_ident(span, x_ident, x_pat_hid));
+            let ready_pat = self.pat_std_enum(
+                span,
+                &[sym::task, sym::Poll, sym::Ready],
+                arena_vec![self; x_pat],
+            );
+            let break_x = self.with_loop_scope(loop_node_id, move |this| {
                 let expr_break =
                     hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr));
-                P(this.expr(await_span, expr_break, ThinVec::new()))
+                this.arena.alloc(this.expr(await_span, expr_break, ThinVec::new()))
             });
             self.arm(ready_pat, break_x)
         };
 
         // `::std::task::Poll::Pending => {}`
         let pending_arm = {
-            let pending_pat =
-                self.pat_std_enum(span, &[sym::task, sym::Poll, sym::Pending], hir_vec![]);
-            let empty_block = P(self.expr_block_empty(span));
+            let pending_pat = self.pat_std_enum(span, &[sym::task, sym::Poll, sym::Pending], &[]);
+            let empty_block = self.arena.alloc(self.expr_block_empty(span));
             self.arm(pending_pat, empty_block)
         };
 
@@ -598,7 +639,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             let match_expr = self.expr_match(
                 span,
                 poll_expr,
-                hir_vec![ready_arm, pending_arm],
+                arena_vec![self; ready_arm, pending_arm],
                 hir::MatchSource::AwaitDesugar,
             );
             self.stmt_expr(span, match_expr)
@@ -608,16 +649,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
             let unit = self.expr_unit(span);
             let yield_expr = self.expr(
                 span,
-                hir::ExprKind::Yield(P(unit), hir::YieldSource::Await),
+                hir::ExprKind::Yield(self.arena.alloc(unit), hir::YieldSource::Await),
                 ThinVec::new(),
             );
             self.stmt_expr(span, yield_expr)
         };
 
-        let loop_block = P(self.block_all(span, hir_vec![inner_match_stmt, yield_stmt], None));
+        let loop_block = self.arena.alloc(self.block_all(
+            span,
+            arena_vec![self; inner_match_stmt, yield_stmt],
+            None,
+        ));
 
         // loop { .. }
-        let loop_expr = P(hir::Expr {
+        let loop_expr = self.arena.alloc(hir::Expr {
             hir_id: loop_hir_id,
             kind: hir::ExprKind::Loop(loop_block, None, hir::LoopSource::Loop),
             span,
@@ -630,8 +675,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
         // match <expr> {
         //     mut pinned => loop { .. }
         // }
-        let expr = P(self.lower_expr(expr));
-        hir::ExprKind::Match(expr, hir_vec![pinned_arm], hir::MatchSource::AwaitDesugar)
+        let expr = self.arena.alloc(self.lower_expr(expr));
+        hir::ExprKind::Match(expr, arena_vec![self; pinned_arm], hir::MatchSource::AwaitDesugar)
     }
 
     fn lower_expr_closure(
@@ -644,8 +689,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
     ) -> hir::ExprKind<'hir> {
         // Lower outside new scope to preserve `is_in_loop_condition`.
         let fn_decl = self.lower_fn_decl(decl, None, false, None);
+        let fn_decl = self.arena.alloc(fn_decl.into_inner());
 
-        self.with_new_scopes(|this| {
+        self.with_new_scopes(move |this| {
             let prev = this.current_item;
             this.current_item = Some(fn_decl_span);
             let mut generator_kind = None;
@@ -706,8 +752,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
         // have to conserve the state of being inside a loop condition for the
         // closure argument types.
         let fn_decl = self.lower_fn_decl(&outer_decl, None, false, None);
+        let fn_decl = self.arena.alloc(fn_decl.into_inner());
 
-        self.with_new_scopes(|this| {
+        self.with_new_scopes(move |this| {
             // FIXME(cramertj): allow `async` non-`move` closures with arguments.
             if capture_clause == CaptureBy::Ref && !decl.inputs.is_empty() {
                 struct_span_err!(
@@ -752,7 +799,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             span,
             &[sym::ops, sym::RangeInclusive],
             "new",
-            hir_vec![e1, e2],
+            arena_vec![self; e1, e2],
         )
     }
 
@@ -777,16 +824,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
             }
         };
 
-        let fields = e1
-            .iter()
-            .map(|e| ("start", e))
-            .chain(e2.iter().map(|e| ("end", e)))
-            .map(|(s, e)| {
-                let expr = P(self.lower_expr(&e));
+        let fields = self.arena.alloc_from_iter(
+            e1.iter().map(|e| ("start", e)).chain(e2.iter().map(|e| ("end", e))).map(|(s, e)| {
+                let expr = self.arena.alloc(self.lower_expr(&e));
                 let ident = Ident::new(Symbol::intern(s), e.span);
                 self.field(ident, expr, e.span)
-            })
-            .collect::<P<[hir::Field<'hir>]>>();
+            }),
+        );
 
         let is_unit = fields.is_empty();
         let struct_path = [sym::ops, path];
@@ -796,7 +840,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         if is_unit {
             hir::ExprKind::Path(struct_path)
         } else {
-            hir::ExprKind::Struct(P(struct_path), fields, None)
+            hir::ExprKind::Struct(self.arena.alloc(struct_path), fields, None)
         }
     }
 
@@ -837,7 +881,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
     fn with_catch_scope<T, F>(&mut self, catch_id: NodeId, f: F) -> T
     where
-        F: FnOnce(&mut LoweringContext<'_, '_>) -> T,
+        F: FnOnce(&mut Self) -> T,
     {
         let len = self.catch_scopes.len();
         self.catch_scopes.push(catch_id);
@@ -856,7 +900,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
     fn with_loop_scope<T, F>(&mut self, loop_id: NodeId, f: F) -> T
     where
-        F: FnOnce(&mut LoweringContext<'_, '_>) -> T,
+        F: FnOnce(&mut Self) -> T,
     {
         // We're no longer in the base loop's condition; we're in another loop.
         let was_in_loop_condition = self.is_in_loop_condition;
@@ -881,7 +925,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
     fn with_loop_condition_scope<T, F>(&mut self, f: F) -> T
     where
-        F: FnOnce(&mut LoweringContext<'_, '_>) -> T,
+        F: FnOnce(&mut Self) -> T,
     {
         let was_in_loop_condition = self.is_in_loop_condition;
         self.is_in_loop_condition = true;
@@ -915,17 +959,21 @@ impl<'hir> LoweringContext<'_, 'hir> {
         };
         let hir_asm = hir::InlineAsm {
             inner,
-            inputs_exprs: asm.inputs.iter().map(|&(_, ref input)| self.lower_expr(input)).collect(),
-            outputs_exprs: asm.outputs.iter().map(|out| self.lower_expr(&out.expr)).collect(),
+            inputs_exprs: self
+                .arena
+                .alloc_from_iter(asm.inputs.iter().map(|&(_, ref input)| self.lower_expr(input))),
+            outputs_exprs: self
+                .arena
+                .alloc_from_iter(asm.outputs.iter().map(|out| self.lower_expr(&out.expr))),
         };
-        hir::ExprKind::InlineAsm(P(hir_asm))
+        hir::ExprKind::InlineAsm(self.arena.alloc(hir_asm))
     }
 
     fn lower_field(&mut self, f: &Field) -> hir::Field<'hir> {
         hir::Field {
             hir_id: self.next_id(),
             ident: f.ident,
-            expr: P(self.lower_expr(&f.expr)),
+            expr: self.arena.alloc(self.lower_expr(&f.expr)),
             span: f.span,
             is_shorthand: f.is_shorthand,
         }
@@ -944,7 +992,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let expr =
             opt_expr.as_ref().map(|x| self.lower_expr(x)).unwrap_or_else(|| self.expr_unit(span));
 
-        hir::ExprKind::Yield(P(expr), hir::YieldSource::Yield)
+        hir::ExprKind::Yield(self.arena.alloc(expr), hir::YieldSource::Yield)
     }
 
     /// Desugar `ExprForLoop` from: `[opt_ident]: for <pat> in <head> <body>` into:
@@ -992,9 +1040,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let pat_arm = {
             let val_ident = Ident::with_dummy_span(sym::val);
             let (val_pat, val_pat_hid) = self.pat_ident(pat.span, val_ident);
-            let val_expr = P(self.expr_ident(pat.span, val_ident, val_pat_hid));
-            let next_expr = P(self.expr_ident(pat.span, next_ident, next_pat_hid));
-            let assign = P(self.expr(
+            let val_expr = self.arena.alloc(self.expr_ident(pat.span, val_ident, val_pat_hid));
+            let next_expr = self.arena.alloc(self.expr_ident(pat.span, next_ident, next_pat_hid));
+            let assign = self.arena.alloc(self.expr(
                 pat.span,
                 hir::ExprKind::Assign(next_expr, val_expr, pat.span),
                 ThinVec::new(),
@@ -1017,18 +1065,21 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
         // `match ::std::iter::Iterator::next(&mut iter) { ... }`
         let match_expr = {
-            let iter = P(self.expr_ident(desugared_span, iter, iter_pat_nid));
+            let iter = self.arena.alloc(self.expr_ident(desugared_span, iter, iter_pat_nid));
             let ref_mut_iter = self.expr_mut_addr_of(desugared_span, iter);
             let next_path = &[sym::iter, sym::Iterator, sym::next];
-            let next_expr =
-                P(self.expr_call_std_path(desugared_span, next_path, hir_vec![ref_mut_iter]));
-            let arms = hir_vec![pat_arm, break_arm];
+            let next_expr = self.arena.alloc(self.expr_call_std_path(
+                desugared_span,
+                next_path,
+                arena_vec![self; ref_mut_iter],
+            ));
+            let arms = arena_vec![self; pat_arm, break_arm];
 
             self.expr_match(desugared_span, next_expr, arms, hir::MatchSource::ForLoopDesugar)
         };
         let match_stmt = self.stmt_expr(desugared_span, match_expr);
 
-        let next_expr = P(self.expr_ident(desugared_span, next_ident, next_pat_hid));
+        let next_expr = self.arena.alloc(self.expr_ident(desugared_span, next_ident, next_pat_hid));
 
         // `let mut __next`
         let next_let = self.stmt_let_pat(
@@ -1053,13 +1104,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let body_expr = self.expr_block(body_block, ThinVec::new());
         let body_stmt = self.stmt_expr(body.span, body_expr);
 
-        let loop_block =
-            P(self.block_all(e.span, hir_vec![next_let, match_stmt, pat_let, body_stmt], None));
+        let loop_block = self.arena.alloc(self.block_all(
+            e.span,
+            arena_vec![self; next_let, match_stmt, pat_let, body_stmt],
+            None,
+        ));
 
         // `[opt_ident]: loop { ... }`
         let kind =
             hir::ExprKind::Loop(loop_block, self.lower_label(opt_label), hir::LoopSource::ForLoop);
-        let loop_expr = P(hir::Expr {
+        let loop_expr = self.arena.alloc(hir::Expr {
             hir_id: self.lower_node_id(e.id),
             kind,
             span: e.span,
@@ -1072,13 +1126,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
         // `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
         let into_iter_expr = {
             let into_iter_path = &[sym::iter, sym::IntoIterator, sym::into_iter];
-            P(self.expr_call_std_path(desugared_span, into_iter_path, hir_vec![head]))
+            self.arena.alloc(self.expr_call_std_path(
+                desugared_span,
+                into_iter_path,
+                arena_vec![self; head],
+            ))
         };
 
-        let match_expr = P(self.expr_match(
+        let match_expr = self.arena.alloc(self.expr_match(
             desugared_span,
             into_iter_expr,
-            hir_vec![iter_arm],
+            arena_vec![self; iter_arm],
             hir::MatchSource::ForLoopDesugar,
         ));
 
@@ -1121,7 +1179,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
             let sub_expr = self.lower_expr(sub_expr);
 
             let path = &[sym::ops, sym::Try, sym::into_result];
-            P(self.expr_call_std_path(unstable_span, path, hir_vec![sub_expr]))
+            self.arena.alloc(self.expr_call_std_path(
+                unstable_span,
+                path,
+                arena_vec![self; sub_expr],
+            ))
         };
 
         // `#[allow(unreachable_code)]`
@@ -1141,7 +1203,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let ok_arm = {
             let val_ident = Ident::with_dummy_span(sym::val);
             let (val_pat, val_pat_nid) = self.pat_ident(span, val_ident);
-            let val_expr = P(self.expr_ident_with_attrs(
+            let val_expr = self.arena.alloc(self.expr_ident_with_attrs(
                 span,
                 val_ident,
                 val_pat_nid,
@@ -1159,7 +1221,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
             let from_expr = {
                 let from_path = &[sym::convert, sym::From, sym::from];
                 let err_expr = self.expr_ident(try_span, err_ident, err_local_nid);
-                self.expr_call_std_path(try_span, from_path, hir_vec![err_expr])
+                self.arena.alloc(self.expr_call_std_path(
+                    try_span,
+                    from_path,
+                    arena_vec![self; err_expr],
+                ))
             };
             let from_err_expr =
                 self.wrap_in_try_constructor(sym::from_error, unstable_span, from_expr, try_span);
@@ -1167,7 +1233,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             let catch_scope = self.catch_scopes.last().map(|x| *x);
             let ret_expr = if let Some(catch_node) = catch_scope {
                 let target_id = Ok(self.lower_node_id(catch_node));
-                P(self.expr(
+                self.arena.alloc(self.expr(
                     try_span,
                     hir::ExprKind::Break(
                         hir::Destination { label: None, target_id },
@@ -1176,14 +1242,22 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     thin_attrs,
                 ))
             } else {
-                P(self.expr(try_span, hir::ExprKind::Ret(Some(from_err_expr)), thin_attrs))
+                self.arena.alloc(self.expr(
+                    try_span,
+                    hir::ExprKind::Ret(Some(from_err_expr)),
+                    thin_attrs,
+                ))
             };
 
             let err_pat = self.pat_err(try_span, err_local);
             self.arm(err_pat, ret_expr)
         };
 
-        hir::ExprKind::Match(scrutinee, hir_vec![err_arm, ok_arm], hir::MatchSource::TryDesugar)
+        hir::ExprKind::Match(
+            scrutinee,
+            arena_vec![self; err_arm, ok_arm],
+            hir::MatchSource::TryDesugar,
+        )
     }
 
     // =========================================================================
@@ -1205,7 +1279,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
     pub(super) fn expr_drop_temps(
         &mut self,
         span: Span,
-        expr: P<hir::Expr<'hir>>,
+        expr: &'hir hir::Expr<'hir>,
         attrs: AttrVec,
     ) -> hir::Expr<'hir> {
         self.expr(span, hir::ExprKind::DropTemps(expr), attrs)
@@ -1214,19 +1288,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
     fn expr_match(
         &mut self,
         span: Span,
-        arg: P<hir::Expr<'hir>>,
-        arms: hir::HirVec<hir::Arm<'hir>>,
+        arg: &'hir hir::Expr<'hir>,
+        arms: &'hir [hir::Arm<'hir>],
         source: hir::MatchSource,
     ) -> hir::Expr<'hir> {
         self.expr(span, hir::ExprKind::Match(arg, arms, source), ThinVec::new())
     }
 
-    fn expr_break(&mut self, span: Span, attrs: AttrVec) -> P<hir::Expr<'hir>> {
+    fn expr_break(&mut self, span: Span, attrs: AttrVec) -> &'hir hir::Expr<'hir> {
         let expr_break = hir::ExprKind::Break(self.lower_loop_destination(None), None);
-        P(self.expr(span, expr_break, attrs))
+        self.arena.alloc(self.expr(span, expr_break, attrs))
     }
 
-    fn expr_mut_addr_of(&mut self, span: Span, e: P<hir::Expr<'_>>) -> hir::Expr<'_> {
+    fn expr_mut_addr_of(&mut self, span: Span, e: &'hir hir::Expr<'hir>) -> hir::Expr<'hir> {
         self.expr(
             span,
             hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, e),
@@ -1235,18 +1309,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
     }
 
     fn expr_unit(&mut self, sp: Span) -> hir::Expr<'hir> {
-        self.expr_tuple(sp, hir_vec![])
+        self.expr_tuple(sp, &[])
     }
 
-    fn expr_tuple(&mut self, sp: Span, exprs: hir::HirVec<hir::Expr<'hir>>) -> hir::Expr<'hir> {
+    fn expr_tuple(&mut self, sp: Span, exprs: &'hir [hir::Expr<'hir>]) -> hir::Expr<'hir> {
         self.expr(sp, hir::ExprKind::Tup(exprs), ThinVec::new())
     }
 
     fn expr_call(
         &mut self,
         span: Span,
-        e: P<hir::Expr<'hir>>,
-        args: hir::HirVec<hir::Expr<'hir>>,
+        e: &'hir hir::Expr<'hir>,
+        args: &'hir [hir::Expr<'hir>],
     ) -> hir::Expr<'hir> {
         self.expr(span, hir::ExprKind::Call(e, args), ThinVec::new())
     }
@@ -1256,9 +1330,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
         &mut self,
         span: Span,
         path_components: &[Symbol],
-        args: hir::HirVec<hir::Expr<'hir>>,
+        args: &'hir [hir::Expr<'hir>],
     ) -> hir::Expr<'hir> {
-        let path = P(self.expr_std_path(span, path_components, None, ThinVec::new()));
+        let path =
+            self.arena.alloc(self.expr_std_path(span, path_components, None, ThinVec::new()));
         self.expr_call(span, path, args)
     }
 
@@ -1277,13 +1352,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
         span: Span,
         ty_path_components: &[Symbol],
         assoc_fn_name: &str,
-        args: hir::HirVec<hir::Expr<'hir>>,
+        args: &'hir [hir::Expr<'hir>],
     ) -> hir::ExprKind<'hir> {
         let ty_path = P(self.std_path(span, ty_path_components, None, false));
         let ty = P(self.ty_path(ty_path_id, span, hir::QPath::Resolved(None, ty_path)));
         let fn_seg = P(hir::PathSegment::from_ident(Ident::from_str(assoc_fn_name)));
         let fn_path = hir::QPath::TypeRelative(ty, fn_seg);
-        let fn_expr = P(self.expr(span, hir::ExprKind::Path(fn_path), ThinVec::new()));
+        let fn_expr =
+            self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path), ThinVec::new()));
         hir::ExprKind::Call(fn_expr, args)
     }
 
@@ -1326,14 +1402,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
         self.expr(span, expr_path, attrs)
     }
 
-    fn expr_unsafe(&mut self, expr: P<hir::Expr<'hir>>) -> hir::Expr<'hir> {
+    fn expr_unsafe(&mut self, expr: &'hir hir::Expr<'hir>) -> hir::Expr<'hir> {
         let hir_id = self.next_id();
         let span = expr.span;
         self.expr(
             span,
             hir::ExprKind::Block(
-                P(hir::Block {
-                    stmts: hir_vec![],
+                self.arena.alloc(hir::Block {
+                    stmts: &[],
                     expr: Some(expr),
                     hir_id,
                     rules: hir::UnsafeBlock(hir::CompilerGenerated),
@@ -1347,11 +1423,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
     }
 
     fn expr_block_empty(&mut self, span: Span) -> hir::Expr<'hir> {
-        let blk = self.block_all(span, hir_vec![], None);
-        self.expr_block(P(blk), ThinVec::new())
+        let blk = self.block_all(span, &[], None);
+        self.expr_block(self.arena.alloc(blk), ThinVec::new())
     }
 
-    pub(super) fn expr_block(&mut self, b: P<hir::Block<'hir>>, attrs: AttrVec) -> hir::Expr<'hir> {
+    pub(super) fn expr_block(
+        &mut self,
+        b: &'hir hir::Block<'hir>,
+        attrs: AttrVec,
+    ) -> hir::Expr<'hir> {
         self.expr(b.span, hir::ExprKind::Block(b, None), attrs)
     }
 
@@ -1364,14 +1444,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
         hir::Expr { hir_id: self.next_id(), kind, span, attrs }
     }
 
-    fn field(&mut self, ident: Ident, expr: P<hir::Expr<'hir>>, span: Span) -> hir::Field<'hir> {
+    fn field(&mut self, ident: Ident, expr: &'hir hir::Expr<'hir>, span: Span) -> hir::Field<'hir> {
         hir::Field { hir_id: self.next_id(), ident, span, expr, is_shorthand: false }
     }
 
-    fn arm(&mut self, pat: P<hir::Pat<'hir>>, expr: P<hir::Expr<'hir>>) -> hir::Arm<'hir> {
+    fn arm(&mut self, pat: &'hir hir::Pat<'hir>, expr: &'hir hir::Expr<'hir>) -> hir::Arm<'hir> {
         hir::Arm {
             hir_id: self.next_id(),
-            attrs: hir_vec![],
+            attrs: &[],
             pat,
             guard: None,
             span: expr.span,
diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs
index 8016ab5c592..19ef106b9bd 100644
--- a/src/librustc/hir/lowering/item.rs
+++ b/src/librustc/hir/lowering/item.rs
@@ -1005,7 +1005,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
     fn lower_param(&mut self, param: &Param) -> hir::Param<'hir> {
         hir::Param {
-            attrs: self.lower_attrs(&param.attrs),
+            attrs: self.lower_attrs_arena(&param.attrs),
             hir_id: self.lower_node_id(param.id),
             pat: self.lower_pat(&param.pat),
             span: param.span,
@@ -1066,8 +1066,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
         };
 
         self.lower_body(|this| {
-            let mut parameters: Vec<hir::Param<'hir>> = Vec::new();
-            let mut statements: Vec<hir::Stmt<'hir>> = Vec::new();
+            let mut parameters: Vec<hir::Param<'_>> = Vec::new();
+            let mut statements: Vec<hir::Stmt<'_>> = Vec::new();
 
             // Async function parameters are lowered into the closure body so that they are
             // captured and so that the drop order matches the equivalent non-async functions.
@@ -1145,7 +1145,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     let stmt = this.stmt_let_pat(
                         stmt_attrs,
                         desugared_span,
-                        Some(P(expr)),
+                        Some(this.arena.alloc(expr)),
                         parameter.pat,
                         hir::LocalSource::AsyncFn,
                     );
@@ -1175,7 +1175,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     let move_stmt = this.stmt_let_pat(
                         AttrVec::new(),
                         desugared_span,
-                        Some(P(move_expr)),
+                        Some(this.arena.alloc(move_expr)),
                         move_pat,
                         hir::LocalSource::AsyncFn,
                     );
@@ -1186,7 +1186,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     let pattern_stmt = this.stmt_let_pat(
                         stmt_attrs,
                         desugared_span,
-                        Some(P(pattern_expr)),
+                        Some(this.arena.alloc(pattern_expr)),
                         parameter.pat,
                         hir::LocalSource::AsyncFn,
                     );
@@ -1212,8 +1212,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     // Transform into `drop-temps { <user-body> }`, an expression:
                     let desugared_span =
                         this.mark_span_with_reason(DesugaringKind::Async, user_body.span, None);
-                    let user_body =
-                        this.expr_drop_temps(desugared_span, P(user_body), AttrVec::new());
+                    let user_body = this.expr_drop_temps(
+                        desugared_span,
+                        this.arena.alloc(user_body),
+                        AttrVec::new(),
+                    );
 
                     // As noted above, create the final block like
                     //
@@ -1224,9 +1227,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     //   drop-temps { <user-body> }
                     // }
                     // ```
-                    let body =
-                        this.block_all(desugared_span, statements.into(), Some(P(user_body)));
-                    this.expr_block(P(body), AttrVec::new())
+                    let body = this.block_all(
+                        desugared_span,
+                        this.arena.alloc_from_iter(statements),
+                        Some(this.arena.alloc(user_body)),
+                    );
+
+                    this.expr_block(this.arena.alloc(body), AttrVec::new())
                 },
             );
 
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 8a450cf167a..003917ee1e1 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -50,6 +50,15 @@ macro_rules! hir_vec {
     );
 }
 
+macro_rules! arena_vec {
+    () => (
+        &[]
+    );
+    ($this:expr; $($x:expr),*) => (
+        $this.arena.alloc_from_iter(vec![$($x),*])
+    );
+}
+
 pub mod check_attr;
 pub mod def;
 pub mod def_id;