]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/hir/lowering.rs
Retire HirVec.
[rust.git] / src / librustc / hir / lowering.rs
index 83869951ea2a15afe36876aae620f6520955200f..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::{self, ParamName};
-use crate::hir::HirVec;
-use crate::hir::map::{DefKey, DefPathData, Definitions};
+use crate::hir::def::{DefKind, Namespace, PartialRes, PerNS, Res};
 use crate::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX};
-use crate::hir::def::{Namespace, Res, DefKind, PartialRes, PerNS};
-use crate::hir::{GenericArg, ConstArg};
+use crate::hir::map::{DefKey, DefPathData, Definitions};
 use crate::hir::ptr::P;
+use crate::hir::{self, ParamName};
+use crate::hir::{ConstArg, GenericArg};
 use crate::lint;
 use crate::lint::builtin::{self, ELIDED_LIFETIMES_IN_PATHS};
 use crate::middle::cstore::CrateStore;
-use crate::session::Session;
 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_data_structures::fx::FxHashSet;
-use rustc_index::vec::IndexVec;
 use rustc_data_structures::sync::Lrc;
+use rustc_index::vec::IndexVec;
 
+use smallvec::SmallVec;
 use std::collections::BTreeMap;
 use std::mem;
-use smallvec::SmallVec;
-use syntax::attr;
 use syntax::ast;
-use syntax::ptr::P as AstP;
 use syntax::ast::*;
+use syntax::attr;
 use syntax::errors;
 use syntax::print::pprust;
-use syntax::token::{self, Nonterminal, Token};
-use syntax::tokenstream::{TokenStream, TokenTree};
+use syntax::ptr::P as AstP;
 use syntax::sess::ParseSess;
-use syntax::source_map::{respan, ExpnData, ExpnKind, DesugaringKind, Spanned};
+use syntax::source_map::{respan, DesugaringKind, ExpnData, ExpnKind, Spanned};
 use syntax::symbol::{kw, sym, Symbol};
+use syntax::token::{self, Nonterminal, Token};
+use syntax::tokenstream::{TokenStream, TokenTree};
 use syntax::visit::{self, Visitor};
 use syntax_pos::hygiene::ExpnId;
 use syntax_pos::Span;
 
 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,7 +301,9 @@ 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()),
-    }.lower_crate(krate)
+        allow_into_future: Some([sym::into_future][..].into()),
+    }
+    .lower_crate(krate)
 }
 
 #[derive(Copy, Clone, PartialEq)]
@@ -359,26 +371,22 @@ enum AnonymousLifetimeMode {
     PassThrough,
 }
 
-struct ImplTraitTypeIdVisitor<'a> { ids: &'a mut SmallVec<[NodeId; 1]> }
+struct ImplTraitTypeIdVisitor<'a> {
+    ids: &'a mut SmallVec<[NodeId; 1]>,
+}
 
 impl<'a, 'b> Visitor<'a> for ImplTraitTypeIdVisitor<'b> {
     fn visit_ty(&mut self, ty: &'a Ty) {
         match ty.kind {
-            | TyKind::Typeof(_)
-            | TyKind::BareFn(_)
-            => return,
+            TyKind::Typeof(_) | TyKind::BareFn(_) => return,
 
             TyKind::ImplTrait(id, _) => self.ids.push(id),
-            _ => {},
+            _ => {}
         }
         visit::walk_ty(self, ty);
     }
 
-    fn visit_path_segment(
-        &mut self,
-        path_span: Span,
-        path_segment: &'v PathSegment,
-    ) {
+    fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) {
         if let Some(ref p) = path_segment.args {
             if let GenericArgs::Parenthesized(_) = **p {
                 return;
@@ -401,11 +409,7 @@ struct MiscCollector<'tcx, 'lowering, 'hir> {
         }
 
         impl MiscCollector<'_, '_, '_> {
-            fn allocate_use_tree_hir_id_counters(
-                &mut self,
-                tree: &UseTree,
-                owner: DefIndex,
-            ) {
+            fn allocate_use_tree_hir_id_counters(&mut self, tree: &UseTree, owner: DefIndex) {
                 match tree.kind {
                     UseTreeKind::Simple(_, id1, id2) => {
                         for &id in &[id1, id2] {
@@ -488,13 +492,11 @@ fn visit_trait_item(&mut self, item: &'tcx AssocItem) {
                 match item.kind {
                     AssocItemKind::Fn(_, None) => {
                         // Ignore patterns in trait methods without bodies
-                        self.with_hir_id_owner(None, |this| {
-                            visit::walk_trait_item(this, item)
-                        });
+                        self.with_hir_id_owner(None, |this| visit::walk_trait_item(this, item));
                     }
                     _ => self.with_hir_id_owner(Some(item.id), |this| {
                         visit::walk_trait_item(this, item);
-                    })
+                    }),
                 }
             }
 
@@ -507,20 +509,14 @@ fn visit_impl_item(&mut self, item: &'tcx AssocItem) {
 
             fn visit_foreign_item(&mut self, i: &'tcx ForeignItem) {
                 // Ignore patterns in foreign items
-                self.with_hir_id_owner(None, |this| {
-                    visit::walk_foreign_item(this, i)
-                });
+                self.with_hir_id_owner(None, |this| visit::walk_foreign_item(this, i));
             }
 
             fn visit_ty(&mut self, t: &'tcx Ty) {
                 match t.kind {
                     // Mirrors the case in visit::walk_ty
                     TyKind::BareFn(ref f) => {
-                        walk_list!(
-                            self,
-                            visit_generic_param,
-                            &f.generic_params
-                        );
+                        walk_list!(self, visit_generic_param, &f.generic_params);
                         // Mirrors visit::walk_fn_decl
                         for parameter in &f.decl.inputs {
                             // We don't lower the ids of argument patterns
@@ -543,12 +539,10 @@ 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);
+        self.resolver.definitions().init_node_id_to_hir_id_mapping(self.node_id_to_hir_id);
 
         hir::Crate {
             module,
@@ -614,7 +608,8 @@ fn with_hir_id_owner<F, T>(&mut self, owner: NodeId, f: F) -> T
     where
         F: FnOnce(&mut Self) -> T,
     {
-        let counter = self.item_local_id_counters
+        let counter = self
+            .item_local_id_counters
             .insert(owner, HIR_ID_COUNTER_LOCKED)
             .unwrap_or_else(|| panic!("no `item_local_id_counters` entry for {:?}", owner));
         let def_index = self.resolver.definitions().opt_def_index(owner).unwrap();
@@ -625,9 +620,7 @@ fn with_hir_id_owner<F, T>(&mut self, owner: NodeId, f: F) -> T
         debug_assert!(def_index == new_def_index);
         debug_assert!(new_counter >= counter);
 
-        let prev = self.item_local_id_counters
-            .insert(owner, new_counter)
-            .unwrap();
+        let prev = self.item_local_id_counters.insert(owner, new_counter).unwrap();
         debug_assert!(prev == HIR_ID_COUNTER_LOCKED);
         ret
     }
@@ -644,10 +637,7 @@ fn lower_node_id(&mut self, ast_node_id: NodeId) -> hir::HirId {
                 this.current_hir_id_owner.last_mut().unwrap();
             let local_id = *local_id_counter;
             *local_id_counter += 1;
-            hir::HirId {
-                owner: def_index,
-                local_id: hir::ItemLocalId::from_u32(local_id),
-            }
+            hir::HirId { owner: def_index, local_id: hir::ItemLocalId::from_u32(local_id) }
         })
     }
 
@@ -665,17 +655,12 @@ fn lower_node_id_with_owner(&mut self, ast_node_id: NodeId, owner: NodeId) -> hi
             debug_assert!(local_id != HIR_ID_COUNTER_LOCKED);
 
             *local_id_counter += 1;
-            let def_index = this
-                .resolver
-                .definitions()
-                .opt_def_index(owner)
-                .expect("you forgot to call `create_def_with_parent` or are lowering node-IDs \
-                         that do not belong to the current owner");
-
-            hir::HirId {
-                owner: def_index,
-                local_id: hir::ItemLocalId::from_u32(local_id),
-            }
+            let def_index = this.resolver.definitions().opt_def_index(owner).expect(
+                "you forgot to call `create_def_with_parent` or are lowering node-IDs \
+                         that do not belong to the current owner",
+            );
+
+            hir::HirId { owner: def_index, local_id: hir::ItemLocalId::from_u32(local_id) }
         })
     }
 
@@ -736,8 +721,10 @@ fn with_anonymous_lifetime_mode<R>(
         self.anonymous_lifetime_mode = anonymous_lifetime_mode;
         let result = op(self);
         self.anonymous_lifetime_mode = old_anonymous_lifetime_mode;
-        debug!("with_anonymous_lifetime_mode: restoring anonymous_lifetime_mode={:?}",
-               old_anonymous_lifetime_mode);
+        debug!(
+            "with_anonymous_lifetime_mode: restoring anonymous_lifetime_mode={:?}",
+            old_anonymous_lifetime_mode
+        );
         result
     }
 
@@ -754,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());
@@ -774,9 +761,7 @@ fn collect_in_band_defs<T, F>(
 
         let params = lifetimes_to_define
             .into_iter()
-            .map(|(span, hir_name)| self.lifetime_to_generic_param(
-                span, hir_name, parent_id.index,
-            ))
+            .map(|(span, hir_name)| self.lifetime_to_generic_param(span, hir_name, parent_id.index))
             .chain(in_band_ty_params.into_iter())
             .collect();
 
@@ -789,25 +774,16 @@ 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
         // that collisions are ok here and this shouldn't
         // really show up for end-user.
         let (str_name, kind) = match hir_name {
-            ParamName::Plain(ident) => (
-                ident.name,
-                hir::LifetimeParamKind::InBand,
-            ),
-            ParamName::Fresh(_) => (
-                kw::UnderscoreLifetime,
-                hir::LifetimeParamKind::Elided,
-            ),
-            ParamName::Error => (
-                kw::UnderscoreLifetime,
-                hir::LifetimeParamKind::Error,
-            ),
+            ParamName::Plain(ident) => (ident.name, hir::LifetimeParamKind::InBand),
+            ParamName::Fresh(_) => (kw::UnderscoreLifetime, hir::LifetimeParamKind::Elided),
+            ParamName::Error => (kw::UnderscoreLifetime, hir::LifetimeParamKind::Error),
         };
 
         // Add a definition for the in-band lifetime def.
@@ -822,11 +798,11 @@ 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 }
+            kind: hir::GenericParamKind::Lifetime { kind },
         }
     }
 
@@ -849,8 +825,8 @@ fn maybe_collect_in_band_lifetime(&mut self, ident: Ident) {
 
         let hir_name = ParamName::Plain(ident);
 
-        if self.lifetimes_to_define.iter()
-                                   .any(|(_, lt_name)| lt_name.modern() == hir_name.modern()) {
+        if self.lifetimes_to_define.iter().any(|(_, lt_name)| lt_name.modern() == hir_name.modern())
+        {
             return;
         }
 
@@ -873,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 {
@@ -900,13 +876,12 @@ 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| {
+        let (in_band_defs, (mut lowered_generics, res)) =
+            self.with_in_scope_lifetime_defs(&generics.params, |this| {
                 this.collect_in_band_defs(parent_id, anonymous_lifetime_mode, |this| {
                     let mut params = Vec::new();
                     // Note: it is necessary to lower generics *before* calling `f`.
@@ -916,42 +891,35 @@ fn add_in_band_defs<F, T>(
                     // `lifetimes_to_define`. If we swapped the order of these two,
                     // 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),
-                    );
+                    let generics =
+                        this.lower_generics_mut(generics, ImplTraitContext::Universal(&mut params));
                     let res = f(this, &mut params);
                     (params, (generics, res))
                 })
-            },
-        );
+            });
 
-        let mut lowered_params: Vec<_> = lowered_generics
-            .params
-            .into_iter()
-            .chain(in_band_defs)
-            .collect();
+        let mut lowered_params: Vec<_> =
+            lowered_generics.params.into_iter().chain(in_band_defs).collect();
 
         // FIXME(const_generics): the compiler doesn't always cope with
         // unsorted generic parameters at the moment, so we make sure
         // that they're ordered correctly here for now. (When we chain
         // the `in_band_defs`, we might make the order unsorted.)
-        lowered_params.sort_by_key(|param| {
-            match param.kind {
-                hir::GenericParamKind::Lifetime { .. } => ParamKindOrd::Lifetime,
-                hir::GenericParamKind::Type { .. } => ParamKindOrd::Type,
-                hir::GenericParamKind::Const { .. } => ParamKindOrd::Const,
-            }
+        lowered_params.sort_by_key(|param| match param.kind {
+            hir::GenericParamKind::Lifetime { .. } => ParamKindOrd::Lifetime,
+            hir::GenericParamKind::Type { .. } => ParamKindOrd::Type,
+            hir::GenericParamKind::Const { .. } => ParamKindOrd::Const,
         });
 
         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;
@@ -965,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;
@@ -989,14 +957,8 @@ fn def_key(&mut self, id: DefId) -> DefKey {
         }
     }
 
-    fn lower_attrs_arena(&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_attrs(&mut self, attrs: &[Attribute]) -> &'hir [Attribute] {
+        self.arena.alloc_from_iter(attrs.iter().map(|a| self.lower_attr(a)))
     }
 
     fn lower_attr(&mut self, attr: &Attribute) -> Attribute {
@@ -1004,48 +966,38 @@ fn lower_attr(&mut self, attr: &Attribute) -> Attribute {
         // lower attributes (we use the AST version) there is nowhere to keep
         // the `HirId`s. We don't actually need HIR version of attributes anyway.
         let kind = match attr.kind {
-            AttrKind::Normal(ref item) => {
-                AttrKind::Normal(AttrItem {
-                    path: item.path.clone(),
-                    args: self.lower_mac_args(&item.args),
-                })
-            }
-            AttrKind::DocComment(comment) => AttrKind::DocComment(comment)
+            AttrKind::Normal(ref item) => AttrKind::Normal(AttrItem {
+                path: item.path.clone(),
+                args: self.lower_mac_args(&item.args),
+            }),
+            AttrKind::DocComment(comment) => AttrKind::DocComment(comment),
         };
 
-        Attribute {
-            kind,
-            id: attr.id,
-            style: attr.style,
-            span: attr.span,
-        }
+        Attribute { kind, id: attr.id, style: attr.style, span: attr.span }
     }
 
     fn lower_mac_args(&mut self, args: &MacArgs) -> MacArgs {
         match *args {
             MacArgs::Empty => MacArgs::Empty,
-            MacArgs::Delimited(dspan, delim, ref tokens) =>
-                MacArgs::Delimited(dspan, delim, self.lower_token_stream(tokens.clone())),
-            MacArgs::Eq(eq_span, ref tokens) =>
-                MacArgs::Eq(eq_span, self.lower_token_stream(tokens.clone())),
+            MacArgs::Delimited(dspan, delim, ref tokens) => {
+                MacArgs::Delimited(dspan, delim, self.lower_token_stream(tokens.clone()))
+            }
+            MacArgs::Eq(eq_span, ref tokens) => {
+                MacArgs::Eq(eq_span, self.lower_token_stream(tokens.clone()))
+            }
         }
     }
 
     fn lower_token_stream(&mut self, tokens: TokenStream) -> TokenStream {
-        tokens
-            .into_trees()
-            .flat_map(|tree| self.lower_token_tree(tree).into_trees())
-            .collect()
+        tokens.into_trees().flat_map(|tree| self.lower_token_tree(tree).into_trees()).collect()
     }
 
     fn lower_token_tree(&mut self, tree: TokenTree) -> TokenStream {
         match tree {
             TokenTree::Token(token) => self.lower_token(token),
-            TokenTree::Delimited(span, delim, tts) => TokenTree::Delimited(
-                span,
-                delim,
-                self.lower_token_stream(tts),
-            ).into(),
+            TokenTree::Delimited(span, delim, tts) => {
+                TokenTree::Delimited(span, delim, self.lower_token_stream(tts)).into()
+            }
         }
     }
 
@@ -1072,14 +1024,14 @@ 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 {
-            AssocTyConstraintKind::Equality { ref ty } => hir::TypeBindingKind::Equality {
-                ty: self.lower_ty(ty, itctx)
-            },
+            AssocTyConstraintKind::Equality { ref ty } => {
+                hir::TypeBindingKind::Equality { ty: self.lower_ty(ty, itctx) }
+            }
             AssocTyConstraintKind::Bound { ref bounds } => {
                 // Piggy-back on the `impl Trait` context to figure out the correct behavior.
                 let (desugar_to_impl_trait, itctx) = match itctx {
@@ -1107,8 +1059,9 @@ fn lower_assoc_ty_constraint(
                     // then to an opaque type).
                     //
                     // FIXME: this is only needed until `impl Trait` is allowed in type aliases.
-                    ImplTraitContext::Disallowed(_) if self.is_in_dyn_type =>
-                        (true, ImplTraitContext::OpaqueTy(None)),
+                    ImplTraitContext::Disallowed(_) if self.is_in_dyn_type => {
+                        (true, ImplTraitContext::OpaqueTy(None))
+                    }
 
                     // We are in the parameter position, but not within a dyn type:
                     //
@@ -1145,18 +1098,14 @@ fn lower_assoc_ty_constraint(
                             itctx,
                         );
 
-                        hir::TypeBindingKind::Equality {
-                            ty
-                        }
+                        hir::TypeBindingKind::Equality { ty }
                     })
                 } else {
                     // Desugar `AssocTy: Bounds` into a type binding where the
                     // later desugars into a trait predicate.
                     let bounds = self.lower_param_bounds(bounds, itctx);
 
-                    hir::TypeBindingKind::Constraint {
-                        bounds
-                    }
+                    hir::TypeBindingKind::Constraint { bounds }
                 }
             }
         };
@@ -1172,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) => {
@@ -1192,8 +1141,7 @@ fn lower_generic_arg(
 
                             // Construct a AnonConst where the expr is the "ty"'s path.
 
-                            let parent_def_index =
-                                self.current_hir_id_owner.last().unwrap().0;
+                            let parent_def_index = self.current_hir_id_owner.last().unwrap().0;
                             let node_id = self.resolver.next_node_id();
 
                             // Add a definition for the in-band const def.
@@ -1212,32 +1160,25 @@ fn lower_generic_arg(
                                 attrs: AttrVec::new(),
                             };
 
-                            let ct = self.with_new_scopes(|this| {
-                                hir::AnonConst {
-                                    hir_id: this.lower_node_id(node_id),
-                                    body: this.lower_const_body(path_expr.span, Some(&path_expr)),
-                                }
-                            });
-                            return GenericArg::Const(ConstArg {
-                                value: ct,
-                                span: ty.span,
+                            let ct = self.with_new_scopes(|this| hir::AnonConst {
+                                hir_id: this.lower_node_id(node_id),
+                                body: this.lower_const_body(path_expr.span, Some(&path_expr)),
                             });
+                            return GenericArg::Const(ConstArg { value: ct, span: ty.span });
                         }
                     }
                 }
                 GenericArg::Type(self.lower_ty_direct(&ty, itctx))
             }
-            ast::GenericArg::Const(ct) => {
-                GenericArg::Const(ConstArg {
-                    value: self.lower_anon_const(&ct),
-                    span: ct.value.span,
-                })
-            }
+            ast::GenericArg::Const(ct) => GenericArg::Const(ConstArg {
+                value: self.lower_anon_const(&ct),
+                span: ct.value.span,
+            }),
         }
     }
 
-    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(
@@ -1246,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);
@@ -1257,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,
@@ -1279,32 +1220,26 @@ fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_>) -> hir::T
                 };
                 hir::TyKind::Rptr(lifetime, self.lower_mt(mt, itctx))
             }
-            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 {
-                                generic_params: this.lower_generic_params(
-                                    &f.generic_params,
-                                    &NodeMap::default(),
-                                    ImplTraitContext::disallowed(),
-                                ),
-                                unsafety: f.unsafety,
-                                abi: this.lower_extern(f.ext),
-                                decl: this.lower_fn_decl(&f.decl, None, false, None),
-                                param_names: this.lower_fn_params_to_names(&f.decl),
-                            }))
-                        },
-                    )
-                },
-            ),
+            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(this.arena.alloc(hir::BareFnTy {
+                        generic_params: this.lower_generic_params(
+                            &f.generic_params,
+                            &NodeMap::default(),
+                            ImplTraitContext::disallowed(),
+                        ),
+                        unsafety: f.unsafety,
+                        abi: this.lower_extern(f.ext),
+                        decl: this.lower_fn_decl(&f.decl, None, false, None),
+                        param_names: this.lower_fn_params_to_names(&f.decl),
+                    }))
+                })
+            }),
             TyKind::Never => hir::TyKind::Never,
             TyKind::Tup(ref tys) => {
-                hir::TyKind::Tup(tys.iter().map(|ty| {
-                    self.lower_ty_direct(ty, itctx.reborrow())
-                }).collect())
+                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);
@@ -1317,39 +1252,37 @@ 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(
+                        segments: arena_vec![self; hir::PathSegment::from_ident(
                             Ident::with_dummy_span(kw::SelfUpper)
                         )],
                         span: t.span,
                     }),
                 ))
-            },
+            }
             TyKind::Array(ref ty, ref length) => {
                 hir::TyKind::Array(self.lower_ty(ty, itctx), self.lower_anon_const(length))
             }
-            TyKind::Typeof(ref expr) => {
-                hir::TyKind::Typeof(self.lower_anon_const(expr))
-            }
+            TyKind::Typeof(ref expr) => hir::TyKind::Typeof(self.lower_anon_const(expr)),
             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)
@@ -1363,18 +1296,14 @@ fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_>) -> hir::T
                 let span = t.span;
                 match itctx {
                     ImplTraitContext::OpaqueTy(fn_def_id) => {
-                        self.lower_opaque_impl_trait(
-                            span, fn_def_id, def_node_id,
-                            |this| this.lower_param_bounds(bounds, itctx),
-                        )
+                        self.lower_opaque_impl_trait(span, fn_def_id, def_node_id, |this| {
+                            this.lower_param_bounds(bounds, itctx)
+                        })
                     }
                     ImplTraitContext::Universal(in_band_ty_params) => {
                         // Add a definition for the in-band `Param`.
-                        let def_index = self
-                            .resolver
-                            .definitions()
-                            .opt_def_index(def_node_id)
-                            .unwrap();
+                        let def_index =
+                            self.resolver.definitions().opt_def_index(def_node_id).unwrap();
 
                         let hir_bounds = self.lower_param_bounds(
                             bounds,
@@ -1386,27 +1315,26 @@ 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 {
                                 default: None,
                                 synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
-                            }
+                            },
                         });
 
                         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)],
                             }),
                         ))
                     }
                     ImplTraitContext::Disallowed(pos) => {
-                        let allowed_in = if self.sess.features_untracked()
-                                                .impl_trait_in_bindings {
+                        let allowed_in = if self.sess.features_untracked().impl_trait_in_bindings {
                             "bindings or function and inherent method return types"
                         } else {
                             "function and inherent method return types"
@@ -1418,11 +1346,13 @@ fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_>) -> hir::T
                             "`impl Trait` not allowed outside of {}",
                             allowed_in,
                         );
-                        if pos == ImplTraitPosition::Binding &&
-                            nightly_options::is_nightly_build() {
-                            help!(err,
-                                  "add `#![feature(impl_trait_in_bindings)]` to the crate \
-                                   attributes to enable");
+                        if pos == ImplTraitPosition::Binding && nightly_options::is_nightly_build()
+                        {
+                            help!(
+                                err,
+                                "add `#![feature(impl_trait_in_bindings)]` to the crate \
+                                   attributes to enable"
+                            );
                         }
                         err.emit();
                         hir::TyKind::Err
@@ -1439,11 +1369,7 @@ fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_>) -> hir::T
             }
         };
 
-        hir::Ty {
-            kind,
-            span: t.span,
-            hir_id: self.lower_node_id(t.id),
-        }
+        hir::Ty { kind, span: t.span, hir_id: self.lower_node_id(t.id) }
     }
 
     fn lower_opaque_impl_trait(
@@ -1451,13 +1377,11 @@ 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,
+            fn_def_id, opaque_ty_node_id, span,
         );
 
         // Make sure we know that some funky desugaring has been going on here.
@@ -1465,17 +1389,10 @@ fn lower_opaque_impl_trait(
         // desugaring that explicitly states that we don't want to track that.
         // Not tracking it makes lints in rustc and clippy very fragile, as
         // frequently opened issues show.
-        let opaque_ty_span = self.mark_span_with_reason(
-            DesugaringKind::OpaqueTy,
-            span,
-            None,
-        );
+        let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None);
 
-        let opaque_ty_def_index = self
-            .resolver
-            .definitions()
-            .opt_def_index(opaque_ty_node_id)
-            .unwrap();
+        let opaque_ty_def_index =
+            self.resolver.definitions().opt_def_index(opaque_ty_node_id).unwrap();
 
         self.allocate_hir_id_counter(opaque_ty_node_id);
 
@@ -1487,22 +1404,15 @@ fn lower_opaque_impl_trait(
             &hir_bounds,
         );
 
-        debug!(
-            "lower_opaque_impl_trait: lifetimes={:#?}", lifetimes,
-        );
+        debug!("lower_opaque_impl_trait: lifetimes={:#?}", lifetimes,);
 
-        debug!(
-            "lower_opaque_impl_trait: lifetime_defs={:#?}", lifetime_defs,
-        );
+        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,
@@ -1511,12 +1421,8 @@ fn lower_opaque_impl_trait(
             };
 
             trace!("lower_opaque_impl_trait: {:#?}", opaque_ty_def_index);
-            let opaque_ty_id = lctx.generate_opaque_type(
-                opaque_ty_node_id,
-                opaque_ty_item,
-                span,
-                opaque_ty_span,
-            );
+            let opaque_ty_id =
+                lctx.generate_opaque_type(opaque_ty_node_id, opaque_ty_item, span, opaque_ty_span);
 
             // `impl Trait` now just becomes `Foo<'a, 'b, ..>`.
             hir::TyKind::Def(hir::ItemId { id: opaque_ty_id }, lifetimes)
@@ -1528,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 {
@@ -1556,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={:?}, \
@@ -1575,20 +1481,18 @@ 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>
-        {
+        impl<'r, 'a, 'v, 'hir> hir::intravisit::Visitor<'v> for ImplTraitLifetimeCollector<'r, 'a, 'hir> {
             fn nested_visit_map<'this>(
                 &'this mut self,
             ) -> hir::intravisit::NestedVisitorMap<'this, 'v> {
                 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;
@@ -1600,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;
@@ -1620,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
@@ -1630,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
@@ -1663,7 +1567,8 @@ fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
                 };
 
                 if !self.currently_bound_lifetimes.contains(&name)
-                    && !self.already_defined_lifetimes.contains(&name) {
+                    && !self.already_defined_lifetimes.contains(&name)
+                {
                     self.already_defined_lifetimes.insert(name);
 
                     self.output_lifetimes.push(hir::GenericArg::Lifetime(hir::Lifetime {
@@ -1680,17 +1585,17 @@ fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
                         def_node_id,
                         DefPathData::LifetimeNs(name.ident().name),
                         ExpnId::root(),
-                        lifetime.span);
+                        lifetime.span,
+                    );
 
                     let (name, kind) = match name {
                         hir::LifetimeName::Underscore => (
                             hir::ParamName::Plain(Ident::with_dummy_span(kw::UnderscoreLifetime)),
                             hir::LifetimeParamKind::Elided,
                         ),
-                        hir::LifetimeName::Param(param_name) => (
-                            param_name,
-                            hir::LifetimeParamKind::Explicit,
-                        ),
+                        hir::LifetimeName::Param(param_name) => {
+                            (param_name, hir::LifetimeParamKind::Explicit)
+                        }
                         _ => bug!("expected `LifetimeName::Param` or `ParamName::Plain`"),
                     };
 
@@ -1699,9 +1604,9 @@ fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
                         name,
                         span: lifetime.span,
                         pure_wrt_drop: false,
-                        attrs: hir_vec![],
-                        bounds: hir_vec![],
-                        kind: hir::GenericParamKind::Lifetime { kind }
+                        attrs: &[],
+                        bounds: &[],
+                        kind: hir::GenericParamKind::Lifetime { kind },
                     });
                 }
             }
@@ -1722,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),
         )
     }
 
@@ -1734,22 +1642,19 @@ 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()));
 
-        let partial_res = self.resolver
-            .get_partial_res(id)
-            .unwrap_or_else(|| PartialRes::new(Res::Err));
+        let partial_res =
+            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
@@ -1777,7 +1682,8 @@ fn lower_qpath(
                         | Res::Def(DefKind::Union, def_id)
                         | Res::Def(DefKind::Enum, def_id)
                         | Res::Def(DefKind::TyAlias, def_id)
-                        | Res::Def(DefKind::Trait, def_id) if i + 1 == proj_start =>
+                        | Res::Def(DefKind::Trait, def_id)
+                            if i + 1 == proj_start =>
                         {
                             Some(def_id)
                         }
@@ -1789,9 +1695,11 @@ fn lower_qpath(
                             ParenthesizedGenericArgs::Ok
                         }
                         // `a::b::Trait(Args)::TraitItem`
-                        Res::Def(DefKind::Method, _) |
-                        Res::Def(DefKind::AssocConst, _) |
-                        Res::Def(DefKind::AssocTy, _) if i + 2 == proj_start => {
+                        Res::Def(DefKind::Method, _)
+                        | Res::Def(DefKind::AssocConst, _)
+                        | Res::Def(DefKind::AssocTy, _)
+                            if i + 2 == proj_start =>
+                        {
                             ParenthesizedGenericArgs::Ok
                         }
                         // Avoid duplicated errors.
@@ -1805,7 +1713,9 @@ fn lower_qpath(
                             return n;
                         }
                         assert!(!def_id.is_local());
-                        let item_generics = self.resolver.cstore()
+                        let item_generics = self
+                            .resolver
+                            .cstore()
                             .item_generics_cloned_untracked(def_id, self.sess);
                         let n = item_generics.own_counts().lifetimes;
                         self.type_def_lifetime_params.insert(def_id, n);
@@ -1820,8 +1730,8 @@ fn lower_qpath(
                         itctx.reborrow(),
                         None,
                     )
-                })
-                .collect(),
+                },
+            )),
             span: p.span,
         });
 
@@ -1841,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",
@@ -1855,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,
@@ -1873,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.
@@ -1891,28 +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)
@@ -1925,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 {
@@ -1944,7 +1851,7 @@ fn lower_path_segment(
                             if data.inputs.len() > 0 {
                                 if let Some(split) = snippet.find('(') {
                                     let trait_name = &snippet[0..split];
-                                    let args = &snippet[split + 1 .. snippet.len() - 1];
+                                    let args = &snippet[split + 1..snippet.len() - 1];
                                     err.span_suggestion(
                                         data.span,
                                         "use angle brackets instead",
@@ -1959,8 +1866,9 @@ fn lower_path_segment(
                             self.lower_angle_bracketed_parameter_data(
                                 &data.as_angle_bracketed_args(),
                                 param_mode,
-                                itctx
-                            ).0,
+                                itctx,
+                            )
+                            .0,
                             false,
                         )
                     }
@@ -1974,14 +1882,18 @@ fn lower_path_segment(
             GenericArg::Lifetime(_) => true,
             _ => false,
         });
-        let first_generic_span = generic_args.args.iter().map(|a| a.span())
-            .chain(generic_args.bindings.iter().map(|b| b.span)).next();
+        let first_generic_span = generic_args
+            .args
+            .iter()
+            .map(|a| a.span())
+            .chain(generic_args.bindings.iter().map(|b| b.span))
+            .next();
         if !generic_args.parenthesized && !has_lifetimes {
-            generic_args.args =
-                self.elided_path_lifetimes(path_span, expected_lifetimes)
-                    .into_iter()
-                    .map(|lt| GenericArg::Lifetime(lt))
-                    .chain(generic_args.args.into_iter())
+            generic_args.args = self
+                .elided_path_lifetimes(path_span, expected_lifetimes)
+                .into_iter()
+                .map(|lt| GenericArg::Lifetime(lt))
+                .chain(generic_args.args.into_iter())
                 .collect();
             if expected_lifetimes > 0 && param_mode == ParamMode::Explicit {
                 let anon_lt_suggestion = vec!["'_"; expected_lifetimes].join(", ");
@@ -2023,8 +1935,7 @@ fn lower_path_segment(
                         );
                         err.emit();
                     }
-                    AnonymousLifetimeMode::PassThrough |
-                    AnonymousLifetimeMode::ReportError => {
+                    AnonymousLifetimeMode::PassThrough | AnonymousLifetimeMode::ReportError => {
                         self.resolver.lint_buffer().buffer_lint_with_diagnostic(
                             ELIDED_LIFETIMES_IN_PATHS,
                             CRATE_NODE_ID,
@@ -2036,7 +1947,7 @@ fn lower_path_segment(
                                 incl_angl_brckt,
                                 insertion_sp,
                                 suggestion,
-                            )
+                            ),
                         );
                     }
                 }
@@ -2054,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,
@@ -2076,54 +1991,50 @@ 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
+            !has_non_lt_args && param_mode == ParamMode::Optional,
         )
     }
 
     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
         // compatibility, even in contexts like an impl header where
         // 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 output_ty = match output {
-                    FunctionRetTy::Ty(ty) => this.lower_ty(&ty, ImplTraitContext::disallowed()),
-                    FunctionRetTy::Default(_) => P(this.ty_tup(span, hir::HirVec::new())),
-                };
-                let args = hir_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,
-                )
-            }
-        )
+        self.with_anonymous_lifetime_mode(AnonymousLifetimeMode::PassThrough, |this| {
+            let &ParenthesizedArgs { ref inputs, ref output, span } = data;
+            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(_) => this.arena.alloc(this.ty_tup(span, &[])),
+            };
+            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 },
+            };
+            (
+                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 {
@@ -2132,26 +2043,32 @@ fn lower_parenthesized_parameter_data(
             }
         }
         let parent_def_id = DefId::local(self.current_hir_id_owner.last().unwrap().0);
-        (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)
-                    }
-                )),
-            pat: self.lower_pat(&l.pat),
-            init: l.init.as_ref().map(|e| P(self.lower_expr(e))),
-            span: l.span,
-            attrs: l.attrs.clone(),
-            source: hir::LocalSource::Normal,
-        }, ids)
+        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,
+                pat: self.lower_pat(&l.pat),
+                init,
+                span: l.span,
+                attrs: l.attrs.clone(),
+                source: hir::LocalSource::Normal,
+            },
+            ids,
+        )
     }
 
-    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`)
@@ -2159,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.
@@ -2183,19 +2097,17 @@ 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> {
-        debug!("lower_fn_decl(\
+    ) -> &'hir hir::FnDecl<'hir> {
+        debug!(
+            "lower_fn_decl(\
             fn_decl: {:?}, \
             in_band_ty_params: {:?}, \
             impl_trait_return_allow: {}, \
             make_ret_async: {:?})",
-            decl,
-            in_band_ty_params,
-            impl_trait_return_allow,
-            make_ret_async,
+            decl, in_band_ty_params, impl_trait_return_allow, make_ret_async,
         );
         let lt_mode = if make_ret_async.is_some() {
             // In `async fn`, argument-position elided lifetimes
@@ -2218,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 {
@@ -2242,43 +2151,40 @@ fn lower_fn_decl(
                     Some((def_id, _)) if impl_trait_return_allow => {
                         hir::Return(self.lower_ty(ty, ImplTraitContext::OpaqueTy(Some(def_id))))
                     }
-                    _ => {
-                        hir::Return(self.lower_ty(ty, ImplTraitContext::disallowed()))
-                    }
+                    _ => hir::Return(self.lower_ty(ty, ImplTraitContext::disallowed())),
                 },
                 FunctionRetTy::Default(span) => hir::DefaultReturn(span),
             }
         };
 
-        P(hir::FnDecl {
+        self.arena.alloc(hir::FnDecl {
             inputs,
             output,
             c_variadic,
-            implicit_self: decl.inputs.get(0).map_or(
-                hir::ImplicitSelfKind::None,
-                |arg| {
-                    let is_mutable_pat = match arg.pat.kind {
-                        PatKind::Ident(BindingMode::ByValue(mt), _, _) |
-                        PatKind::Ident(BindingMode::ByRef(mt), _, _) =>
-                            mt == Mutability::Mut,
-                        _ => false,
-                    };
+            implicit_self: decl.inputs.get(0).map_or(hir::ImplicitSelfKind::None, |arg| {
+                let is_mutable_pat = match arg.pat.kind {
+                    PatKind::Ident(BindingMode::ByValue(mt), _, _)
+                    | PatKind::Ident(BindingMode::ByRef(mt), _, _) => mt == Mutability::Mut,
+                    _ => false,
+                };
 
-                    match arg.ty.kind {
-                        TyKind::ImplicitSelf if is_mutable_pat => hir::ImplicitSelfKind::Mut,
-                        TyKind::ImplicitSelf => hir::ImplicitSelfKind::Imm,
-                        // Given we are only considering `ImplicitSelf` types, we needn't consider
-                        // the case where we have a mutable pattern to a reference as that would
-                        // no longer be an `ImplicitSelf`.
-                        TyKind::Rptr(_, ref mt) if mt.ty.kind.is_implicit_self() &&
-                            mt.mutbl == ast::Mutability::Mut =>
-                                hir::ImplicitSelfKind::MutRef,
-                        TyKind::Rptr(_, ref mt) if mt.ty.kind.is_implicit_self() =>
-                            hir::ImplicitSelfKind::ImmRef,
-                        _ => hir::ImplicitSelfKind::None,
+                match arg.ty.kind {
+                    TyKind::ImplicitSelf if is_mutable_pat => hir::ImplicitSelfKind::Mut,
+                    TyKind::ImplicitSelf => hir::ImplicitSelfKind::Imm,
+                    // Given we are only considering `ImplicitSelf` types, we needn't consider
+                    // the case where we have a mutable pattern to a reference as that would
+                    // no longer be an `ImplicitSelf`.
+                    TyKind::Rptr(_, ref mt)
+                        if mt.ty.kind.is_implicit_self() && mt.mutbl == ast::Mutability::Mut =>
+                    {
+                        hir::ImplicitSelfKind::MutRef
                     }
-                },
-            ),
+                    TyKind::Rptr(_, ref mt) if mt.ty.kind.is_implicit_self() => {
+                        hir::ImplicitSelfKind::ImmRef
+                    }
+                    _ => hir::ImplicitSelfKind::None,
+                }
+            }),
         })
     }
 
@@ -2297,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={:?}, \
@@ -2308,17 +2214,10 @@ fn lower_async_fn_ret_ty(
 
         let span = output.span();
 
-        let opaque_ty_span = self.mark_span_with_reason(
-            DesugaringKind::Async,
-            span,
-            None,
-        );
+        let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::Async, span, None);
 
-        let opaque_ty_def_index = self
-            .resolver
-            .definitions()
-            .opt_def_index(opaque_ty_node_id)
-            .unwrap();
+        let opaque_ty_def_index =
+            self.resolver.definitions().opt_def_index(opaque_ty_node_id).unwrap();
 
         self.allocate_hir_id_counter(opaque_ty_node_id);
 
@@ -2379,14 +2278,10 @@ fn lower_async_fn_ret_ty(
             //
             // Then, we will create `fn foo(..) -> Foo<'_, '_>`, and
             // hence the elision takes place at the fn site.
-            let future_bound = this.with_anonymous_lifetime_mode(
-                AnonymousLifetimeMode::CreateParameter,
-                |this| this.lower_async_fn_output_type_to_future_bound(
-                    output,
-                    fn_def_id,
-                    span,
-                ),
-            );
+            let future_bound = this
+                .with_anonymous_lifetime_mode(AnonymousLifetimeMode::CreateParameter, |this| {
+                    this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span)
+                });
 
             debug!("lower_async_fn_ret_ty: future_bound={:#?}", future_bound);
 
@@ -2396,46 +2291,37 @@ fn lower_async_fn_ret_ty(
             //
             // Note: this must be done after lowering the output type,
             // as the output type may introduce new in-band lifetimes.
-            let lifetime_params: Vec<(Span, ParamName)> =
-                this.in_scope_lifetimes
-                    .iter().cloned()
-                    .map(|name| (name.ident().span, name))
-                    .chain(this.lifetimes_to_define.iter().cloned())
-                    .collect();
+            let lifetime_params: Vec<(Span, ParamName)> = this
+                .in_scope_lifetimes
+                .iter()
+                .cloned()
+                .map(|name| (name.ident().span, name))
+                .chain(this.lifetimes_to_define.iter().cloned())
+                .collect();
 
             debug!("lower_async_fn_ret_ty: in_scope_lifetimes={:#?}", this.in_scope_lifetimes);
             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();
+                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,
             };
 
             trace!("exist ty from async fn def index: {:#?}", opaque_ty_def_index);
-            let opaque_ty_id = this.generate_opaque_type(
-                opaque_ty_node_id,
-                opaque_ty_item,
-                span,
-                opaque_ty_span,
-            );
+            let opaque_ty_id =
+                this.generate_opaque_type(opaque_ty_node_id, opaque_ty_item, span, opaque_ty_span);
 
             (opaque_ty_id, lifetime_params)
         });
@@ -2456,8 +2342,7 @@ fn lower_async_fn_ret_ty(
         //
         // For the "output" lifetime parameters, we just want to
         // generate `'_`.
-        let mut generic_args: Vec<_> =
-            lifetime_params[..input_lifetimes_count]
+        let mut generic_args: Vec<_> = lifetime_params[..input_lifetimes_count]
             .iter()
             .map(|&(span, hir_name)| {
                 // Input lifetime like `'a` or `'1`:
@@ -2468,26 +2353,22 @@ fn lower_async_fn_ret_ty(
                 })
             })
             .collect();
-        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,
-                })
-            })
-        );
+        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>`
@@ -2496,21 +2377,19 @@ 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,
-                },
+                kind: hir::TypeBindingKind::Equality { ty: output_ty },
                 hir_id: self.next_id(),
                 span,
             }],
@@ -2518,16 +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![],
+                trait_ref: hir::TraitRef { path: future_path, hir_ref_id: self.next_id() },
+                bound_generic_params: &[],
                 span,
             },
             hir::TraitBoundModifier::None,
@@ -2537,15 +2417,13 @@ 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),
-                    self.lower_trait_bound_modifier(modifier),
-                )
-            }
+            GenericBound::Trait(ref ty, modifier) => hir::GenericBound::Trait(
+                self.lower_poly_trait_ref(ty, itctx),
+                self.lower_trait_bound_modifier(modifier),
+            ),
             GenericBound::Outlives(ref lifetime) => {
                 hir::GenericBound::Outlives(self.lower_lifetime(lifetime))
             }
@@ -2555,21 +2433,21 @@ fn lower_param_bound(
     fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime {
         let span = l.ident.span;
         match l.ident {
-            ident if ident.name == kw::StaticLifetime =>
-                self.new_named_lifetime(l.id, span, hir::LifetimeName::Static),
-            ident if ident.name == kw::UnderscoreLifetime =>
-                match self.anonymous_lifetime_mode {
-                    AnonymousLifetimeMode::CreateParameter => {
-                        let fresh_name = self.collect_fresh_in_band_lifetime(span);
-                        self.new_named_lifetime(l.id, span, hir::LifetimeName::Param(fresh_name))
-                    }
+            ident if ident.name == kw::StaticLifetime => {
+                self.new_named_lifetime(l.id, span, hir::LifetimeName::Static)
+            }
+            ident if ident.name == kw::UnderscoreLifetime => match self.anonymous_lifetime_mode {
+                AnonymousLifetimeMode::CreateParameter => {
+                    let fresh_name = self.collect_fresh_in_band_lifetime(span);
+                    self.new_named_lifetime(l.id, span, hir::LifetimeName::Param(fresh_name))
+                }
 
-                    AnonymousLifetimeMode::PassThrough => {
-                        self.new_named_lifetime(l.id, span, hir::LifetimeName::Underscore)
-                    }
+                AnonymousLifetimeMode::PassThrough => {
+                    self.new_named_lifetime(l.id, span, hir::LifetimeName::Underscore)
+                }
 
-                    AnonymousLifetimeMode::ReportError => self.new_error_lifetime(Some(l.id), span),
-                },
+                AnonymousLifetimeMode::ReportError => self.new_error_lifetime(Some(l.id), span),
+            },
             ident => {
                 self.maybe_collect_in_band_lifetime(ident);
                 let param_name = ParamName::Plain(ident);
@@ -2584,48 +2462,55 @@ fn new_named_lifetime(
         span: Span,
         name: hir::LifetimeName,
     ) -> hir::Lifetime {
-        hir::Lifetime {
-            hir_id: self.lower_node_id(id),
-            span,
-            name,
-        }
+        hir::Lifetime { hir_id: self.lower_node_id(id), span, name }
+    }
+
+    fn lower_generic_params_mut(
+        &mut self,
+        params: &[GenericParam],
+        add_bounds: &NodeMap<Vec<GenericBound>>,
+        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>>,
-        mut itctx: ImplTraitContext<'_>,
-    ) -> hir::HirVec<hir::GenericParam> {
-        params.iter().map(|param| {
-            self.lower_generic_param(param, add_bounds, itctx.reborrow())
-        }).collect()
-    }
-
-    fn lower_generic_param(&mut self,
-                           param: &GenericParam,
-                           add_bounds: &NodeMap<Vec<GenericBound>>,
-                           mut itctx: ImplTraitContext<'_>)
-                           -> hir::GenericParam {
-        let mut bounds = self.with_anonymous_lifetime_mode(
-            AnonymousLifetimeMode::ReportError,
-            |this| this.lower_param_bounds(&param.bounds, itctx.reborrow()),
-        );
+        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>,
+    ) -> hir::GenericParam<'hir> {
+        let mut bounds: Vec<_> = self
+            .with_anonymous_lifetime_mode(AnonymousLifetimeMode::ReportError, |this| {
+                this.lower_param_bounds_mut(&param.bounds, itctx.reborrow()).collect()
+            });
 
         let (name, kind) = match param.kind {
             GenericParamKind::Lifetime => {
                 let was_collecting_in_band = self.is_collecting_in_band_lifetimes;
                 self.is_collecting_in_band_lifetimes = false;
 
-                let lt = self.with_anonymous_lifetime_mode(
-                    AnonymousLifetimeMode::ReportError,
-                    |this| this.lower_lifetime(&Lifetime { id: param.id, ident: param.ident }),
-                );
+                let lt = self
+                    .with_anonymous_lifetime_mode(AnonymousLifetimeMode::ReportError, |this| {
+                        this.lower_lifetime(&Lifetime { id: param.id, ident: param.ident })
+                    });
                 let param_name = match lt.name {
                     hir::LifetimeName::Param(param_name) => param_name,
                     hir::LifetimeName::Implicit
-                        | hir::LifetimeName::Underscore
-                        | hir::LifetimeName::Static => hir::ParamName::Plain(lt.name.ident()),
+                    | hir::LifetimeName::Underscore
+                    | hir::LifetimeName::Static => hir::ParamName::Plain(lt.name.ident()),
                     hir::LifetimeName::ImplicitObjectLifetimeDefault => {
                         span_bug!(
                             param.ident.span,
@@ -2635,9 +2520,8 @@ fn lower_generic_param(&mut self,
                     hir::LifetimeName::Error => ParamName::Error,
                 };
 
-                let kind = hir::GenericParamKind::Lifetime {
-                    kind: hir::LifetimeParamKind::Explicit
-                };
+                let kind =
+                    hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit };
 
                 self.is_collecting_in_band_lifetimes = was_collecting_in_band;
 
@@ -2646,29 +2530,30 @@ fn lower_generic_param(&mut self,
             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 {
-                    default: default.as_ref().map(|x| {
-                        self.lower_ty(x, ImplTraitContext::OpaqueTy(None))
-                    }),
-                    synthetic: param.attrs.iter()
-                                          .filter(|attr| attr.check_name(sym::rustc_synthetic))
-                                          .map(|_| hir::SyntheticTyParamKind::ImplTrait)
-                                          .next(),
+                    default: default
+                        .as_ref()
+                        .map(|x| self.lower_ty(x, ImplTraitContext::OpaqueTy(None))),
+                    synthetic: param
+                        .attrs
+                        .iter()
+                        .filter(|attr| attr.check_name(sym::rustc_synthetic))
+                        .map(|_| hir::SyntheticTyParamKind::ImplTrait)
+                        .next(),
                 };
 
                 (hir::ParamName::Plain(param.ident), kind)
             }
-            GenericParamKind::Const { ref ty } => {
-                (hir::ParamName::Plain(param.ident), hir::GenericParamKind::Const {
+            GenericParamKind::Const { ref ty } => (
+                hir::ParamName::Plain(param.ident),
+                hir::GenericParamKind::Const {
                     ty: self.lower_ty(&ty, ImplTraitContext::disallowed()),
-                })
-            }
+                },
+            ),
         };
 
         hir::GenericParam {
@@ -2677,64 +2562,72 @@ fn lower_generic_param(&mut self,
             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),
         };
-        hir::TraitRef {
-            path,
-            hir_ref_id: self.lower_node_id(p.ref_id),
-        }
+        hir::TraitRef { path, hir_ref_id: self.lower_node_id(p.ref_id) }
     }
 
     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(),
             itctx.reborrow(),
         );
-        let trait_ref = self.with_in_scope_lifetime_defs(
-            &p.bound_generic_params,
-            |this| this.lower_trait_ref(&p.trait_ref, itctx),
-        );
+        let trait_ref = self.with_in_scope_lifetime_defs(&p.bound_generic_params, |this| {
+            this.lower_trait_ref(&p.trait_ref, itctx)
+        });
 
-        hir::PolyTraitRef {
-            bound_generic_params,
-            trait_ref,
-            span: p.span,
-        }
+        hir::PolyTraitRef { bound_generic_params, trait_ref, span: p.span }
     }
 
-    fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext<'_>) -> hir::MutTy {
-        hir::MutTy {
-            ty: self.lower_ty(&mt.ty, itctx),
-            mutbl: mt.mutbl,
-        }
+    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],
+        itctx: ImplTraitContext<'_, 'hir>,
+    ) -> hir::GenericBounds<'hir> {
+        self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, itctx))
     }
 
-    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()
+    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) -> P<hir::Block> {
+    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));
                 }
@@ -2743,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) => {
@@ -2768,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,
@@ -2781,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(
@@ -2802,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) => {
@@ -2819,12 +2709,10 @@ fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
                 hir::PatKind::Tuple(pats, ddpos)
             }
             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::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),
@@ -2843,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;
 
@@ -2871,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
@@ -2880,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;
@@ -2895,7 +2783,7 @@ fn lower_pat_slice(&mut self, pats: &[AstP<Pat>]) -> hir::PatKind {
                     prev_rest_span = Some(pat.span);
                     slice = Some(self.pat_wild_with_node_id_of(pat));
                     break;
-                },
+                }
                 // Found a sub-slice pattern `$binding_mode $ident @ ..`.
                 // Record, lower it to `$binding_mode $ident @ _`, and stop here.
                 PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => {
@@ -2904,7 +2792,7 @@ fn lower_pat_slice(&mut self, pats: &[AstP<Pat>]) -> hir::PatKind {
                     let node = self.lower_pat_ident(pat, bm, ident, lower_sub);
                     slice = Some(self.pat_with_node_id_of(pat, node));
                     break;
-                },
+                }
                 // It was not a subslice pattern so lower it normally.
                 _ => before.push(self.lower_pat(pat)),
             }
@@ -2919,7 +2807,7 @@ fn lower_pat_slice(&mut self, pats: &[AstP<Pat>]) -> hir::PatKind {
                     // The `HirValidator` is merciless; add a `_` pattern to avoid ICEs.
                     after.push(self.pat_wild_with_node_id_of(pat));
                     Some(sub.span)
-                },
+                }
                 _ => None,
             };
             if let Some(rest_span) = rest_span {
@@ -2931,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(
@@ -2939,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(_)) => {
@@ -2958,26 +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.
@@ -2990,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")
@@ -3010,19 +2898,17 @@ fn lower_range_end(&mut self, e: &RangeEnd) -> hir::RangeEnd {
     }
 
     fn lower_anon_const(&mut self, c: &AnonConst) -> hir::AnonConst {
-        self.with_new_scopes(|this| {
-            hir::AnonConst {
-                hir_id: this.lower_node_id(c.id),
-                body: this.lower_const_body(c.value.span, Some(&c.value)),
-            }
+        self.with_new_scopes(|this| hir::AnonConst {
+            hir_id: this.lower_node_id(c.id),
+            body: this.lower_const_body(c.value.span, Some(&c.value)),
         })
     }
 
-    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) };
@@ -3032,39 +2918,33 @@ 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,
                     }
                 });
                 return ids;
-            },
+            }
             StmtKind::Item(ref it) => {
                 // Can only use the ID once.
                 let mut id = Some(s.id);
-                return self.lower_item_id(it)
+                return self
+                    .lower_item_id(it)
                     .into_iter()
                     .map(|item_id| {
-                        let hir_id = id.take()
-                          .map(|id| self.lower_node_id(id))
-                          .unwrap_or_else(|| self.next_id());
-
-                        hir::Stmt {
-                            hir_id,
-                            kind: hir::StmtKind::Item(item_id),
-                            span: s.span,
-                        }
+                        let hir_id = id
+                            .take()
+                            .map(|id| self.lower_node_id(id))
+                            .unwrap_or_else(|| self.next_id());
+
+                        hir::Stmt { hir_id, kind: hir::StmtKind::Item(item_id), span: s.span }
                     })
                     .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,
-        }]
+        smallvec![hir::Stmt { hir_id: self.lower_node_id(s.id), kind, span: s.span }]
     }
 
     fn lower_block_check_mode(&mut self, b: &BlockCheckMode) -> hir::BlockCheckMode {
@@ -3099,84 +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 {
-        let local = hir::Local {
-            attrs,
-            hir_id: self.next_id(),
-            init,
-            pat,
-            source,
-            span,
-            ty: None,
-        };
-        self.stmt(span, hir::StmtKind::Local(P(local)))
+    ) -> 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(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 {
@@ -3185,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)
     }
 
@@ -3194,29 +3067,25 @@ 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,
             }),
-            hir_id
+            hir_id,
         )
     }
 
-    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
@@ -3226,50 +3095,59 @@ 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);
 
-        let mut segments: Vec<_> = path.segments.iter().map(|segment| {
-            let res = self.expect_full_res(segment.id);
-            hir::PathSegment {
-                ident: segment.ident,
-                hir_id: Some(self.lower_node_id(segment.id)),
-                res: Some(self.lower_res(res)),
-                infer_args: true,
-                args: None,
-            }
-        }).collect();
+        let mut segments: Vec<_> = path
+            .segments
+            .iter()
+            .map(|segment| {
+                let res = self.expect_full_res(segment.id);
+                hir::PathSegment {
+                    ident: segment.ident,
+                    hir_id: Some(self.lower_node_id(segment.id)),
+                    res: Some(self.lower_res(res)),
+                    infer_args: true,
+                    args: None,
+                }
+            })
+            .collect();
         segments.last_mut().unwrap().args = params;
 
         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(),
-                            trait_ref: hir::TraitRef {
-                                path,
-                                hir_ref_id: hir_id,
-                            },
+                            bound_generic_params: &[],
+                            trait_ref: hir::TraitRef { path, hir_ref_id: hir_id },
                             span,
                         };
 
                         // 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)),
                 }
@@ -3277,11 +3155,7 @@ fn ty_path(&mut self, mut hir_id: hir::HirId, span: Span, qpath: hir::QPath) ->
             _ => hir::TyKind::Path(qpath),
         };
 
-        hir::Ty {
-            hir_id,
-            kind,
-            span,
-        }
+        hir::Ty { hir_id, kind, span }
     }
 
     /// Invoked to create the lifetime argument for a type `&T`
@@ -3320,13 +3194,7 @@ fn new_error_lifetime(&mut self, id: Option<NodeId>, span: Span) -> hir::Lifetim
             ),
         };
 
-        let mut err = struct_span_err!(
-            self.sess,
-            span,
-            E0637,
-            "{}",
-            msg,
-        );
+        let mut err = struct_span_err!(self.sess, span, E0637, "{}", msg,);
         err.span_label(span, label);
         err.emit();
 
@@ -3338,19 +3206,15 @@ fn new_error_lifetime(&mut self, id: Option<NodeId>, span: Span) -> hir::Lifetim
     /// sorts of cases are deprecated. This may therefore report a warning or an
     /// error, depending on the mode.
     fn elided_path_lifetimes(&mut self, span: Span, count: usize) -> P<[hir::Lifetime]> {
-        (0..count)
-            .map(|_| self.elided_path_lifetime(span))
-            .collect()
+        (0..count).map(|_| self.elided_path_lifetime(span)).collect()
     }
 
     fn elided_path_lifetime(&mut self, span: Span) -> hir::Lifetime {
         match self.anonymous_lifetime_mode {
             AnonymousLifetimeMode::CreateParameter => {
                 // We should have emitted E0726 when processing this path above
-                self.sess.delay_span_bug(
-                    span,
-                    "expected 'implicit elided lifetime not allowed' error",
-                );
+                self.sess
+                    .delay_span_bug(span, "expected 'implicit elided lifetime not allowed' error");
                 let id = self.resolver.next_node_id();
                 self.new_named_lifetime(id, span, hir::LifetimeName::Error)
             }
@@ -3360,8 +3224,9 @@ fn elided_path_lifetime(&mut self, span: Span) -> hir::Lifetime {
             // `PathSegment`, for which there is no associated `'_` or `&T` with no explicit
             // lifetime. Instead, we simply create an implicit lifetime, which will be checked
             // later, at which point a suitable error will be emitted.
-          | AnonymousLifetimeMode::PassThrough
-          | AnonymousLifetimeMode::ReportError => self.new_implicit_lifetime(span),
+            AnonymousLifetimeMode::PassThrough | AnonymousLifetimeMode::ReportError => {
+                self.new_implicit_lifetime(span)
+            }
         }
     }
 
@@ -3404,17 +3269,15 @@ fn elided_dyn_bound(&mut self, span: Span) -> hir::Lifetime {
     }
 
     fn new_implicit_lifetime(&mut self, span: Span) -> hir::Lifetime {
-        hir::Lifetime {
-            hir_id: self.next_id(),
-            span,
-            name: hir::LifetimeName::Implicit,
-        }
+        hir::Lifetime { hir_id: self.next_id(), span, name: hir::LifetimeName::Implicit }
     }
 
     fn maybe_lint_bare_trait(&mut self, span: Span, id: NodeId, is_global: bool) {
         // FIXME(davidtwco): This is a hack to detect macros which produce spans of the
         // call site which do not have a macro backtrace. See #61963.
-        let is_macro_callsite = self.sess.source_map()
+        let is_macro_callsite = self
+            .sess
+            .source_map()
             .span_to_snippet(span)
             .map(|snippet| snippet.starts_with("#["))
             .unwrap_or(true);
@@ -3438,64 +3301,23 @@ fn body_ids(bodies: &BTreeMap<hir::BodyId, hir::Body<'hir>>) -> Vec<hir::BodyId>
     body_ids
 }
 
-/// Checks if the specified expression is a built-in range literal.
-/// (See: `LoweringContext::lower_expr()`).
-pub fn is_range_literal(sess: &Session, expr: &hir::Expr) -> bool {
-    use hir::{Path, QPath, ExprKind, TyKind};
-
-    // Returns whether the given path represents a (desugared) range,
-    // either in std or core, i.e. has either a `::std::ops::Range` or
-    // `::core::ops::Range` prefix.
-    fn is_range_path(path: &Path) -> bool {
-        let segs: Vec<_> = path.segments.iter().map(|seg| seg.ident.to_string()).collect();
-        let segs: Vec<_> = segs.iter().map(|seg| &**seg).collect();
-
-        // "{{root}}" is the equivalent of `::` prefix in `Path`.
-        if let ["{{root}}", std_core, "ops", range] = segs.as_slice() {
-            (*std_core == "std" || *std_core == "core") && range.starts_with("Range")
-        } else {
-            false
-        }
-    };
-
-    // Check whether a span corresponding to a range expression is a
-    // range literal, rather than an explicit struct or `new()` call.
-    fn is_lit(sess: &Session, span: &Span) -> bool {
-        let source_map = sess.source_map();
-        let end_point = source_map.end_point(*span);
-
-        if let Ok(end_string) = source_map.span_to_snippet(end_point) {
-            !(end_string.ends_with("}") || end_string.ends_with(")"))
-        } else {
-            false
-        }
-    };
-
-    match expr.kind {
-        // All built-in range literals but `..=` and `..` desugar to `Struct`s.
-        ExprKind::Struct(ref qpath, _, _) => {
-            if let QPath::Resolved(None, ref path) = **qpath {
-                return is_range_path(&path) && is_lit(sess, &expr.span);
-            }
-        }
+/// Helper struct for delayed construction of GenericArgs.
+struct GenericArgsCtor<'hir> {
+    args: Vec<hir::GenericArg<'hir>>,
+    bindings: &'hir [hir::TypeBinding<'hir>],
+    parenthesized: bool,
+}
 
-        // `..` desugars to its struct path.
-        ExprKind::Path(QPath::Resolved(None, ref path)) => {
-            return is_range_path(&path) && is_lit(sess, &expr.span);
-        }
+impl GenericArgsCtor<'hir> {
+    fn is_empty(&self) -> bool {
+        self.args.is_empty() && self.bindings.is_empty() && !self.parenthesized
+    }
 
-        // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
-        ExprKind::Call(ref func, _) => {
-            if let ExprKind::Path(QPath::TypeRelative(ref ty, ref segment)) = func.kind {
-                if let TyKind::Path(QPath::Resolved(None, ref path)) = ty.kind {
-                    let new_call = segment.ident.name == sym::new;
-                    return is_range_path(&path) && is_lit(sess, &expr.span) && new_call;
-                }
-            }
+    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,
         }
-
-        _ => {}
     }
-
-    false
 }