]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/hir/lowering.rs
Retire HirVec.
[rust.git] / src / librustc / hir / lowering.rs
index f6db451d57ead86c101730c3eb197fa5f39cc4f1..e4836ef4eef8928ea75f65f833f461b5f270c63a 100644 (file)
 //! get confused if the spans from leaf AST nodes occur in multiple places
 //! in the HIR, especially for multiple identifiers.
 
-mod expr;
-mod item;
-
 use crate::arena::Arena;
 use crate::dep_graph::DepGraph;
 use crate::hir::def::{DefKind, Namespace, PartialRes, PerNS, Res};
 use crate::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX};
 use crate::hir::map::{DefKey, DefPathData, Definitions};
 use crate::hir::ptr::P;
-use crate::hir::HirVec;
 use crate::hir::{self, ParamName};
 use crate::hir::{ConstArg, GenericArg};
 use crate::lint;
@@ -49,6 +45,7 @@
 use crate::middle::cstore::CrateStore;
 use crate::session::config::nightly_options;
 use crate::session::Session;
+use crate::util::captures::Captures;
 use crate::util::common::FN_OUTPUT_NAME;
 use crate::util::nodemap::{DefIdMap, NodeMap};
 use errors::Applicability;
 
 use rustc_error_codes::*;
 
+macro_rules! arena_vec {
+    () => (
+        &[]
+    );
+    ($this:expr; $($x:expr),*) => (
+        $this.arena.alloc_from_iter(vec![$($x),*])
+    );
+}
+
+mod expr;
+mod item;
+
 const HIR_ID_COUNTER_LOCKED: u32 = 0xFFFFFFFF;
 
 pub struct LoweringContext<'a, 'hir: 'a> {
@@ -159,6 +168,7 @@ pub struct LoweringContext<'a, 'hir: 'a> {
 
     allow_try_trait: Option<Lrc<[Symbol]>>,
     allow_gen_future: Option<Lrc<[Symbol]>>,
+    allow_into_future: Option<Lrc<[Symbol]>>,
 }
 
 pub trait Resolver {
@@ -197,13 +207,13 @@ fn resolve_str_path(
 /// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree,
 /// and if so, what meaning it has.
 #[derive(Debug)]
-enum ImplTraitContext<'a> {
+enum ImplTraitContext<'b, 'a> {
     /// Treat `impl Trait` as shorthand for a new universal generic parameter.
     /// Example: `fn foo(x: impl Debug)`, where `impl Debug` is conceptually
     /// equivalent to a fresh universal parameter like `fn foo<T: Debug>(x: T)`.
     ///
     /// Newly generated parameters should be inserted into the given `Vec`.
-    Universal(&'a mut Vec<hir::GenericParam>),
+    Universal(&'b mut Vec<hir::GenericParam<'a>>),
 
     /// Treat `impl Trait` as shorthand for a new opaque type.
     /// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually
@@ -228,13 +238,13 @@ enum ImplTraitPosition {
     Other,
 }
 
-impl<'a> ImplTraitContext<'a> {
+impl<'b, 'a> ImplTraitContext<'b, 'a> {
     #[inline]
     fn disallowed() -> Self {
         ImplTraitContext::Disallowed(ImplTraitPosition::Other)
     }
 
-    fn reborrow(&'b mut self) -> ImplTraitContext<'b> {
+    fn reborrow(&'c mut self) -> ImplTraitContext<'c, 'a> {
         use self::ImplTraitContext::*;
         match self {
             Universal(params) => Universal(params),
@@ -291,6 +301,7 @@ pub fn lower_crate<'a, 'hir>(
         in_scope_lifetimes: Vec::new(),
         allow_try_trait: Some([sym::try_trait][..].into()),
         allow_gen_future: Some([sym::gen_future][..].into()),
+        allow_into_future: Some([sym::into_future][..].into()),
     }
     .lower_crate(krate)
 }
@@ -528,7 +539,7 @@ fn visit_ty(&mut self, t: &'tcx Ty) {
         visit::walk_crate(&mut item::ItemLowerer { lctx: &mut self }, c);
 
         let module = self.lower_mod(&c.module);
-        let attrs = self.arena.alloc_from_iter(self.lower_attrs(&c.attrs).into_iter());
+        let attrs = self.lower_attrs(&c.attrs);
         let body_ids = body_ids(&self.bodies);
 
         self.resolver.definitions().init_node_id_to_hir_id_mapping(self.node_id_to_hir_id);
@@ -730,9 +741,9 @@ fn collect_in_band_defs<T, F>(
         parent_id: DefId,
         anonymous_lifetime_mode: AnonymousLifetimeMode,
         f: F,
-    ) -> (Vec<hir::GenericParam>, T)
+    ) -> (Vec<hir::GenericParam<'hir>>, T)
     where
-        F: FnOnce(&mut LoweringContext<'_, '_>) -> (Vec<hir::GenericParam>, T),
+        F: FnOnce(&mut Self) -> (Vec<hir::GenericParam<'hir>>, T),
     {
         assert!(!self.is_collecting_in_band_lifetimes);
         assert!(self.lifetimes_to_define.is_empty());
@@ -763,7 +774,7 @@ fn lifetime_to_generic_param(
         span: Span,
         hir_name: ParamName,
         parent_index: DefIndex,
-    ) -> hir::GenericParam {
+    ) -> hir::GenericParam<'hir> {
         let node_id = self.resolver.next_node_id();
 
         // Get the name we'll use to make the def-path. Note
@@ -787,8 +798,8 @@ fn lifetime_to_generic_param(
         hir::GenericParam {
             hir_id: self.lower_node_id(node_id),
             name: hir_name,
-            attrs: hir_vec![],
-            bounds: hir_vec![],
+            attrs: &[],
+            bounds: &[],
             span,
             pure_wrt_drop: false,
             kind: hir::GenericParamKind::Lifetime { kind },
@@ -838,7 +849,7 @@ fn collect_fresh_in_band_lifetime(&mut self, span: Span) -> ParamName {
     // for them.
     fn with_in_scope_lifetime_defs<T, F>(&mut self, params: &[GenericParam], f: F) -> T
     where
-        F: FnOnce(&mut LoweringContext<'_, 'hir>) -> T,
+        F: FnOnce(&mut Self) -> T,
     {
         let old_len = self.in_scope_lifetimes.len();
         let lt_def_names = params.iter().filter_map(|param| match param.kind {
@@ -865,9 +876,9 @@ fn add_in_band_defs<F, T>(
         parent_id: DefId,
         anonymous_lifetime_mode: AnonymousLifetimeMode,
         f: F,
-    ) -> (hir::Generics, T)
+    ) -> (hir::Generics<'hir>, T)
     where
-        F: FnOnce(&mut LoweringContext<'_, '_>, &mut Vec<hir::GenericParam>) -> T,
+        F: FnOnce(&mut Self, &mut Vec<hir::GenericParam<'hir>>) -> T,
     {
         let (in_band_defs, (mut lowered_generics, res)) =
             self.with_in_scope_lifetime_defs(&generics.params, |this| {
@@ -881,7 +892,7 @@ fn add_in_band_defs<F, T>(
                     // in-band-lifetimes introduced by generics or where-clauses
                     // wouldn't have been added yet.
                     let generics =
-                        this.lower_generics(generics, ImplTraitContext::Universal(&mut params));
+                        this.lower_generics_mut(generics, ImplTraitContext::Universal(&mut params));
                     let res = f(this, &mut params);
                     (params, (generics, res))
                 })
@@ -902,12 +913,13 @@ fn add_in_band_defs<F, T>(
 
         lowered_generics.params = lowered_params.into();
 
+        let lowered_generics = lowered_generics.into_generics(self.arena);
         (lowered_generics, res)
     }
 
     fn with_dyn_type_scope<T, F>(&mut self, in_scope: bool, f: F) -> T
     where
-        F: FnOnce(&mut LoweringContext<'_, '_>) -> T,
+        F: FnOnce(&mut Self) -> T,
     {
         let was_in_dyn_type = self.is_in_dyn_type;
         self.is_in_dyn_type = in_scope;
@@ -921,7 +933,7 @@ fn with_dyn_type_scope<T, F>(&mut self, in_scope: bool, f: F) -> T
 
     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;
@@ -945,14 +957,10 @@ fn def_key(&mut self, id: DefId) -> DefKey {
         }
     }
 
-    fn lower_attrs_arena(&mut self, attrs: &[Attribute]) -> &'hir [Attribute] {
+    fn lower_attrs(&mut self, attrs: &[Attribute]) -> &'hir [Attribute] {
         self.arena.alloc_from_iter(attrs.iter().map(|a| self.lower_attr(a)))
     }
 
-    fn lower_attrs(&mut self, attrs: &[Attribute]) -> hir::HirVec<Attribute> {
-        attrs.iter().map(|a| self.lower_attr(a)).collect::<Vec<_>>().into()
-    }
-
     fn lower_attr(&mut self, attr: &Attribute) -> Attribute {
         // Note that we explicitly do not walk the path. Since we don't really
         // lower attributes (we use the AST version) there is nowhere to keep
@@ -1016,8 +1024,8 @@ fn lower_token(&mut self, token: Token) -> TokenStream {
     fn lower_assoc_ty_constraint(
         &mut self,
         constraint: &AssocTyConstraint,
-        itctx: ImplTraitContext<'_>,
-    ) -> hir::TypeBinding {
+        itctx: ImplTraitContext<'_, 'hir>,
+    ) -> hir::TypeBinding<'hir> {
         debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", constraint, itctx);
 
         let kind = match constraint.kind {
@@ -1113,8 +1121,8 @@ fn lower_assoc_ty_constraint(
     fn lower_generic_arg(
         &mut self,
         arg: &ast::GenericArg,
-        itctx: ImplTraitContext<'_>,
-    ) -> hir::GenericArg {
+        itctx: ImplTraitContext<'_, 'hir>,
+    ) -> hir::GenericArg<'hir> {
         match arg {
             ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(&lt)),
             ast::GenericArg::Type(ty) => {
@@ -1169,8 +1177,8 @@ fn lower_generic_arg(
         }
     }
 
-    fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext<'_>) -> P<hir::Ty> {
-        P(self.lower_ty_direct(t, itctx))
+    fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext<'_, 'hir>) -> &'hir hir::Ty<'hir> {
+        self.arena.alloc(self.lower_ty_direct(t, itctx))
     }
 
     fn lower_path_ty(
@@ -1179,8 +1187,8 @@ fn lower_path_ty(
         qself: &Option<QSelf>,
         path: &Path,
         param_mode: ParamMode,
-        itctx: ImplTraitContext<'_>,
-    ) -> hir::Ty {
+        itctx: ImplTraitContext<'_, 'hir>,
+    ) -> hir::Ty<'hir> {
         let id = self.lower_node_id(t.id);
         let qpath = self.lower_qpath(t.id, qself, path, param_mode, itctx);
         let ty = self.ty_path(id, t.span, qpath);
@@ -1190,15 +1198,15 @@ fn lower_path_ty(
         ty
     }
 
-    fn ty(&mut self, span: Span, kind: hir::TyKind) -> hir::Ty {
+    fn ty(&mut self, span: Span, kind: hir::TyKind<'hir>) -> hir::Ty<'hir> {
         hir::Ty { hir_id: self.next_id(), kind, span }
     }
 
-    fn ty_tup(&mut self, span: Span, tys: HirVec<hir::Ty>) -> hir::Ty {
+    fn ty_tup(&mut self, span: Span, tys: &'hir [hir::Ty<'hir>]) -> hir::Ty<'hir> {
         self.ty(span, hir::TyKind::Tup(tys))
     }
 
-    fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_>) -> hir::Ty {
+    fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_, 'hir>) -> hir::Ty<'hir> {
         let kind = match t.kind {
             TyKind::Infer => hir::TyKind::Infer,
             TyKind::Err => hir::TyKind::Err,
@@ -1214,7 +1222,7 @@ fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_>) -> hir::T
             }
             TyKind::BareFn(ref f) => self.with_in_scope_lifetime_defs(&f.generic_params, |this| {
                 this.with_anonymous_lifetime_mode(AnonymousLifetimeMode::PassThrough, |this| {
-                    hir::TyKind::BareFn(P(hir::BareFnTy {
+                    hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy {
                         generic_params: this.lower_generic_params(
                             &f.generic_params,
                             &NodeMap::default(),
@@ -1228,9 +1236,11 @@ fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_>) -> hir::T
                 })
             }),
             TyKind::Never => hir::TyKind::Never,
-            TyKind::Tup(ref tys) => hir::TyKind::Tup(
-                tys.iter().map(|ty| self.lower_ty_direct(ty, itctx.reborrow())).collect(),
-            ),
+            TyKind::Tup(ref tys) => {
+                hir::TyKind::Tup(self.arena.alloc_from_iter(
+                    tys.iter().map(|ty| self.lower_ty_direct(ty, itctx.reborrow())),
+                ))
+            }
             TyKind::Paren(ref ty) => {
                 return self.lower_ty_direct(ty, itctx);
             }
@@ -1242,11 +1252,11 @@ fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_>) -> hir::T
                 let res = self.lower_res(res);
                 hir::TyKind::Path(hir::QPath::Resolved(
                     None,
-                    P(hir::Path {
+                    self.arena.alloc(hir::Path {
                         res,
-                        segments: hir_vec![hir::PathSegment::from_ident(Ident::with_dummy_span(
-                            kw::SelfUpper
-                        ))],
+                        segments: arena_vec![self; hir::PathSegment::from_ident(
+                            Ident::with_dummy_span(kw::SelfUpper)
+                        )],
                         span: t.span,
                     }),
                 ))
@@ -1258,21 +1268,21 @@ fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_>) -> hir::T
             TyKind::TraitObject(ref bounds, kind) => {
                 let mut lifetime_bound = None;
                 let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| {
-                    let bounds = bounds
-                        .iter()
-                        .filter_map(|bound| match *bound {
-                            GenericBound::Trait(ref ty, TraitBoundModifier::None) => {
-                                Some(this.lower_poly_trait_ref(ty, itctx.reborrow()))
-                            }
-                            GenericBound::Trait(_, TraitBoundModifier::Maybe) => None,
-                            GenericBound::Outlives(ref lifetime) => {
-                                if lifetime_bound.is_none() {
-                                    lifetime_bound = Some(this.lower_lifetime(lifetime));
+                    let bounds =
+                        this.arena.alloc_from_iter(bounds.iter().filter_map(
+                            |bound| match *bound {
+                                GenericBound::Trait(ref ty, TraitBoundModifier::None) => {
+                                    Some(this.lower_poly_trait_ref(ty, itctx.reborrow()))
                                 }
-                                None
-                            }
-                        })
-                        .collect();
+                                GenericBound::Trait(_, TraitBoundModifier::Maybe) => None,
+                                GenericBound::Outlives(ref lifetime) => {
+                                    if lifetime_bound.is_none() {
+                                        lifetime_bound = Some(this.lower_lifetime(lifetime));
+                                    }
+                                    None
+                                }
+                            },
+                        ));
                     let lifetime_bound =
                         lifetime_bound.unwrap_or_else(|| this.elided_dyn_bound(t.span));
                     (bounds, lifetime_bound)
@@ -1305,7 +1315,7 @@ fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_>) -> hir::T
                             hir_id: self.lower_node_id(def_node_id),
                             name: ParamName::Plain(ident),
                             pure_wrt_drop: false,
-                            attrs: hir_vec![],
+                            attrs: &[],
                             bounds: hir_bounds,
                             span,
                             kind: hir::GenericParamKind::Type {
@@ -1316,10 +1326,10 @@ fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_>) -> hir::T
 
                         hir::TyKind::Path(hir::QPath::Resolved(
                             None,
-                            P(hir::Path {
+                            self.arena.alloc(hir::Path {
                                 span,
                                 res: Res::Def(DefKind::TyParam, DefId::local(def_index)),
-                                segments: hir_vec![hir::PathSegment::from_ident(ident)],
+                                segments: arena_vec![self; hir::PathSegment::from_ident(ident)],
                             }),
                         ))
                     }
@@ -1367,8 +1377,8 @@ fn lower_opaque_impl_trait(
         span: Span,
         fn_def_id: Option<DefId>,
         opaque_ty_node_id: NodeId,
-        lower_bounds: impl FnOnce(&mut LoweringContext<'_, '_>) -> hir::GenericBounds,
-    ) -> hir::TyKind {
+        lower_bounds: impl FnOnce(&mut Self) -> hir::GenericBounds<'hir>,
+    ) -> hir::TyKind<'hir> {
         debug!(
             "lower_opaque_impl_trait(fn_def_id={:?}, opaque_ty_node_id={:?}, span={:?})",
             fn_def_id, opaque_ty_node_id, span,
@@ -1398,11 +1408,11 @@ fn lower_opaque_impl_trait(
 
         debug!("lower_opaque_impl_trait: lifetime_defs={:#?}", lifetime_defs,);
 
-        self.with_hir_id_owner(opaque_ty_node_id, |lctx| {
+        self.with_hir_id_owner(opaque_ty_node_id, move |lctx| {
             let opaque_ty_item = hir::OpaqueTy {
                 generics: hir::Generics {
                     params: lifetime_defs,
-                    where_clause: hir::WhereClause { predicates: hir_vec![], span },
+                    where_clause: hir::WhereClause { predicates: &[], span },
                     span,
                 },
                 bounds: hir_bounds,
@@ -1424,7 +1434,7 @@ fn lower_opaque_impl_trait(
     fn generate_opaque_type(
         &mut self,
         opaque_ty_node_id: NodeId,
-        opaque_ty_item: hir::OpaqueTy,
+        opaque_ty_item: hir::OpaqueTy<'hir>,
         span: Span,
         opaque_ty_span: Span,
     ) -> hir::HirId {
@@ -1452,8 +1462,8 @@ fn lifetimes_from_impl_trait_bounds(
         &mut self,
         opaque_ty_id: NodeId,
         parent_index: DefIndex,
-        bounds: &hir::GenericBounds,
-    ) -> (HirVec<hir::GenericArg>, HirVec<hir::GenericParam>) {
+        bounds: hir::GenericBounds<'hir>,
+    ) -> (&'hir [hir::GenericArg<'hir>], &'hir [hir::GenericParam<'hir>]) {
         debug!(
             "lifetimes_from_impl_trait_bounds(opaque_ty_id={:?}, \
              parent_index={:?}, \
@@ -1471,8 +1481,8 @@ struct ImplTraitLifetimeCollector<'r, 'a, 'hir> {
             collect_elided_lifetimes: bool,
             currently_bound_lifetimes: Vec<hir::LifetimeName>,
             already_defined_lifetimes: FxHashSet<hir::LifetimeName>,
-            output_lifetimes: Vec<hir::GenericArg>,
-            output_lifetime_params: Vec<hir::GenericParam>,
+            output_lifetimes: Vec<hir::GenericArg<'hir>>,
+            output_lifetime_params: Vec<hir::GenericParam<'hir>>,
         }
 
         impl<'r, 'a, 'v, 'hir> hir::intravisit::Visitor<'v> for ImplTraitLifetimeCollector<'r, 'a, 'hir> {
@@ -1482,7 +1492,7 @@ fn nested_visit_map<'this>(
                 hir::intravisit::NestedVisitorMap::None
             }
 
-            fn visit_generic_args(&mut self, span: Span, parameters: &'v hir::GenericArgs) {
+            fn visit_generic_args(&mut self, span: Span, parameters: &'v hir::GenericArgs<'v>) {
                 // Don't collect elided lifetimes used inside of `Fn()` syntax.
                 if parameters.parenthesized {
                     let old_collect_elided_lifetimes = self.collect_elided_lifetimes;
@@ -1494,7 +1504,7 @@ fn visit_generic_args(&mut self, span: Span, parameters: &'v hir::GenericArgs) {
                 }
             }
 
-            fn visit_ty(&mut self, t: &'v hir::Ty) {
+            fn visit_ty(&mut self, t: &'v hir::Ty<'v>) {
                 // Don't collect elided lifetimes used inside of `fn()` syntax.
                 if let hir::TyKind::BareFn(_) = t.kind {
                     let old_collect_elided_lifetimes = self.collect_elided_lifetimes;
@@ -1514,7 +1524,7 @@ fn visit_ty(&mut self, t: &'v hir::Ty) {
 
             fn visit_poly_trait_ref(
                 &mut self,
-                trait_ref: &'v hir::PolyTraitRef,
+                trait_ref: &'v hir::PolyTraitRef<'v>,
                 modifier: hir::TraitBoundModifier,
             ) {
                 // Record the "stack height" of `for<'a>` lifetime bindings
@@ -1524,7 +1534,7 @@ fn visit_poly_trait_ref(
                 self.currently_bound_lifetimes.truncate(old_len);
             }
 
-            fn visit_generic_param(&mut self, param: &'v hir::GenericParam) {
+            fn visit_generic_param(&mut self, param: &'v hir::GenericParam<'v>) {
                 // Record the introduction of 'a in `for<'a> ...`.
                 if let hir::GenericParamKind::Lifetime { .. } = param.kind {
                     // Introduce lifetimes one at a time so that we can handle
@@ -1594,8 +1604,8 @@ fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
                         name,
                         span: lifetime.span,
                         pure_wrt_drop: false,
-                        attrs: hir_vec![],
-                        bounds: hir_vec![],
+                        attrs: &[],
+                        bounds: &[],
                         kind: hir::GenericParamKind::Lifetime { kind },
                     });
                 }
@@ -1617,9 +1627,12 @@ fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
             hir::intravisit::walk_param_bound(&mut lifetime_collector, &bound);
         }
 
+        let ImplTraitLifetimeCollector { output_lifetimes, output_lifetime_params, .. } =
+            lifetime_collector;
+
         (
-            lifetime_collector.output_lifetimes.into(),
-            lifetime_collector.output_lifetime_params.into(),
+            self.arena.alloc_from_iter(output_lifetimes),
+            self.arena.alloc_from_iter(output_lifetime_params),
         )
     }
 
@@ -1629,8 +1642,8 @@ fn lower_qpath(
         qself: &Option<QSelf>,
         p: &Path,
         param_mode: ParamMode,
-        mut itctx: ImplTraitContext<'_>,
-    ) -> hir::QPath {
+        mut itctx: ImplTraitContext<'_, 'hir>,
+    ) -> hir::QPath<'hir> {
         let qself_position = qself.as_ref().map(|q| q.position);
         let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx.reborrow()));
 
@@ -1638,12 +1651,10 @@ fn lower_qpath(
             self.resolver.get_partial_res(id).unwrap_or_else(|| PartialRes::new(Res::Err));
 
         let proj_start = p.segments.len() - partial_res.unresolved_segments();
-        let path = P(hir::Path {
+        let path = self.arena.alloc(hir::Path {
             res: self.lower_res(partial_res.base_res()),
-            segments: p.segments[..proj_start]
-                .iter()
-                .enumerate()
-                .map(|(i, segment)| {
+            segments: self.arena.alloc_from_iter(p.segments[..proj_start].iter().enumerate().map(
+                |(i, segment)| {
                     let param_mode = match (qself_position, param_mode) {
                         (Some(j), ParamMode::Optional) if i < j => {
                             // This segment is part of the trait path in a
@@ -1719,8 +1730,8 @@ fn lower_qpath(
                         itctx.reborrow(),
                         None,
                     )
-                })
-                .collect(),
+                },
+            )),
             span: p.span,
         });
 
@@ -1740,7 +1751,7 @@ fn lower_qpath(
             // e.g., `Vec` in `Vec::new` or `<I as Iterator>::Item` in
             // `<I as Iterator>::Item::default`.
             let new_id = self.next_id();
-            P(self.ty_path(new_id, p.span, hir::QPath::Resolved(qself, path)))
+            self.arena.alloc(self.ty_path(new_id, p.span, hir::QPath::Resolved(qself, path)))
         };
 
         // Anything after the base path are associated "extensions",
@@ -1754,7 +1765,7 @@ fn lower_qpath(
         //   3. `<<std::vec::Vec<T>>::IntoIter>::Item`
         // * final path is `<<<std::vec::Vec<T>>::IntoIter>::Item>::clone`
         for (i, segment) in p.segments.iter().enumerate().skip(proj_start) {
-            let segment = P(self.lower_path_segment(
+            let segment = self.arena.alloc(self.lower_path_segment(
                 p.span,
                 segment,
                 param_mode,
@@ -1772,7 +1783,7 @@ fn lower_qpath(
 
             // Wrap the associated extension in another type node.
             let new_id = self.next_id();
-            ty = P(self.ty_path(new_id, p.span, qpath));
+            ty = self.arena.alloc(self.ty_path(new_id, p.span, qpath));
         }
 
         // We should've returned in the for loop above.
@@ -1790,29 +1801,25 @@ fn lower_path_extra(
         p: &Path,
         param_mode: ParamMode,
         explicit_owner: Option<NodeId>,
-    ) -> hir::Path {
+    ) -> hir::Path<'hir> {
         hir::Path {
             res,
-            segments: p
-                .segments
-                .iter()
-                .map(|segment| {
-                    self.lower_path_segment(
-                        p.span,
-                        segment,
-                        param_mode,
-                        0,
-                        ParenthesizedGenericArgs::Err,
-                        ImplTraitContext::disallowed(),
-                        explicit_owner,
-                    )
-                })
-                .collect(),
+            segments: self.arena.alloc_from_iter(p.segments.iter().map(|segment| {
+                self.lower_path_segment(
+                    p.span,
+                    segment,
+                    param_mode,
+                    0,
+                    ParenthesizedGenericArgs::Err,
+                    ImplTraitContext::disallowed(),
+                    explicit_owner,
+                )
+            })),
             span: p.span,
         }
     }
 
-    fn lower_path(&mut self, id: NodeId, p: &Path, param_mode: ParamMode) -> hir::Path {
+    fn lower_path(&mut self, id: NodeId, p: &Path, param_mode: ParamMode) -> hir::Path<'hir> {
         let res = self.expect_full_res(id);
         let res = self.lower_res(res);
         self.lower_path_extra(res, p, param_mode, None)
@@ -1825,9 +1832,9 @@ fn lower_path_segment(
         param_mode: ParamMode,
         expected_lifetimes: usize,
         parenthesized_generic_args: ParenthesizedGenericArgs,
-        itctx: ImplTraitContext<'_>,
+        itctx: ImplTraitContext<'_, 'hir>,
         explicit_owner: Option<NodeId>,
-    ) -> hir::PathSegment {
+    ) -> hir::PathSegment<'hir> {
         let (mut generic_args, infer_args) = if let Some(ref generic_args) = segment.args {
             let msg = "parenthesized type parameters may only be used with a `Fn` trait";
             match **generic_args {
@@ -1958,21 +1965,25 @@ fn lower_path_segment(
             segment.ident, segment.id, id,
         );
 
-        hir::PathSegment::new(
-            segment.ident,
-            Some(id),
-            Some(self.lower_res(res)),
-            generic_args,
+        hir::PathSegment {
+            ident: segment.ident,
+            hir_id: Some(id),
+            res: Some(self.lower_res(res)),
             infer_args,
-        )
+            args: if generic_args.is_empty() {
+                None
+            } else {
+                Some(self.arena.alloc(generic_args.into_generic_args(self.arena)))
+            },
+        }
     }
 
     fn lower_angle_bracketed_parameter_data(
         &mut self,
         data: &AngleBracketedArgs,
         param_mode: ParamMode,
-        mut itctx: ImplTraitContext<'_>,
-    ) -> (hir::GenericArgs, bool) {
+        mut itctx: ImplTraitContext<'_, 'hir>,
+    ) -> (GenericArgsCtor<'hir>, bool) {
         let &AngleBracketedArgs { ref args, ref constraints, .. } = data;
         let has_non_lt_args = args.iter().any(|arg| match arg {
             ast::GenericArg::Lifetime(_) => false,
@@ -1980,12 +1991,11 @@ fn lower_angle_bracketed_parameter_data(
             ast::GenericArg::Const(_) => true,
         });
         (
-            hir::GenericArgs {
+            GenericArgsCtor {
                 args: args.iter().map(|a| self.lower_generic_arg(a, itctx.reborrow())).collect(),
-                bindings: constraints
-                    .iter()
-                    .map(|b| self.lower_assoc_ty_constraint(b, itctx.reborrow()))
-                    .collect(),
+                bindings: self.arena.alloc_from_iter(
+                    constraints.iter().map(|b| self.lower_assoc_ty_constraint(b, itctx.reborrow())),
+                ),
                 parenthesized: false,
             },
             !has_non_lt_args && param_mode == ParamMode::Optional,
@@ -1995,7 +2005,7 @@ fn lower_angle_bracketed_parameter_data(
     fn lower_parenthesized_parameter_data(
         &mut self,
         data: &ParenthesizedArgs,
-    ) -> (hir::GenericArgs, bool) {
+    ) -> (GenericArgsCtor<'hir>, bool) {
         // Switch to `PassThrough` mode for anonymous lifetimes; this
         // means that we permit things like `&Ref<T>`, where `Ref` has
         // a hidden lifetime parameter. This is needed for backwards
@@ -2003,26 +2013,28 @@ fn lower_parenthesized_parameter_data(
         // we generally don't permit such things (see #51008).
         self.with_anonymous_lifetime_mode(AnonymousLifetimeMode::PassThrough, |this| {
             let &ParenthesizedArgs { ref inputs, ref output, span } = data;
-            let inputs = inputs
-                .iter()
-                .map(|ty| this.lower_ty_direct(ty, ImplTraitContext::disallowed()))
-                .collect();
+            let inputs = this.arena.alloc_from_iter(
+                inputs.iter().map(|ty| this.lower_ty_direct(ty, ImplTraitContext::disallowed())),
+            );
             let output_ty = match output {
                 FunctionRetTy::Ty(ty) => this.lower_ty(&ty, ImplTraitContext::disallowed()),
-                FunctionRetTy::Default(_) => P(this.ty_tup(span, hir::HirVec::new())),
+                FunctionRetTy::Default(_) => this.arena.alloc(this.ty_tup(span, &[])),
             };
-            let args = hir_vec![GenericArg::Type(this.ty_tup(span, inputs))];
+            let args = vec![GenericArg::Type(this.ty_tup(span, inputs))];
             let binding = hir::TypeBinding {
                 hir_id: this.next_id(),
                 ident: Ident::with_dummy_span(FN_OUTPUT_NAME),
                 span: output_ty.span,
                 kind: hir::TypeBindingKind::Equality { ty: output_ty },
             };
-            (hir::GenericArgs { args, bindings: hir_vec![binding], parenthesized: true }, false)
+            (
+                GenericArgsCtor { args, bindings: arena_vec![this; binding], parenthesized: true },
+                false,
+            )
         })
     }
 
-    fn lower_local(&mut self, l: &Local) -> (hir::Local, SmallVec<[NodeId; 1]>) {
+    fn lower_local(&mut self, l: &Local) -> (hir::Local<'hir>, SmallVec<[NodeId; 1]>) {
         let mut ids = SmallVec::<[NodeId; 1]>::new();
         if self.sess.features_untracked().impl_trait_in_bindings {
             if let Some(ref ty) = l.ty {
@@ -2031,21 +2043,23 @@ fn lower_parenthesized_parameter_data(
             }
         }
         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 init = l.init.as_ref().map(|e| 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,
@@ -2054,7 +2068,7 @@ fn lower_parenthesized_parameter_data(
         )
     }
 
-    fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> hir::HirVec<Ident> {
+    fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Ident] {
         // Skip the `...` (`CVarArgs`) trailing arguments from the AST,
         // as they are not explicit in HIR/Ty function signatures.
         // (instead, the `c_variadic` flag is set to `true`)
@@ -2062,13 +2076,10 @@ fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> hir::HirVec<Ident> {
         if decl.c_variadic() {
             inputs = &inputs[..inputs.len() - 1];
         }
-        inputs
-            .iter()
-            .map(|param| match param.pat.kind {
-                PatKind::Ident(_, ident, _) => ident,
-                _ => Ident::new(kw::Invalid, param.pat.span),
-            })
-            .collect()
+        self.arena.alloc_from_iter(inputs.iter().map(|param| match param.pat.kind {
+            PatKind::Ident(_, ident, _) => ident,
+            _ => Ident::new(kw::Invalid, param.pat.span),
+        }))
     }
 
     // Lowers a function declaration.
@@ -2086,10 +2097,10 @@ fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> hir::HirVec<Ident> {
     fn lower_fn_decl(
         &mut self,
         decl: &FnDecl,
-        mut in_band_ty_params: Option<(DefId, &mut Vec<hir::GenericParam>)>,
+        mut in_band_ty_params: Option<(DefId, &mut Vec<hir::GenericParam<'hir>>)>,
         impl_trait_return_allow: bool,
         make_ret_async: Option<NodeId>,
-    ) -> P<hir::FnDecl> {
+    ) -> &'hir hir::FnDecl<'hir> {
         debug!(
             "lower_fn_decl(\
             fn_decl: {:?}, \
@@ -2119,16 +2130,13 @@ fn lower_fn_decl(
             if c_variadic {
                 inputs = &inputs[..inputs.len() - 1];
             }
-            inputs
-                .iter()
-                .map(|param| {
-                    if let Some((_, ibty)) = &mut in_band_ty_params {
-                        this.lower_ty_direct(&param.ty, ImplTraitContext::Universal(ibty))
-                    } else {
-                        this.lower_ty_direct(&param.ty, ImplTraitContext::disallowed())
-                    }
-                })
-                .collect::<HirVec<_>>()
+            this.arena.alloc_from_iter(inputs.iter().map(|param| {
+                if let Some((_, ibty)) = &mut in_band_ty_params {
+                    this.lower_ty_direct(&param.ty, ImplTraitContext::Universal(ibty))
+                } else {
+                    this.lower_ty_direct(&param.ty, ImplTraitContext::disallowed())
+                }
+            }))
         });
 
         let output = if let Some(ret_id) = make_ret_async {
@@ -2149,7 +2157,7 @@ fn lower_fn_decl(
             }
         };
 
-        P(hir::FnDecl {
+        self.arena.alloc(hir::FnDecl {
             inputs,
             output,
             c_variadic,
@@ -2195,7 +2203,7 @@ fn lower_async_fn_ret_ty(
         output: &FunctionRetTy,
         fn_def_id: DefId,
         opaque_ty_node_id: NodeId,
-    ) -> hir::FunctionRetTy {
+    ) -> hir::FunctionRetTy<'hir> {
         debug!(
             "lower_async_fn_ret_ty(\
              output={:?}, \
@@ -2295,21 +2303,18 @@ fn lower_async_fn_ret_ty(
             debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", this.lifetimes_to_define);
             debug!("lower_async_fn_ret_ty: lifetime_params={:#?}", lifetime_params);
 
-            let generic_params = lifetime_params
-                .iter()
-                .cloned()
-                .map(|(span, hir_name)| {
-                    this.lifetime_to_generic_param(span, hir_name, opaque_ty_def_index)
-                })
-                .collect();
+            let generic_params =
+                this.arena.alloc_from_iter(lifetime_params.iter().map(|(span, hir_name)| {
+                    this.lifetime_to_generic_param(*span, *hir_name, opaque_ty_def_index)
+                }));
 
             let opaque_ty_item = hir::OpaqueTy {
                 generics: hir::Generics {
                     params: generic_params,
-                    where_clause: hir::WhereClause { predicates: hir_vec![], span },
+                    where_clause: hir::WhereClause { predicates: &[], span },
                     span,
                 },
-                bounds: hir_vec![future_bound],
+                bounds: arena_vec![this; future_bound],
                 impl_trait_fn: Some(fn_def_id),
                 origin: hir::OpaqueTyOrigin::AsyncFn,
             };
@@ -2348,22 +2353,22 @@ fn lower_async_fn_ret_ty(
                 })
             })
             .collect();
-        generic_args.extend(lifetime_params[input_lifetimes_count..].iter().map(|&(span, _)| {
+        generic_args.extend(lifetime_params[input_lifetimes_count..].iter().map(|&(span, _)|
             // Output lifetime like `'_`.
             GenericArg::Lifetime(hir::Lifetime {
                 hir_id: self.next_id(),
                 span,
                 name: hir::LifetimeName::Implicit,
-            })
-        }));
+            })));
+        let generic_args = self.arena.alloc_from_iter(generic_args);
 
         // Create the `Foo<...>` reference itself. Note that the `type
         // Foo = impl Trait` is, internally, created as a child of the
         // async fn, so the *type parameters* are inherited.  It's
         // only the lifetime parameters that we must supply.
-        let opaque_ty_ref = hir::TyKind::Def(hir::ItemId { id: opaque_ty_id }, generic_args.into());
+        let opaque_ty_ref = hir::TyKind::Def(hir::ItemId { id: opaque_ty_id }, generic_args);
         let opaque_ty = self.ty(opaque_ty_span, opaque_ty_ref);
-        hir::FunctionRetTy::Return(P(opaque_ty))
+        hir::FunctionRetTy::Return(self.arena.alloc(opaque_ty))
     }
 
     /// Transforms `-> T` into `Future<Output = T>`
@@ -2372,17 +2377,17 @@ fn lower_async_fn_output_type_to_future_bound(
         output: &FunctionRetTy,
         fn_def_id: DefId,
         span: Span,
-    ) -> hir::GenericBound {
+    ) -> hir::GenericBound<'hir> {
         // Compute the `T` in `Future<Output = T>` from the return type.
         let output_ty = match output {
             FunctionRetTy::Ty(ty) => self.lower_ty(ty, ImplTraitContext::OpaqueTy(Some(fn_def_id))),
-            FunctionRetTy::Default(ret_ty_span) => P(self.ty_tup(*ret_ty_span, hir_vec![])),
+            FunctionRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])),
         };
 
         // "<Output = T>"
-        let future_params = P(hir::GenericArgs {
-            args: hir_vec![],
-            bindings: hir_vec![hir::TypeBinding {
+        let future_params = self.arena.alloc(hir::GenericArgs {
+            args: &[],
+            bindings: arena_vec![self; hir::TypeBinding {
                 ident: Ident::with_dummy_span(FN_OUTPUT_NAME),
                 kind: hir::TypeBindingKind::Equality { ty: output_ty },
                 hir_id: self.next_id(),
@@ -2392,13 +2397,17 @@ fn lower_async_fn_output_type_to_future_bound(
         });
 
         // ::std::future::Future<future_params>
-        let future_path =
-            P(self.std_path(span, &[sym::future, sym::Future], Some(future_params), false));
+        let future_path = self.arena.alloc(self.std_path(
+            span,
+            &[sym::future, sym::Future],
+            Some(future_params),
+            false,
+        ));
 
         hir::GenericBound::Trait(
             hir::PolyTraitRef {
                 trait_ref: hir::TraitRef { path: future_path, hir_ref_id: self.next_id() },
-                bound_generic_params: hir_vec![],
+                bound_generic_params: &[],
                 span,
             },
             hir::TraitBoundModifier::None,
@@ -2408,8 +2417,8 @@ fn lower_async_fn_output_type_to_future_bound(
     fn lower_param_bound(
         &mut self,
         tpb: &GenericBound,
-        itctx: ImplTraitContext<'_>,
-    ) -> hir::GenericBound {
+        itctx: ImplTraitContext<'_, 'hir>,
+    ) -> hir::GenericBound<'hir> {
         match *tpb {
             GenericBound::Trait(ref ty, modifier) => hir::GenericBound::Trait(
                 self.lower_poly_trait_ref(ty, itctx),
@@ -2456,27 +2465,36 @@ fn new_named_lifetime(
         hir::Lifetime { hir_id: self.lower_node_id(id), span, name }
     }
 
-    fn lower_generic_params(
+    fn lower_generic_params_mut(
         &mut self,
         params: &[GenericParam],
         add_bounds: &NodeMap<Vec<GenericBound>>,
-        mut itctx: ImplTraitContext<'_>,
-    ) -> hir::HirVec<hir::GenericParam> {
+        mut itctx: ImplTraitContext<'_, 'hir>,
+    ) -> Vec<hir::GenericParam<'hir>> {
         params
             .iter()
             .map(|param| self.lower_generic_param(param, add_bounds, itctx.reborrow()))
             .collect()
     }
 
+    fn lower_generic_params(
+        &mut self,
+        params: &[GenericParam],
+        add_bounds: &NodeMap<Vec<GenericBound>>,
+        itctx: ImplTraitContext<'_, 'hir>,
+    ) -> &'hir [hir::GenericParam<'hir>] {
+        self.arena.alloc_from_iter(self.lower_generic_params_mut(params, add_bounds, itctx))
+    }
+
     fn lower_generic_param(
         &mut self,
         param: &GenericParam,
         add_bounds: &NodeMap<Vec<GenericBound>>,
-        mut itctx: ImplTraitContext<'_>,
-    ) -> hir::GenericParam {
-        let mut bounds = self
+        mut itctx: ImplTraitContext<'_, 'hir>,
+    ) -> hir::GenericParam<'hir> {
+        let mut bounds: Vec<_> = self
             .with_anonymous_lifetime_mode(AnonymousLifetimeMode::ReportError, |this| {
-                this.lower_param_bounds(&param.bounds, itctx.reborrow())
+                this.lower_param_bounds_mut(&param.bounds, itctx.reborrow()).collect()
             });
 
         let (name, kind) = match param.kind {
@@ -2512,8 +2530,8 @@ fn lower_generic_param(
             GenericParamKind::Type { ref default, .. } => {
                 let add_bounds = add_bounds.get(&param.id).map_or(&[][..], |x| &x);
                 if !add_bounds.is_empty() {
-                    let params = self.lower_param_bounds(add_bounds, itctx.reborrow()).into_iter();
-                    bounds = bounds.into_iter().chain(params).collect();
+                    let params = self.lower_param_bounds_mut(add_bounds, itctx.reborrow());
+                    bounds.extend(params);
                 }
 
                 let kind = hir::GenericParamKind::Type {
@@ -2544,12 +2562,16 @@ fn lower_generic_param(
             span: param.ident.span,
             pure_wrt_drop: attr::contains_name(&param.attrs, sym::may_dangle),
             attrs: self.lower_attrs(&param.attrs),
-            bounds,
+            bounds: self.arena.alloc_from_iter(bounds),
             kind,
         }
     }
 
-    fn lower_trait_ref(&mut self, p: &TraitRef, itctx: ImplTraitContext<'_>) -> hir::TraitRef {
+    fn lower_trait_ref(
+        &mut self,
+        p: &TraitRef,
+        itctx: ImplTraitContext<'_, 'hir>,
+    ) -> hir::TraitRef<'hir> {
         let path = match self.lower_qpath(p.ref_id, &None, &p.path, ParamMode::Explicit, itctx) {
             hir::QPath::Resolved(None, path) => path,
             qpath => bug!("lower_trait_ref: unexpected QPath `{:?}`", qpath),
@@ -2560,8 +2582,8 @@ fn lower_trait_ref(&mut self, p: &TraitRef, itctx: ImplTraitContext<'_>) -> hir:
     fn lower_poly_trait_ref(
         &mut self,
         p: &PolyTraitRef,
-        mut itctx: ImplTraitContext<'_>,
-    ) -> hir::PolyTraitRef {
+        mut itctx: ImplTraitContext<'_, 'hir>,
+    ) -> hir::PolyTraitRef<'hir> {
         let bound_generic_params = self.lower_generic_params(
             &p.bound_generic_params,
             &NodeMap::default(),
@@ -2574,26 +2596,38 @@ fn lower_poly_trait_ref(
         hir::PolyTraitRef { bound_generic_params, trait_ref, span: p.span }
     }
 
-    fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext<'_>) -> hir::MutTy {
+    fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext<'_, 'hir>) -> hir::MutTy<'hir> {
         hir::MutTy { ty: self.lower_ty(&mt.ty, itctx), mutbl: mt.mutbl }
     }
 
     fn lower_param_bounds(
         &mut self,
         bounds: &[GenericBound],
-        mut itctx: ImplTraitContext<'_>,
-    ) -> hir::GenericBounds {
-        bounds.iter().map(|bound| self.lower_param_bound(bound, itctx.reborrow())).collect()
+        itctx: ImplTraitContext<'_, 'hir>,
+    ) -> hir::GenericBounds<'hir> {
+        self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, itctx))
     }
 
-    fn lower_block(&mut self, b: &Block, targeted_by_break: bool) -> P<hir::Block> {
+    fn lower_param_bounds_mut<'s>(
+        &'s mut self,
+        bounds: &'s [GenericBound],
+        mut itctx: ImplTraitContext<'s, 'hir>,
+    ) -> impl Iterator<Item = hir::GenericBound<'hir>> + Captures<'s> + Captures<'a> {
+        bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx.reborrow()))
+    }
+
+    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.lower_expr(e));
                 } else {
                     stmts.extend(self.lower_stmt(stmt));
                 }
@@ -2602,24 +2636,24 @@ fn lower_block(&mut self, b: &Block, targeted_by_break: bool) -> P<hir::Block> {
             }
         }
 
-        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
     /// has no attributes and is not targeted by a `break`.
-    fn lower_block_expr(&mut self, b: &Block) -> hir::Expr {
+    fn lower_block_expr(&mut self, b: &Block) -> hir::Expr<'hir> {
         let block = self.lower_block(b, false);
         self.expr_block(block, AttrVec::new())
     }
 
-    fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
+    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 +2661,7 @@ fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
                 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.lower_expr(e)),
             PatKind::TupleStruct(ref path, ref pats) => {
                 let qpath = self.lower_qpath(
                     p.id,
@@ -2640,7 +2674,7 @@ fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
                 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 +2695,13 @@ fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
                     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 +2711,8 @@ fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
             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.lower_expr(e1),
+                self.lower_expr(e2),
                 self.lower_range_end(end),
             ),
             PatKind::Slice(ref pats) => self.lower_pat_slice(pats),
@@ -2700,7 +2731,7 @@ fn lower_pat_tuple(
         &mut self,
         pats: &[AstP<Pat>],
         ctx: &str,
-    ) -> (HirVec<P<hir::Pat>>, Option<usize>) {
+    ) -> (&'hir [&'hir hir::Pat<'hir>], Option<usize>) {
         let mut elems = Vec::with_capacity(pats.len());
         let mut rest = None;
 
@@ -2728,7 +2759,7 @@ fn lower_pat_tuple(
             }
         }
 
-        (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
@@ -2737,7 +2768,7 @@ fn lower_pat_tuple(
     /// When encountering `($binding_mode $ident @)? ..` (`slice`),
     /// this is interpreted as a sub-slice pattern semantically.
     /// Patterns that follow, which are not like `slice` -- or an error occurs, are in `after`.
-    fn lower_pat_slice(&mut self, pats: &[AstP<Pat>]) -> hir::PatKind {
+    fn lower_pat_slice(&mut self, pats: &[AstP<Pat>]) -> hir::PatKind<'hir> {
         let mut before = Vec::new();
         let mut after = Vec::new();
         let mut slice = None;
@@ -2788,7 +2819,11 @@ fn lower_pat_slice(&mut self, pats: &[AstP<Pat>]) -> hir::PatKind {
             }
         }
 
-        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,8 +2831,8 @@ fn lower_pat_ident(
         p: &Pat,
         binding_mode: &BindingMode,
         ident: Ident,
-        lower_sub: impl FnOnce(&mut Self) -> Option<P<hir::Pat>>,
-    ) -> hir::PatKind {
+        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
             res @ None | res @ Some(Res::Local(_)) => {
@@ -2815,22 +2850,22 @@ fn lower_pat_ident(
             }
             Some(res) => hir::PatKind::Path(hir::QPath::Resolved(
                 None,
-                P(hir::Path {
+                self.arena.alloc(hir::Path {
                     span: ident.span,
                     res: self.lower_res(res),
-                    segments: hir_vec![hir::PathSegment::from_ident(ident)],
+                    segments: arena_vec![self; hir::PathSegment::from_ident(ident)],
                 }),
             )),
         }
     }
 
-    fn pat_wild_with_node_id_of(&mut self, p: &Pat) -> P<hir::Pat> {
+    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) -> P<hir::Pat> {
-        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.
@@ -2843,7 +2878,7 @@ fn ban_extra_rest_pat(&self, sp: Span, prev_sp: Span, ctx: &str) {
     }
 
     /// Used to ban the `..` pattern in places it shouldn't be semantically.
-    fn ban_illegal_rest_pat(&self, sp: Span) -> hir::PatKind {
+    fn ban_illegal_rest_pat(&self, sp: Span) -> hir::PatKind<'hir> {
         self.diagnostic()
             .struct_span_err(sp, "`..` patterns are not allowed here")
             .note("only allowed in tuple, tuple struct, and slice patterns")
@@ -2869,11 +2904,11 @@ fn lower_anon_const(&mut self, c: &AnonConst) -> hir::AnonConst {
         })
     }
 
-    fn lower_stmt(&mut self, s: &Stmt) -> SmallVec<[hir::Stmt; 1]> {
+    fn lower_stmt(&mut self, s: &Stmt) -> SmallVec<[hir::Stmt<'hir>; 1]> {
         let kind = match s.kind {
             StmtKind::Local(ref l) => {
                 let (l, item_ids) = self.lower_local(l);
-                let mut ids: SmallVec<[hir::Stmt; 1]> = item_ids
+                let mut ids: SmallVec<[hir::Stmt<'hir>; 1]> = item_ids
                     .into_iter()
                     .map(|item_id| {
                         let item_id = hir::ItemId { id: self.lower_node_id(item_id) };
@@ -2883,7 +2918,7 @@ fn lower_anon_const(&mut self, c: &AnonConst) -> hir::AnonConst {
                 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 +2940,8 @@ fn lower_anon_const(&mut self, c: &AnonConst) -> hir::AnonConst {
                     })
                     .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.lower_expr(e)),
+            StmtKind::Semi(ref e) => hir::StmtKind::Semi(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 }]
@@ -2944,76 +2979,77 @@ fn lower_trait_bound_modifier(&mut self, f: TraitBoundModifier) -> hir::TraitBou
 
     // Helper methods for building HIR.
 
-    fn stmt(&mut self, span: Span, kind: hir::StmtKind) -> hir::Stmt {
+    fn stmt(&mut self, span: Span, kind: hir::StmtKind<'hir>) -> hir::Stmt<'hir> {
         hir::Stmt { span, kind, hir_id: self.next_id() }
     }
 
-    fn stmt_expr(&mut self, span: Span, expr: hir::Expr) -> hir::Stmt {
-        self.stmt(span, hir::StmtKind::Expr(P(expr)))
+    fn stmt_expr(&mut self, span: Span, expr: hir::Expr<'hir>) -> hir::Stmt<'hir> {
+        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>>,
-        pat: P<hir::Pat>,
+        init: Option<&'hir hir::Expr<'hir>>,
+        pat: &'hir hir::Pat<'hir>,
         source: hir::LocalSource,
-    ) -> hir::Stmt {
+    ) -> 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::Block {
-        self.block_all(expr.span, hir::HirVec::new(), Some(expr))
+    fn block_expr(&mut self, expr: &'hir hir::Expr<'hir>) -> &'hir hir::Block<'hir> {
+        self.block_all(expr.span, &[], Some(expr))
     }
 
     fn block_all(
         &mut self,
         span: Span,
-        stmts: hir::HirVec<hir::Stmt>,
-        expr: Option<P<hir::Expr>>,
-    ) -> hir::Block {
-        hir::Block {
+        stmts: &'hir [hir::Stmt<'hir>],
+        expr: Option<&'hir hir::Expr<'hir>>,
+    ) -> &'hir hir::Block<'hir> {
+        let blk = hir::Block {
             stmts,
             expr,
             hir_id: self.next_id(),
             rules: hir::DefaultBlock,
             span,
             targeted_by_break: false,
-        }
+        };
+        self.arena.alloc(blk)
     }
 
     /// Constructs a `true` or `false` literal pattern.
-    fn pat_bool(&mut self, span: Span, val: bool) -> P<hir::Pat> {
+    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(expr))
     }
 
-    fn pat_ok(&mut self, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
-        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>) -> P<hir::Pat> {
-        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>) -> P<hir::Pat> {
-        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> {
-        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>>,
-    ) -> P<hir::Pat> {
+        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 qpath = hir::QPath::Resolved(None, self.arena.alloc(path));
         let pt = if subpats.is_empty() {
             hir::PatKind::Path(qpath)
         } else {
@@ -3022,7 +3058,7 @@ fn pat_std_enum(
         self.pat(span, pt)
     }
 
-    fn pat_ident(&mut self, span: Span, ident: Ident) -> (P<hir::Pat>, 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 +3067,11 @@ fn pat_ident_binding_mode(
         span: Span,
         ident: Ident,
         bm: hir::BindingAnnotation,
-    ) -> (P<hir::Pat>, 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 +3080,12 @@ fn pat_ident_binding_mode(
         )
     }
 
-    fn pat_wild(&mut self, span: Span) -> P<hir::Pat> {
+    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) -> P<hir::Pat> {
-        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
@@ -3059,9 +3095,9 @@ fn std_path(
         &mut self,
         span: Span,
         components: &[Symbol],
-        params: Option<P<hir::GenericArgs>>,
+        params: Option<&'hir hir::GenericArgs<'hir>>,
         is_value: bool,
-    ) -> hir::Path {
+    ) -> hir::Path<'hir> {
         let ns = if is_value { Namespace::ValueNS } else { Namespace::TypeNS };
         let (path, res) = self.resolver.resolve_str_path(span, self.crate_root, components, ns);
 
@@ -3084,18 +3120,23 @@ fn std_path(
         hir::Path {
             span,
             res: res.map_id(|_| panic!("unexpected `NodeId`")),
-            segments: segments.into(),
+            segments: self.arena.alloc_from_iter(segments),
         }
     }
 
-    fn ty_path(&mut self, mut hir_id: hir::HirId, span: Span, qpath: hir::QPath) -> hir::Ty {
+    fn ty_path(
+        &mut self,
+        mut hir_id: hir::HirId,
+        span: Span,
+        qpath: hir::QPath<'hir>,
+    ) -> hir::Ty<'hir> {
         let kind = match qpath {
             hir::QPath::Resolved(None, path) => {
                 // Turn trait object paths into `TyKind::TraitObject` instead.
                 match path.res {
                     Res::Def(DefKind::Trait, _) | Res::Def(DefKind::TraitAlias, _) => {
                         let principal = hir::PolyTraitRef {
-                            bound_generic_params: hir::HirVec::new(),
+                            bound_generic_params: &[],
                             trait_ref: hir::TraitRef { path, hir_ref_id: hir_id },
                             span,
                         };
@@ -3103,7 +3144,10 @@ fn ty_path(&mut self, mut hir_id: hir::HirId, span: Span, qpath: hir::QPath) ->
                         // The original ID is taken by the `PolyTraitRef`,
                         // so the `Ty` itself needs a different one.
                         hir_id = self.next_id();
-                        hir::TyKind::TraitObject(hir_vec![principal], self.elided_dyn_bound(span))
+                        hir::TyKind::TraitObject(
+                            arena_vec![self; principal],
+                            self.elided_dyn_bound(span),
+                        )
                     }
                     _ => hir::TyKind::Path(hir::QPath::Resolved(None, path)),
                 }
@@ -3256,3 +3300,24 @@ fn body_ids(bodies: &BTreeMap<hir::BodyId, hir::Body<'hir>>) -> Vec<hir::BodyId>
     body_ids.sort_by_key(|b| bodies[b].value.span);
     body_ids
 }
+
+/// Helper struct for delayed construction of GenericArgs.
+struct GenericArgsCtor<'hir> {
+    args: Vec<hir::GenericArg<'hir>>,
+    bindings: &'hir [hir::TypeBinding<'hir>],
+    parenthesized: bool,
+}
+
+impl GenericArgsCtor<'hir> {
+    fn is_empty(&self) -> bool {
+        self.args.is_empty() && self.bindings.is_empty() && !self.parenthesized
+    }
+
+    fn into_generic_args(self, arena: &'hir Arena<'hir>) -> hir::GenericArgs<'hir> {
+        hir::GenericArgs {
+            args: arena.alloc_from_iter(self.args),
+            bindings: self.bindings,
+            parenthesized: self.parenthesized,
+        }
+    }
+}