diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs
index 518442efe7417..c2edcd22f953b 100644
--- a/src/libcore/iter/adapters/mod.rs
+++ b/src/libcore/iter/adapters/mod.rs
@@ -1509,6 +1509,20 @@ impl<I> DoubleEndedIterator for Skip<I> where I: DoubleEndedIterator + ExactSize
         }
     }
 
+    #[inline]
+    fn nth_back(&mut self, n: usize) -> Option<I::Item> {
+        let len = self.len();
+        if n < len {
+            self.iter.nth_back(n)
+        } else {
+            if len > 0 {
+                // consume the original iterator
+                self.iter.nth_back(len-1);
+            }
+            None
+        }
+    }
+
     fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where
         Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
     {
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index af1b20a4c10cf..c6d44324ef5ee 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -3019,6 +3019,28 @@ macro_rules! iterator {
         {$( $mut_:tt )*},
         {$($extra:tt)*}
     ) => {
+        // Returns the first element and moves the start of the iterator forwards by 1.
+        // Greatly improves performance compared to an inlined function. The iterator
+        // must not be empty.
+        macro_rules! next_unchecked {
+            ($self: ident) => {& $( $mut_ )* *$self.post_inc_start(1)}
+        }
+
+        // Returns the last element and moves the end of the iterator backwards by 1.
+        // Greatly improves performance compared to an inlined function. The iterator
+        // must not be empty.
+        macro_rules! next_back_unchecked {
+            ($self: ident) => {& $( $mut_ )* *$self.pre_dec_end(1)}
+        }
+
+        // Shrinks the iterator when T is a ZST, by moving the end of the iterator
+        // backwards by `n`. `n` must not exceed `self.len()`.
+        macro_rules! zst_shrink {
+            ($self: ident, $n: ident) => {
+                $self.end = ($self.end as * $raw_mut u8).wrapping_offset(-$n) as * $raw_mut T;
+            }
+        }
+
         impl<'a, T> $name<'a, T> {
             // Helper function for creating a slice from the iterator.
             #[inline(always)]
@@ -3028,12 +3050,11 @@ macro_rules! iterator {
 
             // Helper function for moving the start of the iterator forwards by `offset` elements,
             // returning the old start.
-            // Unsafe because the offset must be in-bounds or one-past-the-end.
+            // Unsafe because the offset must not exceed `self.len()`.
             #[inline(always)]
             unsafe fn post_inc_start(&mut self, offset: isize) -> * $raw_mut T {
                 if mem::size_of::<T>() == 0 {
-                    // This is *reducing* the length.  `ptr` never changes with ZST.
-                    self.end = (self.end as * $raw_mut u8).wrapping_offset(-offset) as * $raw_mut T;
+                    zst_shrink!(self, offset);
                     self.ptr
                 } else {
                     let old = self.ptr;
@@ -3044,11 +3065,11 @@ macro_rules! iterator {
 
             // Helper function for moving the end of the iterator backwards by `offset` elements,
             // returning the new end.
-            // Unsafe because the offset must be in-bounds or one-past-the-end.
+            // Unsafe because the offset must not exceed `self.len()`.
             #[inline(always)]
             unsafe fn pre_dec_end(&mut self, offset: isize) -> * $raw_mut T {
                 if mem::size_of::<T>() == 0 {
-                    self.end = (self.end as * $raw_mut u8).wrapping_offset(-offset) as * $raw_mut T;
+                    zst_shrink!(self, offset);
                     self.ptr
                 } else {
                     self.end = self.end.offset(-offset);
@@ -3085,7 +3106,7 @@ macro_rules! iterator {
                     if is_empty!(self) {
                         None
                     } else {
-                        Some(& $( $mut_ )* *self.post_inc_start(1))
+                        Some(next_unchecked!(self))
                     }
                 }
             }
@@ -3114,11 +3135,10 @@ macro_rules! iterator {
                     }
                     return None;
                 }
-                // We are in bounds. `offset` does the right thing even for ZSTs.
+                // We are in bounds. `post_inc_start` does the right thing even for ZSTs.
                 unsafe {
-                    let elem = Some(& $( $mut_ )* *self.ptr.add(n));
-                    self.post_inc_start((n as isize).wrapping_add(1));
-                    elem
+                    self.post_inc_start(n as isize);
+                    Some(next_unchecked!(self))
                 }
             }
 
@@ -3135,13 +3155,13 @@ macro_rules! iterator {
                 let mut accum = init;
                 unsafe {
                     while len!(self) >= 4 {
-                        accum = f(accum, & $( $mut_ )* *self.post_inc_start(1))?;
-                        accum = f(accum, & $( $mut_ )* *self.post_inc_start(1))?;
-                        accum = f(accum, & $( $mut_ )* *self.post_inc_start(1))?;
-                        accum = f(accum, & $( $mut_ )* *self.post_inc_start(1))?;
+                        accum = f(accum, next_unchecked!(self))?;
+                        accum = f(accum, next_unchecked!(self))?;
+                        accum = f(accum, next_unchecked!(self))?;
+                        accum = f(accum, next_unchecked!(self))?;
                     }
                     while !is_empty!(self) {
-                        accum = f(accum, & $( $mut_ )* *self.post_inc_start(1))?;
+                        accum = f(accum, next_unchecked!(self))?;
                     }
                 }
                 Try::from_ok(accum)
@@ -3212,11 +3232,25 @@ macro_rules! iterator {
                     if is_empty!(self) {
                         None
                     } else {
-                        Some(& $( $mut_ )* *self.pre_dec_end(1))
+                        Some(next_back_unchecked!(self))
                     }
                 }
             }
 
+            #[inline]
+            fn nth_back(&mut self, n: usize) -> Option<$elem> {
+                if n >= len!(self) {
+                    // This iterator is now empty.
+                    self.end = self.ptr;
+                    return None;
+                }
+                // We are in bounds. `pre_dec_end` does the right thing even for ZSTs.
+                unsafe {
+                    self.pre_dec_end(n as isize);
+                    Some(next_back_unchecked!(self))
+                }
+            }
+
             #[inline]
             fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R where
                 Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B>
@@ -3225,14 +3259,14 @@ macro_rules! iterator {
                 let mut accum = init;
                 unsafe {
                     while len!(self) >= 4 {
-                        accum = f(accum, & $( $mut_ )* *self.pre_dec_end(1))?;
-                        accum = f(accum, & $( $mut_ )* *self.pre_dec_end(1))?;
-                        accum = f(accum, & $( $mut_ )* *self.pre_dec_end(1))?;
-                        accum = f(accum, & $( $mut_ )* *self.pre_dec_end(1))?;
+                        accum = f(accum, next_back_unchecked!(self))?;
+                        accum = f(accum, next_back_unchecked!(self))?;
+                        accum = f(accum, next_back_unchecked!(self))?;
+                        accum = f(accum, next_back_unchecked!(self))?;
                     }
                     // inlining is_empty everywhere makes a huge performance difference
                     while !is_empty!(self) {
-                        accum = f(accum, & $( $mut_ )* *self.pre_dec_end(1))?;
+                        accum = f(accum, next_back_unchecked!(self))?;
                     }
                 }
                 Try::from_ok(accum)
diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs
index 020618ae7aeed..4d840ef24c8e6 100644
--- a/src/libcore/tests/iter.rs
+++ b/src/libcore/tests/iter.rs
@@ -2333,6 +2333,40 @@ fn test_skip_try_folds() {
     assert_eq!(iter.next_back(), Some(24));
 }
 
+#[test]
+fn test_skip_nth_back() {
+    let xs = [0, 1, 2, 3, 4, 5];
+    let mut it = xs.iter().skip(2);
+    assert_eq!(it.nth_back(0), Some(&5));
+    assert_eq!(it.nth_back(1), Some(&3));
+    assert_eq!(it.nth_back(0), Some(&2));
+    assert_eq!(it.nth_back(0), None);
+
+    let ys = [2, 3, 4, 5];
+    let mut ity = ys.iter();
+    let mut it = xs.iter().skip(2);
+    assert_eq!(it.nth_back(1), ity.nth_back(1));
+    assert_eq!(it.clone().nth(0), ity.clone().nth(0));
+    assert_eq!(it.nth_back(0), ity.nth_back(0));
+    assert_eq!(it.clone().nth(0), ity.clone().nth(0));
+    assert_eq!(it.nth_back(0), ity.nth_back(0));
+    assert_eq!(it.clone().nth(0), ity.clone().nth(0));
+    assert_eq!(it.nth_back(0), ity.nth_back(0));
+    assert_eq!(it.clone().nth(0), ity.clone().nth(0));
+
+    let mut it = xs.iter().skip(2);
+    assert_eq!(it.nth_back(4), None);
+    assert_eq!(it.nth_back(0), None);
+
+    let mut it = xs.iter();
+    it.by_ref().skip(2).nth_back(3);
+    assert_eq!(it.next_back(), Some(&1));
+
+    let mut it = xs.iter();
+    it.by_ref().skip(2).nth_back(10);
+    assert_eq!(it.next_back(), Some(&1));
+}
+
 #[test]
 fn test_take_try_folds() {
     let f = &|acc, x| i32::checked_add(2*acc, x);
diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs
index eaa799fa96ee2..03e65d2fe0b81 100644
--- a/src/libcore/tests/slice.rs
+++ b/src/libcore/tests/slice.rs
@@ -88,6 +88,19 @@ fn test_iterator_nth() {
     assert_eq!(iter.nth(1).unwrap(), &v[4]);
 }
 
+#[test]
+fn test_iterator_nth_back() {
+    let v: &[_] = &[0, 1, 2, 3, 4];
+    for i in 0..v.len() {
+        assert_eq!(v.iter().nth_back(i).unwrap(), &v[v.len() - i - 1]);
+    }
+    assert_eq!(v.iter().nth_back(v.len()), None);
+
+    let mut iter = v.iter();
+    assert_eq!(iter.nth_back(2).unwrap(), &v[2]);
+    assert_eq!(iter.nth_back(1).unwrap(), &v[0]);
+}
+
 #[test]
 fn test_iterator_last() {
     let v: &[_] = &[0, 1, 2, 3, 4];
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 996af3672e8bd..c87ab68693726 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -608,15 +608,7 @@ impl<'a> LoweringContext<'a> {
                 });
 
                 if let Some(hir_id) = item_hir_id {
-                    let item_generics = match self.lctx.items.get(&hir_id).unwrap().node {
-                        hir::ItemKind::Impl(_, _, _, ref generics, ..)
-                        | hir::ItemKind::Trait(_, _, ref generics, ..) => {
-                            generics.params.clone()
-                        }
-                        _ => HirVec::new(),
-                    };
-
-                    self.lctx.with_parent_impl_lifetime_defs(&item_generics, |this| {
+                    self.lctx.with_parent_item_lifetime_defs(hir_id, |this| {
                         let this = &mut ItemLowerer { lctx: this };
                         if let ItemKind::Impl(.., ref opt_trait_ref, _, _) = item.node {
                             this.with_trait_impl_ref(opt_trait_ref, |this| {
@@ -1054,14 +1046,22 @@ impl<'a> LoweringContext<'a> {
     // This should only be used with generics that have already had their
     // in-band lifetimes added. In practice, this means that this function is
     // only used when lowering a child item of a trait or impl.
-    fn with_parent_impl_lifetime_defs<T, F>(&mut self,
-        params: &HirVec<hir::GenericParam>,
+    fn with_parent_item_lifetime_defs<T, F>(&mut self,
+        parent_hir_id: hir::HirId,
         f: F
     ) -> T where
         F: FnOnce(&mut LoweringContext<'_>) -> T,
     {
         let old_len = self.in_scope_lifetimes.len();
-        let lt_def_names = params.iter().filter_map(|param| match param.kind {
+
+        let parent_generics = match self.items.get(&parent_hir_id).unwrap().node {
+            hir::ItemKind::Impl(_, _, _, ref generics, ..)
+            | hir::ItemKind::Trait(_, _, ref generics, ..) => {
+                &generics.params[..]
+            }
+            _ => &[],
+        };
+        let lt_def_names = parent_generics.iter().filter_map(|param| match param.kind {
             hir::GenericParamKind::Lifetime { .. } => Some(param.name.ident().modern()),
             _ => None,
         });
@@ -1113,8 +1113,7 @@ impl<'a> LoweringContext<'a> {
 
         lowered_generics.params = lowered_generics
             .params
-            .iter()
-            .cloned()
+            .into_iter()
             .chain(in_band_defs)
             .collect();
 
@@ -3114,8 +3113,8 @@ impl<'a> LoweringContext<'a> {
             &NodeMap::default(),
             itctx.reborrow(),
         );
-        let trait_ref = self.with_parent_impl_lifetime_defs(
-            &bound_generic_params,
+        let trait_ref = self.with_in_scope_lifetime_defs(
+            &p.bound_generic_params,
             |this| this.lower_trait_ref(&p.trait_ref, itctx),
         );
 
@@ -3602,8 +3601,7 @@ impl<'a> LoweringContext<'a> {
                 // Essentially a single `use` which imports two names is desugared into
                 // two imports.
                 for (res, &new_node_id) in resolutions.zip([id1, id2].iter()) {
-                    let vis = vis.clone();
-                    let ident = ident.clone();
+                    let ident = *ident;
                     let mut path = path.clone();
                     for seg in &mut path.segments {
                         seg.id = self.sess.next_node_id();
@@ -3616,19 +3614,7 @@ impl<'a> LoweringContext<'a> {
                         let path =
                             this.lower_path_extra(res, &path, ParamMode::Explicit, None);
                         let item = hir::ItemKind::Use(P(path), hir::UseKind::Single);
-                        let vis_kind = match vis.node {
-                            hir::VisibilityKind::Public => hir::VisibilityKind::Public,
-                            hir::VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar),
-                            hir::VisibilityKind::Inherited => hir::VisibilityKind::Inherited,
-                            hir::VisibilityKind::Restricted { ref path, hir_id: _ } => {
-                                let path = this.renumber_segment_ids(path);
-                                hir::VisibilityKind::Restricted {
-                                    path,
-                                    hir_id: this.next_id(),
-                                }
-                            }
-                        };
-                        let vis = respan(vis.span, vis_kind);
+                        let vis = this.rebuild_vis(&vis);
 
                         this.insert_item(
                             hir::Item {
@@ -3692,8 +3678,6 @@ impl<'a> LoweringContext<'a> {
                 for &(ref use_tree, id) in trees {
                     let new_hir_id = self.lower_node_id(id);
 
-                    let mut vis = vis.clone();
-                    let mut ident = ident.clone();
                     let mut prefix = prefix.clone();
 
                     // Give the segments new node-ids since they are being cloned.
@@ -3707,6 +3691,9 @@ impl<'a> LoweringContext<'a> {
                     // own its own names, we have to adjust the owner before
                     // lowering the rest of the import.
                     self.with_hir_id_owner(id, |this| {
+                        let mut vis = this.rebuild_vis(&vis);
+                        let mut ident = *ident;
+
                         let item = this.lower_use_tree(use_tree,
                                                        &prefix,
                                                        id,
@@ -3714,20 +3701,6 @@ impl<'a> LoweringContext<'a> {
                                                        &mut ident,
                                                        attrs);
 
-                        let vis_kind = match vis.node {
-                            hir::VisibilityKind::Public => hir::VisibilityKind::Public,
-                            hir::VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar),
-                            hir::VisibilityKind::Inherited => hir::VisibilityKind::Inherited,
-                            hir::VisibilityKind::Restricted { ref path, hir_id: _ } => {
-                                let path = this.renumber_segment_ids(path);
-                                hir::VisibilityKind::Restricted {
-                                    path: path,
-                                    hir_id: this.next_id(),
-                                }
-                            }
-                        };
-                        let vis = respan(vis.span, vis_kind);
-
                         this.insert_item(
                             hir::Item {
                                 hir_id: new_hir_id,
@@ -3773,15 +3746,35 @@ impl<'a> LoweringContext<'a> {
     /// Paths like the visibility path in `pub(super) use foo::{bar, baz}` are repeated
     /// many times in the HIR tree; for each occurrence, we need to assign distinct
     /// `NodeId`s. (See, e.g., #56128.)
-    fn renumber_segment_ids(&mut self, path: &P<hir::Path>) -> P<hir::Path> {
-        debug!("renumber_segment_ids(path = {:?})", path);
-        let mut path = path.clone();
-        for seg in path.segments.iter_mut() {
-            if seg.hir_id.is_some() {
-                seg.hir_id = Some(self.next_id());
-            }
+    fn rebuild_use_path(&mut self, path: &hir::Path) -> hir::Path {
+        debug!("rebuild_use_path(path = {:?})", path);
+        let segments = path.segments.iter().map(|seg| hir::PathSegment {
+            ident: seg.ident,
+            hir_id: seg.hir_id.map(|_| self.next_id()),
+            res: seg.res,
+            args: None,
+            infer_args: seg.infer_args,
+        }).collect();
+        hir::Path {
+            span: path.span,
+            res: path.res,
+            segments,
         }
-        path
+    }
+
+    fn rebuild_vis(&mut self, vis: &hir::Visibility) -> hir::Visibility {
+        let vis_kind = match vis.node {
+            hir::VisibilityKind::Public => hir::VisibilityKind::Public,
+            hir::VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar),
+            hir::VisibilityKind::Inherited => hir::VisibilityKind::Inherited,
+            hir::VisibilityKind::Restricted { ref path, hir_id: _ } => {
+                hir::VisibilityKind::Restricted {
+                    path: P(self.rebuild_use_path(path)),
+                    hir_id: self.next_id(),
+                }
+            }
+        };
+        respan(vis.span, vis_kind)
     }
 
     fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 85c86991f489a..87da3273bd220 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -51,11 +51,11 @@ impl<'hir> Entry<'hir> {
         }
     }
 
-    fn fn_decl(&self) -> Option<&FnDecl> {
+    fn fn_decl(&self) -> Option<&'hir FnDecl> {
         match self.node {
             Node::Item(ref item) => {
                 match item.node {
-                    ItemKind::Fn(ref fn_decl, _, _, _) => Some(&fn_decl),
+                    ItemKind::Fn(ref fn_decl, _, _, _) => Some(fn_decl),
                     _ => None,
                 }
             }
@@ -76,7 +76,7 @@ impl<'hir> Entry<'hir> {
 
             Node::Expr(ref expr) => {
                 match expr.node {
-                    ExprKind::Closure(_, ref fn_decl, ..) => Some(&fn_decl),
+                    ExprKind::Closure(_, ref fn_decl, ..) => Some(fn_decl),
                     _ => None,
                 }
             }
@@ -412,9 +412,9 @@ impl<'hir> Map<'hir> {
         self.forest.krate.body(id)
     }
 
-    pub fn fn_decl_by_hir_id(&self, hir_id: HirId) -> Option<FnDecl> {
+    pub fn fn_decl_by_hir_id(&self, hir_id: HirId) -> Option<&'hir FnDecl> {
         if let Some(entry) = self.find_entry(hir_id) {
-            entry.fn_decl().cloned()
+            entry.fn_decl()
         } else {
             bug!("no entry for hir_id `{}`", hir_id)
         }
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 527f18f57dc2e..2b46170a6d232 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -155,7 +155,7 @@ pub const DUMMY_HIR_ID: HirId = HirId {
 
 pub const DUMMY_ITEM_LOCAL_ID: ItemLocalId = ItemLocalId::MAX;
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Copy, HashStable)]
+#[derive(Copy, Clone, RustcEncodable, RustcDecodable, HashStable)]
 pub struct Lifetime {
     pub hir_id: HirId,
     pub span: Span,
@@ -295,7 +295,7 @@ impl Lifetime {
 /// A `Path` is essentially Rust's notion of a name; for instance,
 /// `std::cmp::PartialEq`. It's represented as a sequence of identifiers,
 /// along with a bunch of supporting information.
-#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, HashStable)]
 pub struct Path {
     pub span: Span,
     /// The resolution for the path.
@@ -324,7 +324,7 @@ impl fmt::Display for Path {
 
 /// A segment of a path: an identifier, an optional lifetime, and a set of
 /// types.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct PathSegment {
     /// The identifier portion of this path segment.
     #[stable_hasher(project(name))]
@@ -383,27 +383,23 @@ impl PathSegment {
         }
     }
 
-    // FIXME: hack required because you can't create a static
-    // `GenericArgs`, so you can't just return a `&GenericArgs`.
-    pub fn with_generic_args<F, R>(&self, f: F) -> R
-        where F: FnOnce(&GenericArgs) -> R
-    {
-        let dummy = GenericArgs::none();
-        f(if let Some(ref args) = self.args {
-            &args
+    pub fn generic_args(&self) -> &GenericArgs {
+        if let Some(ref args) = self.args {
+            args
         } else {
-            &dummy
-        })
+            const DUMMY: &GenericArgs = &GenericArgs::none();
+            DUMMY
+        }
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct ConstArg {
     pub value: AnonConst,
     pub span: Span,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub enum GenericArg {
     Lifetime(Lifetime),
     Type(Ty),
@@ -435,7 +431,7 @@ impl GenericArg {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct GenericArgs {
     /// The generic arguments for this path segment.
     pub args: HirVec<GenericArg>,
@@ -449,7 +445,7 @@ pub struct GenericArgs {
 }
 
 impl GenericArgs {
-    pub fn none() -> Self {
+    pub const fn none() -> Self {
         Self {
             args: HirVec::new(),
             bindings: HirVec::new(),
@@ -509,7 +505,7 @@ pub enum TraitBoundModifier {
 /// `typeck::collect::compute_bounds` matches these against
 /// the "special" built-in traits (see `middle::lang_items`) and
 /// detects `Copy`, `Send` and `Sync`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub enum GenericBound {
     Trait(PolyTraitRef, TraitBoundModifier),
     Outlives(Lifetime),
@@ -545,7 +541,7 @@ pub enum LifetimeParamKind {
     Error,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub enum GenericParamKind {
     /// A lifetime definition (e.g., `'a: 'b + 'c + 'd`).
     Lifetime {
@@ -560,7 +556,7 @@ pub enum GenericParamKind {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct GenericParam {
     pub hir_id: HirId,
     pub name: ParamName,
@@ -580,7 +576,7 @@ pub struct GenericParamCount {
 
 /// Represents lifetimes and type parameters attached to a declaration
 /// of a function, enum, trait, etc.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct Generics {
     pub params: HirVec<GenericParam>,
     pub where_clause: WhereClause,
@@ -588,7 +584,7 @@ pub struct Generics {
 }
 
 impl Generics {
-    pub fn empty() -> Generics {
+    pub const fn empty() -> Generics {
         Generics {
             params: HirVec::new(),
             where_clause: WhereClause {
@@ -642,7 +638,7 @@ pub enum SyntheticTyParamKind {
 }
 
 /// A where-clause in a definition.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct WhereClause {
     pub predicates: HirVec<WherePredicate>,
     // Only valid if predicates isn't empty.
@@ -660,7 +656,7 @@ impl WhereClause {
 }
 
 /// A single predicate in a where-clause.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub enum WherePredicate {
     /// A type binding (e.g., `for<'c> Foo: Send + Clone + 'c`).
     BoundPredicate(WhereBoundPredicate),
@@ -681,7 +677,7 @@ impl WherePredicate {
 }
 
 /// A type bound (e.g., `for<'c> Foo: Send + Clone + 'c`).
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct WhereBoundPredicate {
     pub span: Span,
     /// Any generics from a `for` binding.
@@ -693,7 +689,7 @@ pub struct WhereBoundPredicate {
 }
 
 /// A lifetime predicate (e.g., `'a: 'b + 'c`).
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct WhereRegionPredicate {
     pub span: Span,
     pub lifetime: Lifetime,
@@ -701,7 +697,7 @@ pub struct WhereRegionPredicate {
 }
 
 /// An equality predicate (e.g., `T = int`); currently unsupported.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct WhereEqPredicate {
     pub hir_id: HirId,
     pub span: Span,
@@ -709,7 +705,7 @@ pub struct WhereEqPredicate {
     pub rhs_ty: P<Ty>,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(RustcEncodable, RustcDecodable, Debug)]
 pub struct ModuleItems {
     // Use BTreeSets here so items are in the same order as in the
     // list of all items in Crate
@@ -724,7 +720,7 @@ pub struct ModuleItems {
 /// For more details, see the [rustc guide].
 ///
 /// [rustc guide]: https://rust-lang.github.io/rustc-guide/hir.html
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(RustcEncodable, RustcDecodable, Debug)]
 pub struct Crate {
     pub module: Mod,
     pub attrs: HirVec<Attribute>,
@@ -819,7 +815,7 @@ impl Crate {
 /// A macro definition, in this crate or imported from another.
 ///
 /// Not parsed directly, but created on macro import or `macro_rules!` expansion.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct MacroDef {
     pub name: Name,
     pub vis: Visibility,
@@ -833,7 +829,7 @@ pub struct MacroDef {
 /// A block of statements `{ .. }`, which may have a label (in this case the
 /// `targeted_by_break` field will be `true`) and may be `unsafe` by means of
 /// the `rules` being anything but `DefaultBlock`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct Block {
     /// Statements in a block.
     pub stmts: HirVec<Stmt>,
@@ -851,7 +847,7 @@ pub struct Block {
     pub targeted_by_break: bool,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, HashStable)]
 pub struct Pat {
     #[stable_hasher(ignore)]
     pub hir_id: HirId,
@@ -914,7 +910,7 @@ impl Pat {
 /// Patterns like the fields of Foo `{ x, ref y, ref mut z }`
 /// are treated the same as` x: x, y: ref y, z: ref mut z`,
 /// except `is_shorthand` is true.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct FieldPat {
     #[stable_hasher(ignore)]
     pub hir_id: HirId,
@@ -929,7 +925,7 @@ pub struct FieldPat {
 /// Explicit binding annotations given in the HIR for a binding. Note
 /// that this is not the final binding *mode* that we infer after type
 /// inference.
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, HashStable)]
+#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub enum BindingAnnotation {
     /// No binding annotation given: this means that the final binding mode
     /// will depend on whether we have skipped through a `&` reference
@@ -956,7 +952,7 @@ pub enum RangeEnd {
     Excluded,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub enum PatKind {
     /// Represents a wildcard pattern (i.e., `_`).
     Wild,
@@ -1001,8 +997,8 @@ pub enum PatKind {
     Slice(HirVec<P<Pat>>, Option<P<Pat>>, HirVec<P<Pat>>),
 }
 
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, HashStable,
-         RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, HashStable,
+         RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum Mutability {
     MutMutable,
     MutImmutable,
@@ -1018,7 +1014,7 @@ impl Mutability {
     }
 }
 
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, Hash, HashStable)]
+#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Hash, HashStable)]
 pub enum BinOpKind {
     /// The `+` operator (addition).
     Add,
@@ -1152,7 +1148,7 @@ impl Into<ast::BinOpKind> for BinOpKind {
 
 pub type BinOp = Spanned<BinOpKind>;
 
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, Hash, HashStable)]
+#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Hash, HashStable)]
 pub enum UnOp {
     /// The `*` operator (deferencing).
     UnDeref,
@@ -1181,7 +1177,7 @@ impl UnOp {
 }
 
 /// A statement.
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(RustcEncodable, RustcDecodable)]
 pub struct Stmt {
     pub hir_id: HirId,
     pub node: StmtKind,
@@ -1196,7 +1192,7 @@ impl fmt::Debug for Stmt {
 }
 
 /// The contents of a statement.
-#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, HashStable)]
 pub enum StmtKind {
     /// A local (`let`) binding.
     Local(P<Local>),
@@ -1223,7 +1219,7 @@ impl StmtKind {
 }
 
 /// Represents a `let` statement (i.e., `let <pat>:<ty> = <expr>;`).
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct Local {
     pub pat: P<Pat>,
     /// Type annotation, if any (otherwise the type will be inferred).
@@ -1240,7 +1236,7 @@ pub struct Local {
 
 /// Represents a single arm of a `match` expression, e.g.
 /// `<pats> (if <guard>) => <body>`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct Arm {
     #[stable_hasher(ignore)]
     pub hir_id: HirId,
@@ -1254,12 +1250,12 @@ pub struct Arm {
     pub body: P<Expr>,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub enum Guard {
     If(P<Expr>),
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct Field {
     #[stable_hasher(ignore)]
     pub hir_id: HirId,
@@ -1269,7 +1265,7 @@ pub struct Field {
     pub is_shorthand: bool,
 }
 
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, HashStable)]
+#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub enum BlockCheckMode {
     DefaultBlock,
     UnsafeBlock(UnsafeSource),
@@ -1277,7 +1273,7 @@ pub enum BlockCheckMode {
     PopUnsafeBlock(UnsafeSource),
 }
 
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, HashStable)]
+#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub enum UnsafeSource {
     CompilerGenerated,
     UserProvided,
@@ -1309,7 +1305,7 @@ pub struct BodyId {
 ///
 /// All bodies have an **owner**, which can be accessed via the HIR
 /// map using `body_owner_def_id()`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(RustcEncodable, RustcDecodable, Debug)]
 pub struct Body {
     pub arguments: HirVec<Arg>,
     pub value: Expr,
@@ -1383,7 +1379,7 @@ pub struct AnonConst {
 }
 
 /// An expression
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(RustcEncodable, RustcDecodable)]
 pub struct Expr {
     pub span: Span,
     pub node: ExprKind,
@@ -1494,7 +1490,7 @@ impl fmt::Debug for Expr {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub enum ExprKind {
     /// A `box x` expression.
     Box(P<Expr>),
@@ -1602,7 +1598,7 @@ pub enum ExprKind {
 }
 
 /// Represents an optionally `Self`-qualified value/type path or associated extension.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub enum QPath {
     /// Path to a definition, optionally "fully-qualified" with a `Self`
     /// type, if the path points to an associated item in a trait.
@@ -1622,7 +1618,7 @@ pub enum QPath {
 }
 
 /// Hints at the original code for a let statement.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, HashStable)]
+#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub enum LocalSource {
     /// A `match _ { .. }`.
     Normal,
@@ -1644,7 +1640,7 @@ pub enum LocalSource {
 }
 
 /// Hints at the original code for a `match _ { .. }`.
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy, HashStable)]
+#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)]
 pub enum MatchSource {
     /// A `match _ { .. }`.
     Normal,
@@ -1668,7 +1664,7 @@ pub enum MatchSource {
 }
 
 /// The loop type that yielded an `ExprKind::Loop`.
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, HashStable)]
+#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub enum LoopSource {
     /// A `loop { .. }` loop.
     Loop,
@@ -1678,7 +1674,7 @@ pub enum LoopSource {
     ForLoop,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, HashStable)]
+#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub enum LoopIdError {
     OutsideLoopScope,
     UnlabeledCfInWhileCondition,
@@ -1696,7 +1692,7 @@ impl fmt::Display for LoopIdError {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, HashStable)]
+#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct Destination {
     // This is `Some(_)` iff there is an explicit user-specified `label
     pub label: Option<Label>,
@@ -1707,8 +1703,8 @@ pub struct Destination {
 }
 
 /// Whether a generator contains self-references, causing it to be `!Unpin`.
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, HashStable,
-         RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, HashStable,
+         RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum GeneratorMovability {
     /// May contain self-references, `!Unpin`.
     Static,
@@ -1717,7 +1713,7 @@ pub enum GeneratorMovability {
 }
 
 /// The yield kind that caused an `ExprKind::Yield`.
-#[derive(Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
 pub enum YieldSource {
     /// An `<expr>.await`.
     Await,
@@ -1734,7 +1730,7 @@ impl fmt::Display for YieldSource {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, HashStable)]
+#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub enum CaptureClause {
     CaptureByValue,
     CaptureByRef,
@@ -1742,14 +1738,14 @@ pub enum CaptureClause {
 
 // N.B., if you change this, you'll probably want to change the corresponding
 // type structure in middle/ty.rs as well.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct MutTy {
     pub ty: P<Ty>,
     pub mutbl: Mutability,
 }
 
 /// Represents a method's signature in a trait declaration or implementation.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct MethodSig {
     pub header: FnHeader,
     pub decl: P<FnDecl>,
@@ -1767,7 +1763,7 @@ pub struct TraitItemId {
 /// possibly including a default implementation. A trait item is
 /// either required (meaning it doesn't have an implementation, just a
 /// signature) or provided (meaning it has a default implementation).
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(RustcEncodable, RustcDecodable, Debug)]
 pub struct TraitItem {
     pub ident: Ident,
     pub hir_id: HirId,
@@ -1778,7 +1774,7 @@ pub struct TraitItem {
 }
 
 /// Represents a trait method's body (or just argument names).
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub enum TraitMethod {
     /// No default body in the trait, just a signature.
     Required(HirVec<Ident>),
@@ -1788,7 +1784,7 @@ pub enum TraitMethod {
 }
 
 /// Represents a trait method or associated constant or type
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub enum TraitItemKind {
     /// An associated constant with an optional value (otherwise `impl`s must contain a value).
     Const(P<Ty>, Option<BodyId>),
@@ -1808,7 +1804,7 @@ pub struct ImplItemId {
 }
 
 /// Represents anything within an `impl` block
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(RustcEncodable, RustcDecodable, Debug)]
 pub struct ImplItem {
     pub ident: Ident,
     pub hir_id: HirId,
@@ -1821,7 +1817,7 @@ pub struct ImplItem {
 }
 
 /// Represents various kinds of content within an `impl`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub enum ImplItemKind {
     /// An associated constant of the given type, set to the constant result
     /// of the expression
@@ -1848,7 +1844,7 @@ pub enum ImplItemKind {
 ///    Binding(...),
 /// }
 /// ```
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct TypeBinding {
     pub hir_id: HirId,
     #[stable_hasher(project(name))]
@@ -1858,7 +1854,7 @@ pub struct TypeBinding {
 }
 
 // Represents the two kinds of type bindings.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub enum TypeBindingKind {
     /// E.g., `Foo<Bar: Send>`.
     Constraint {
@@ -1879,7 +1875,7 @@ impl TypeBinding {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(RustcEncodable, RustcDecodable)]
 pub struct Ty {
     pub hir_id: HirId,
     pub node: TyKind,
@@ -1894,7 +1890,7 @@ impl fmt::Debug for Ty {
 }
 
 /// Not represented directly in the AST; referred to by name through a `ty_path`.
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy, HashStable)]
+#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)]
 pub enum PrimTy {
     Int(IntTy),
     Uint(UintTy),
@@ -1904,7 +1900,7 @@ pub enum PrimTy {
     Char,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct BareFnTy {
     pub unsafety: Unsafety,
     pub abi: Abi,
@@ -1913,7 +1909,7 @@ pub struct BareFnTy {
     pub arg_names: HirVec<Ident>,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct ExistTy {
     pub generics: Generics,
     pub bounds: GenericBounds,
@@ -1933,7 +1929,7 @@ pub enum ExistTyOrigin {
 }
 
 /// The various kinds of types recognized by the compiler.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub enum TyKind {
     /// A variable length slice (i.e., `[T]`).
     Slice(P<Ty>),
@@ -1975,7 +1971,7 @@ pub enum TyKind {
     CVarArgs(Lifetime),
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct InlineAsmOutput {
     pub constraint: Symbol,
     pub is_rw: bool,
@@ -1998,14 +1994,14 @@ pub struct InlineAsm {
 }
 
 /// Represents an argument in a function header.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct Arg {
     pub pat: P<Pat>,
     pub hir_id: HirId,
 }
 
 /// Represents the header (not the body) of a function declaration.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct FnDecl {
     /// The types of the function's arguments.
     ///
@@ -2018,7 +2014,7 @@ pub struct FnDecl {
 }
 
 /// Represents what type of implicit self a function has, if any.
-#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub enum ImplicitSelfKind {
     /// Represents a `fn x(self);`.
     Imm,
@@ -2123,7 +2119,7 @@ impl fmt::Debug for ImplPolarity {
 }
 
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub enum FunctionRetTy {
     /// Return type is not specified.
     ///
@@ -2153,7 +2149,7 @@ impl FunctionRetTy {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(RustcEncodable, RustcDecodable, Debug)]
 pub struct Mod {
     /// A span from the first token past `{` to the last token until `}`.
     /// For `mod foo;`, the inner span ranges from the first token
@@ -2162,25 +2158,25 @@ pub struct Mod {
     pub item_ids: HirVec<ItemId>,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct ForeignMod {
     pub abi: Abi,
     pub items: HirVec<ForeignItem>,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct GlobalAsm {
     pub asm: Symbol,
     #[stable_hasher(ignore)] // This is used for error reporting
     pub ctxt: SyntaxContext,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct EnumDef {
     pub variants: HirVec<Variant>,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct VariantKind {
     /// Name of the variant.
     #[stable_hasher(project(name))]
@@ -2219,7 +2215,7 @@ pub enum UseKind {
 /// that the `ref_id` is for. Note that `ref_id`'s value is not the `HirId` of the
 /// trait being referred to but just a unique `HirId` that serves as a key
 /// within the resolution map.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct TraitRef {
     pub path: Path,
     // Don't hash the ref_id. It is tracked via the thing it is used to access
@@ -2241,7 +2237,7 @@ impl TraitRef {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct PolyTraitRef {
     /// The `'a` in `<'a> Foo<&'a T>`.
     pub bound_generic_params: HirVec<GenericParam>,
@@ -2254,7 +2250,7 @@ pub struct PolyTraitRef {
 
 pub type Visibility = Spanned<VisibilityKind>;
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(RustcEncodable, RustcDecodable, Debug)]
 pub enum VisibilityKind {
     Public,
     Crate(CrateSugar),
@@ -2289,7 +2285,7 @@ impl VisibilityKind {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct StructField {
     pub span: Span,
     #[stable_hasher(project(name))]
@@ -2309,7 +2305,7 @@ impl StructField {
 }
 
 /// Fields and constructor IDs of enum variants and structs.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub enum VariantData {
     /// A struct variant.
     ///
@@ -2354,7 +2350,7 @@ pub struct ItemId {
 /// An item
 ///
 /// The name might be a dummy name in case of anonymous items
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(RustcEncodable, RustcDecodable, Debug)]
 pub struct Item {
     pub ident: Ident,
     pub hir_id: HirId,
@@ -2364,7 +2360,7 @@ pub struct Item {
     pub span: Span,
 }
 
-#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct FnHeader {
     pub unsafety: Unsafety,
     pub constness: Constness,
@@ -2381,7 +2377,7 @@ impl FnHeader {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub enum ItemKind {
     /// An `extern crate` item, with optional *original* crate name if the crate was renamed.
     ///
@@ -2484,7 +2480,7 @@ impl ItemKind {
 /// type or method, and whether it is public). This allows other
 /// passes to find the impl they want without loading the ID (which
 /// means fewer edges in the incremental compilation graph).
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct TraitItemRef {
     pub id: TraitItemId,
     #[stable_hasher(project(name))]
@@ -2500,7 +2496,7 @@ pub struct TraitItemRef {
 /// type or method, and whether it is public). This allows other
 /// passes to find the impl they want without loading the ID (which
 /// means fewer edges in the incremental compilation graph).
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct ImplItemRef {
     pub id: ImplItemId,
     #[stable_hasher(project(name))]
@@ -2519,7 +2515,7 @@ pub enum AssocItemKind {
     Existential,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct ForeignItem {
     #[stable_hasher(project(name))]
     pub ident: Ident,
@@ -2531,7 +2527,7 @@ pub struct ForeignItem {
 }
 
 /// An item within an `extern` block.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub enum ForeignItemKind {
     /// A foreign function.
     Fn(P<FnDecl>, HirVec<Ident>, Generics),
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index e1c713b537c2a..8b1984e04f55b 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -625,10 +625,10 @@ impl<'a> State<'a> {
                         self.word_space("for ?")?;
                         self.print_trait_ref(&ptr.trait_ref)?;
                     } else {
-                        real_bounds.push(b.clone());
+                        real_bounds.push(b);
                     }
                 }
-                self.print_bounds(":", &real_bounds[..])?;
+                self.print_bounds(":", real_bounds)?;
                 self.s.word(";")?;
                 self.end()?; // end the outer ibox
             }
@@ -698,10 +698,10 @@ impl<'a> State<'a> {
                         self.word_space("for ?")?;
                         self.print_trait_ref(&ptr.trait_ref)?;
                     } else {
-                        real_bounds.push(b.clone());
+                        real_bounds.push(b);
                     }
                 }
-                self.print_bounds(":", &real_bounds[..])?;
+                self.print_bounds(":", real_bounds)?;
                 self.print_where_clause(&generics.where_clause)?;
                 self.s.word(" ")?;
                 self.bopen()?;
@@ -724,11 +724,11 @@ impl<'a> State<'a> {
                         self.word_space("for ?")?;
                         self.print_trait_ref(&ptr.trait_ref)?;
                     } else {
-                        real_bounds.push(b.clone());
+                        real_bounds.push(b);
                     }
                 }
                 self.nbsp()?;
-                self.print_bounds("=", &real_bounds[..])?;
+                self.print_bounds("=", real_bounds)?;
                 self.print_where_clause(&generics.where_clause)?;
                 self.s.word(";")?;
             }
@@ -1194,12 +1194,11 @@ impl<'a> State<'a> {
         self.s.word(".")?;
         self.print_ident(segment.ident)?;
 
-        segment.with_generic_args(|generic_args| {
-            if !generic_args.args.is_empty() || !generic_args.bindings.is_empty() {
-                return self.print_generic_args(&generic_args, segment.infer_args, true);
-            }
-            Ok(())
-        })?;
+        let generic_args = segment.generic_args();
+        if !generic_args.args.is_empty() || !generic_args.bindings.is_empty() {
+            self.print_generic_args(generic_args, segment.infer_args, true)?;
+        }
+
         self.print_call_post(base_args)
     }
 
@@ -1559,11 +1558,9 @@ impl<'a> State<'a> {
                 self.s.word("::")?
             }
             if segment.ident.name != kw::PathRoot {
-               self.print_ident(segment.ident)?;
-               segment.with_generic_args(|generic_args| {
-                   self.print_generic_args(generic_args, segment.infer_args,
-                                           colons_before_params)
-               })?;
+                self.print_ident(segment.ident)?;
+                self.print_generic_args(segment.generic_args(), segment.infer_args,
+                                        colons_before_params)?;
             }
         }
 
@@ -1572,10 +1569,8 @@ impl<'a> State<'a> {
 
     pub fn print_path_segment(&mut self, segment: &hir::PathSegment) -> io::Result<()> {
         if segment.ident.name != kw::PathRoot {
-           self.print_ident(segment.ident)?;
-           segment.with_generic_args(|generic_args| {
-               self.print_generic_args(generic_args, segment.infer_args, false)
-           })?;
+            self.print_ident(segment.ident)?;
+            self.print_generic_args(segment.generic_args(), segment.infer_args, false)?;
         }
         Ok(())
     }
@@ -1600,11 +1595,9 @@ impl<'a> State<'a> {
                     }
                     if segment.ident.name != kw::PathRoot {
                         self.print_ident(segment.ident)?;
-                        segment.with_generic_args(|generic_args| {
-                            self.print_generic_args(generic_args,
-                                                    segment.infer_args,
-                                                    colons_before_params)
-                        })?;
+                        self.print_generic_args(segment.generic_args(),
+                                                segment.infer_args,
+                                                colons_before_params)?;
                     }
                 }
 
@@ -1612,11 +1605,9 @@ impl<'a> State<'a> {
                 self.s.word("::")?;
                 let item_segment = path.segments.last().unwrap();
                 self.print_ident(item_segment.ident)?;
-                item_segment.with_generic_args(|generic_args| {
-                    self.print_generic_args(generic_args,
-                                            item_segment.infer_args,
-                                            colons_before_params)
-                })
+                self.print_generic_args(item_segment.generic_args(),
+                                        item_segment.infer_args,
+                                        colons_before_params)
             }
             hir::QPath::TypeRelative(ref qself, ref item_segment) => {
                 self.s.word("<")?;
@@ -1624,11 +1615,9 @@ impl<'a> State<'a> {
                 self.s.word(">")?;
                 self.s.word("::")?;
                 self.print_ident(item_segment.ident)?;
-                item_segment.with_generic_args(|generic_args| {
-                    self.print_generic_args(generic_args,
-                                            item_segment.infer_args,
-                                            colons_before_params)
-                })
+                self.print_generic_args(item_segment.generic_args(),
+                                        item_segment.infer_args,
+                                        colons_before_params)
             }
         }
     }
@@ -2009,31 +1998,34 @@ impl<'a> State<'a> {
         }
     }
 
-    pub fn print_bounds(&mut self, prefix: &'static str, bounds: &[hir::GenericBound])
-                        -> io::Result<()> {
-        if !bounds.is_empty() {
-            self.s.word(prefix)?;
-            let mut first = true;
-            for bound in bounds {
-                if !(first && prefix.is_empty()) {
-                    self.nbsp()?;
-                }
-                if first {
-                    first = false;
-                } else {
-                    self.word_space("+")?;
-                }
+    pub fn print_bounds<'b>(
+        &mut self,
+        prefix: &'static str,
+        bounds: impl IntoIterator<Item = &'b hir::GenericBound>,
+    ) -> io::Result<()> {
+        let mut first = true;
+        for bound in bounds {
+            if first {
+                self.s.word(prefix)?;
+            }
+            if !(first && prefix.is_empty()) {
+                self.nbsp()?;
+            }
+            if first {
+                first = false;
+            } else {
+                self.word_space("+")?;
+            }
 
-                match bound {
-                    GenericBound::Trait(tref, modifier) => {
-                        if modifier == &TraitBoundModifier::Maybe {
-                            self.s.word("?")?;
-                        }
-                        self.print_poly_trait_ref(tref)?;
-                    }
-                    GenericBound::Outlives(lt) => {
-                        self.print_lifetime(lt)?;
+            match bound {
+                GenericBound::Trait(tref, modifier) => {
+                    if modifier == &TraitBoundModifier::Maybe {
+                        self.s.word("?")?;
                     }
+                    self.print_poly_trait_ref(tref)?;
+                }
+                GenericBound::Outlives(lt) => {
+                    self.print_lifetime(lt)?;
                 }
             }
         }
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 4b65d3b9d8e3a..2555833cd77e3 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -1050,10 +1050,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 (self.tcx.sess.source_map().def_span(span), self.tcx.hir().body(id).arguments.iter()
                     .map(|arg| {
                         if let hir::Pat {
-                            node: hir::PatKind::Tuple(args, _),
+                            node: hir::PatKind::Tuple(ref args, _),
                             span,
                             ..
-                        } = arg.pat.clone().into_inner() {
+                        } = *arg.pat {
                             ArgKind::Tuple(
                                 Some(span),
                                 args.iter().map(|pat| {
diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/conflict_errors.rs
index 6a70a23729c26..dfaad95fa3cb9 100644
--- a/src/librustc_mir/borrow_check/conflict_errors.rs
+++ b/src/librustc_mir/borrow_check/conflict_errors.rs
@@ -1815,8 +1815,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 // as the HIR doesn't have full types for closure arguments.
                 let return_ty = *sig.output().skip_binder();
                 let mut return_span = fn_decl.output.span();
-                if let hir::FunctionRetTy::Return(ty) = fn_decl.output {
-                    if let hir::TyKind::Rptr(lifetime, _) = ty.into_inner().node {
+                if let hir::FunctionRetTy::Return(ty) = &fn_decl.output {
+                    if let hir::TyKind::Rptr(lifetime, _) = ty.node {
                         return_span = lifetime.span;
                     }
                 }
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 8236cd1f73857..267f3798bd1e3 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -97,15 +97,15 @@ pub enum SizedByDefault {
     No,
 }
 
-struct ConvertedBinding<'tcx> {
+struct ConvertedBinding<'a, 'tcx> {
     item_name: ast::Ident,
-    kind: ConvertedBindingKind<'tcx>,
+    kind: ConvertedBindingKind<'a, 'tcx>,
     span: Span,
 }
 
-enum ConvertedBindingKind<'tcx> {
+enum ConvertedBindingKind<'a, 'tcx> {
     Equality(Ty<'tcx>),
-    Constraint(P<[hir::GenericBound]>),
+    Constraint(&'a [hir::GenericBound]),
 }
 
 #[derive(PartialEq)]
@@ -191,15 +191,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         item_segment: &hir::PathSegment)
         -> SubstsRef<'tcx>
     {
-        let (substs, assoc_bindings, _) = item_segment.with_generic_args(|generic_args| {
-            self.create_substs_for_ast_path(
-                span,
-                def_id,
-                generic_args,
-                item_segment.infer_args,
-                None,
-            )
-        });
+        let (substs, assoc_bindings, _) = self.create_substs_for_ast_path(
+            span,
+            def_id,
+            item_segment.generic_args(),
+            item_segment.infer_args,
+            None,
+        );
 
         assoc_bindings.first().map(|b| Self::prohibit_assoc_ty_binding(self.tcx(), b.span));
 
@@ -598,7 +596,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         generic_args: &'a hir::GenericArgs,
         infer_args: bool,
         self_ty: Option<Ty<'tcx>>)
-        -> (SubstsRef<'tcx>, Vec<ConvertedBinding<'tcx>>, Option<Vec<Span>>)
+        -> (SubstsRef<'tcx>, Vec<ConvertedBinding<'a, 'tcx>>, Option<Vec<Span>>)
     {
         // If the type is parameterized by this region, then replace this
         // region with the current anon region binding (in other words,
@@ -740,7 +738,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     hir::TypeBindingKind::Equality { ref ty } =>
                         ConvertedBindingKind::Equality(self.ast_ty_to_ty(ty)),
                     hir::TypeBindingKind::Constraint { ref bounds } =>
-                        ConvertedBindingKind::Constraint(bounds.clone()),
+                        ConvertedBindingKind::Constraint(bounds),
                 };
                 ConvertedBinding {
                     item_name: binding.ident,
@@ -861,21 +859,21 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         ty::TraitRef::new(trait_def_id, substs)
     }
 
-    fn create_substs_for_ast_trait_ref(
+    fn create_substs_for_ast_trait_ref<'a>(
         &self,
         span: Span,
         trait_def_id: DefId,
         self_ty: Ty<'tcx>,
-        trait_segment: &hir::PathSegment,
-    ) -> (SubstsRef<'tcx>, Vec<ConvertedBinding<'tcx>>, Option<Vec<Span>>) {
+        trait_segment: &'a hir::PathSegment,
+    ) -> (SubstsRef<'tcx>, Vec<ConvertedBinding<'a, 'tcx>>, Option<Vec<Span>>) {
         debug!("create_substs_for_ast_trait_ref(trait_segment={:?})",
                trait_segment);
 
         let trait_def = self.tcx().trait_def(trait_def_id);
 
         if !self.tcx().features().unboxed_closures &&
-            trait_segment.with_generic_args(|generic_args| generic_args.parenthesized)
-            != trait_def.paren_sugar {
+            trait_segment.generic_args().parenthesized != trait_def.paren_sugar
+        {
             // For now, require that parenthetical notation be used only with `Fn()` etc.
             let msg = if trait_def.paren_sugar {
                 "the precise format of `Fn`-family traits' type parameters is subject to change. \
@@ -887,13 +885,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                              span, GateIssue::Language, msg);
         }
 
-        trait_segment.with_generic_args(|generic_args| {
-            self.create_substs_for_ast_path(span,
-                                            trait_def_id,
-                                            generic_args,
-                                            trait_segment.infer_args,
-                                            Some(self_ty))
-        })
+        self.create_substs_for_ast_path(span,
+                                        trait_def_id,
+                                        trait_segment.generic_args(),
+                                        trait_segment.infer_args,
+                                        Some(self_ty))
     }
 
     fn trait_defines_associated_type_named(&self,
@@ -916,7 +912,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         for ab in ast_bounds {
             if let &hir::GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = ab {
                 if unbound.is_none() {
-                    unbound = Some(ptr.trait_ref.clone());
+                    unbound = Some(&ptr.trait_ref);
                 } else {
                     span_err!(
                         tcx.sess,
@@ -931,7 +927,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
         let kind_id = tcx.lang_items().require(SizedTraitLangItem);
         match unbound {
-            Some(ref tpb) => {
+            Some(tpb) => {
                 // FIXME(#8559) currently requires the unbound to be built-in.
                 if let Ok(kind_id) = kind_id {
                     if tpb.path.res != Res::Def(DefKind::Trait, kind_id) {
@@ -1052,7 +1048,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         &self,
         hir_ref_id: hir::HirId,
         trait_ref: ty::PolyTraitRef<'tcx>,
-        binding: &ConvertedBinding<'tcx>,
+        binding: &ConvertedBinding<'_, 'tcx>,
         bounds: &mut Bounds<'tcx>,
         speculative: bool,
         dup_bindings: &mut FxHashMap<DefId, Span>,
@@ -1169,7 +1165,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     }
                 }), binding.span));
             }
-            ConvertedBindingKind::Constraint(ref ast_bounds) => {
+            ConvertedBindingKind::Constraint(ast_bounds) => {
                 // "Desugar" a constraint like `T: Iterator<Item: Debug>` to
                 //
                 // `<T as Iterator>::Item: Debug`
@@ -1765,47 +1761,45 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             &self, segments: T) -> bool {
         let mut has_err = false;
         for segment in segments {
-            segment.with_generic_args(|generic_args| {
-                let (mut err_for_lt, mut err_for_ty, mut err_for_ct) = (false, false, false);
-                for arg in &generic_args.args {
-                    let (span, kind) = match arg {
-                        hir::GenericArg::Lifetime(lt) => {
-                            if err_for_lt { continue }
-                            err_for_lt = true;
-                            has_err = true;
-                            (lt.span, "lifetime")
-                        }
-                        hir::GenericArg::Type(ty) => {
-                            if err_for_ty { continue }
-                            err_for_ty = true;
-                            has_err = true;
-                            (ty.span, "type")
-                        }
-                        hir::GenericArg::Const(ct) => {
-                            if err_for_ct { continue }
-                            err_for_ct = true;
-                            (ct.span, "const")
-                        }
-                    };
-                    let mut err = struct_span_err!(
-                        self.tcx().sess,
-                        span,
-                        E0109,
-                        "{} arguments are not allowed for this type",
-                        kind,
-                    );
-                    err.span_label(span, format!("{} argument not allowed", kind));
-                    err.emit();
-                    if err_for_lt && err_for_ty && err_for_ct {
-                        break;
+            let (mut err_for_lt, mut err_for_ty, mut err_for_ct) = (false, false, false);
+            for arg in &segment.generic_args().args {
+                let (span, kind) = match arg {
+                    hir::GenericArg::Lifetime(lt) => {
+                        if err_for_lt { continue }
+                        err_for_lt = true;
+                        has_err = true;
+                        (lt.span, "lifetime")
                     }
-                }
-                for binding in &generic_args.bindings {
-                    has_err = true;
-                    Self::prohibit_assoc_ty_binding(self.tcx(), binding.span);
+                    hir::GenericArg::Type(ty) => {
+                        if err_for_ty { continue }
+                        err_for_ty = true;
+                        has_err = true;
+                        (ty.span, "type")
+                    }
+                    hir::GenericArg::Const(ct) => {
+                        if err_for_ct { continue }
+                        err_for_ct = true;
+                        (ct.span, "const")
+                    }
+                };
+                let mut err = struct_span_err!(
+                    self.tcx().sess,
+                    span,
+                    E0109,
+                    "{} arguments are not allowed for this type",
+                    kind,
+                );
+                err.span_label(span, format!("{} argument not allowed", kind));
+                err.emit();
+                if err_for_lt && err_for_ty && err_for_ct {
                     break;
                 }
-            })
+            }
+            for binding in &segment.generic_args().bindings {
+                has_err = true;
+                Self::prohibit_assoc_ty_binding(self.tcx(), binding.span);
+                break;
+            }
         }
         has_err
     }
diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs
index 563bb5760a94e..8ca1b85ad9aee 100644
--- a/src/librustc_typeck/check/expr.rs
+++ b/src/librustc_typeck/check/expr.rs
@@ -1125,7 +1125,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                     err.emit();
                 } else {
-                    self.report_unknown_field(adt_ty, variant, field, ast_fields, kind_name);
+                    self.report_unknown_field(adt_ty, variant, field, ast_fields, kind_name, span);
                 }
 
                 tcx.types.err
@@ -1196,6 +1196,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         field: &hir::Field,
         skip_fields: &[hir::Field],
         kind_name: &str,
+        ty_span: Span
     ) {
         if variant.recovered {
             return;
@@ -1215,37 +1216,57 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
             },
             ty);
-        // prevent all specified fields from being suggested
-        let skip_fields = skip_fields.iter().map(|ref x| x.ident.as_str());
-        if let Some(field_name) = Self::suggest_field_name(variant,
-                                                           &field.ident.as_str(),
-                                                           skip_fields.collect()) {
-            err.span_suggestion(
-                field.ident.span,
-                "a field with a similar name exists",
-                field_name.to_string(),
-                Applicability::MaybeIncorrect,
-            );
-        } else {
-            match ty.sty {
-                ty::Adt(adt, ..) => {
-                    if adt.is_enum() {
-                        err.span_label(field.ident.span,
-                                       format!("`{}::{}` does not have this field",
-                                               ty, variant.ident));
-                    } else {
-                        err.span_label(field.ident.span,
-                                       format!("`{}` does not have this field", ty));
-                    }
-                    let available_field_names = self.available_field_names(variant);
-                    if !available_field_names.is_empty() {
-                        err.note(&format!("available fields are: {}",
-                                          self.name_series_display(available_field_names)));
+        match variant.ctor_kind {
+            CtorKind::Fn => {
+                err.span_label(variant.ident.span, format!("`{adt}` defined here", adt=ty));
+                err.span_label(field.ident.span, "field does not exist");
+                err.span_label(ty_span, format!(
+                        "`{adt}` is a tuple {kind_name}, \
+                         use the appropriate syntax: `{adt}(/* fields */)`",
+                    adt=ty,
+                    kind_name=kind_name
+                ));
+            }
+            _ => {
+                // prevent all specified fields from being suggested
+                let skip_fields = skip_fields.iter().map(|ref x| x.ident.as_str());
+                if let Some(field_name) = Self::suggest_field_name(
+                    variant,
+                    &field.ident.as_str(),
+                    skip_fields.collect()
+                ) {
+                    err.span_suggestion(
+                        field.ident.span,
+                        "a field with a similar name exists",
+                        field_name.to_string(),
+                        Applicability::MaybeIncorrect,
+                    );
+                } else {
+                    match ty.sty {
+                        ty::Adt(adt, ..) => {
+                            if adt.is_enum() {
+                                err.span_label(field.ident.span, format!(
+                                    "`{}::{}` does not have this field",
+                                    ty,
+                                    variant.ident
+                                ));
+                            } else {
+                                err.span_label(field.ident.span, format!(
+                                    "`{}` does not have this field",
+                                    ty
+                                ));
+                            }
+                            let available_field_names = self.available_field_names(variant);
+                            if !available_field_names.is_empty() {
+                                err.note(&format!("available fields are: {}",
+                                                  self.name_series_display(available_field_names)));
+                            }
+                        }
+                        _ => bug!("non-ADT passed to report_unknown_field")
                     }
-                }
-                _ => bug!("non-ADT passed to report_unknown_field")
+                };
             }
-        };
+        }
         err.emit();
     }
 
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index fe742a74fffec..0e83db48284a8 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -3696,39 +3696,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 
     /// Given a function block's `HirId`, returns its `FnDecl` if it exists, or `None` otherwise.
-    fn get_parent_fn_decl(&self, blk_id: hir::HirId) -> Option<(hir::FnDecl, ast::Ident)> {
+    fn get_parent_fn_decl(&self, blk_id: hir::HirId) -> Option<(&'tcx hir::FnDecl, ast::Ident)> {
         let parent = self.tcx.hir().get_by_hir_id(self.tcx.hir().get_parent_item(blk_id));
         self.get_node_fn_decl(parent).map(|(fn_decl, ident, _)| (fn_decl, ident))
     }
 
     /// Given a function `Node`, return its `FnDecl` if it exists, or `None` otherwise.
-    fn get_node_fn_decl(&self, node: Node<'_>) -> Option<(hir::FnDecl, ast::Ident, bool)> {
+    fn get_node_fn_decl(&self, node: Node<'tcx>) -> Option<(&'tcx hir::FnDecl, ast::Ident, bool)> {
         match node {
             Node::Item(&hir::Item {
                 ident, node: hir::ItemKind::Fn(ref decl, ..), ..
-            }) => decl.clone().and_then(|decl| {
+            }) => {
                 // This is less than ideal, it will not suggest a return type span on any
                 // method called `main`, regardless of whether it is actually the entry point,
                 // but it will still present it as the reason for the expected type.
                 Some((decl, ident, ident.name != sym::main))
-            }),
+            }
             Node::TraitItem(&hir::TraitItem {
                 ident, node: hir::TraitItemKind::Method(hir::MethodSig {
                     ref decl, ..
                 }, ..), ..
-            }) => decl.clone().and_then(|decl| Some((decl, ident, true))),
+            }) => Some((decl, ident, true)),
             Node::ImplItem(&hir::ImplItem {
                 ident, node: hir::ImplItemKind::Method(hir::MethodSig {
                     ref decl, ..
                 }, ..), ..
-            }) => decl.clone().and_then(|decl| Some((decl, ident, false))),
+            }) => Some((decl, ident, false)),
             _ => None,
         }
     }
 
     /// Given a `HirId`, return the `FnDecl` of the method it is enclosed by and whether a
     /// suggestion can be made, `None` otherwise.
-    pub fn get_fn_decl(&self, blk_id: hir::HirId) -> Option<(hir::FnDecl, bool)> {
+    pub fn get_fn_decl(&self, blk_id: hir::HirId) -> Option<(&'tcx hir::FnDecl, bool)> {
         // Get enclosing Fn, if it is a function or a trait method, unless there's a `loop` or
         // `while` before reaching it, as block tail returns are not available in them.
         self.tcx.hir().get_return_block(blk_id).and_then(|blk_id| {
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 5606d9c0ce815..52cda4ac3c628 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -165,7 +165,7 @@ impl ItemCtxt<'tcx> {
         ItemCtxt { tcx, item_def_id }
     }
 
-    pub fn to_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> {
+    pub fn to_ty(&self, ast_ty: &'tcx hir::Ty) -> Ty<'tcx> {
         AstConv::ast_ty_to_ty(self, ast_ty)
     }
 }
@@ -338,7 +338,7 @@ impl ItemCtxt<'tcx> {
     /// bounds for a type parameter `X` if `X::Foo` is used.
     fn type_parameter_bounds_in_generics(
         &self,
-        ast_generics: &hir::Generics,
+        ast_generics: &'tcx hir::Generics,
         param_id: hir::HirId,
         ty: Ty<'tcx>,
         only_self_bounds: OnlySelfBounds,
@@ -1909,7 +1909,9 @@ fn explicit_predicates_of<'tcx>(
     let mut is_default_impl_trait = None;
 
     let icx = ItemCtxt::new(tcx, def_id);
-    let no_generics = hir::Generics::empty();
+
+    const NO_GENERICS: &hir::Generics = &hir::Generics::empty();
+
     let empty_trait_items = HirVec::new();
 
     let mut predicates = UniquePredicates::new();
@@ -1991,17 +1993,17 @@ fn explicit_predicates_of<'tcx>(
                     }
                 }
 
-                _ => &no_generics,
+                _ => NO_GENERICS,
             }
         }
 
         Node::ForeignItem(item) => match item.node {
-            ForeignItemKind::Static(..) => &no_generics,
+            ForeignItemKind::Static(..) => NO_GENERICS,
             ForeignItemKind::Fn(_, _, ref generics) => generics,
-            ForeignItemKind::Type => &no_generics,
+            ForeignItemKind::Type => NO_GENERICS,
         },
 
-        _ => &no_generics,
+        _ => NO_GENERICS,
     };
 
     let generics = tcx.generics_of(def_id);
@@ -2205,7 +2207,7 @@ fn explicit_predicates_of<'tcx>(
 fn predicates_from_bound<'tcx>(
     astconv: &dyn AstConv<'tcx>,
     param_ty: Ty<'tcx>,
-    bound: &hir::GenericBound,
+    bound: &'tcx hir::GenericBound,
 ) -> Vec<(ty::Predicate<'tcx>, Span)> {
     match *bound {
         hir::GenericBound::Trait(ref tr, hir::TraitBoundModifier::None) => {
@@ -2227,7 +2229,7 @@ fn predicates_from_bound<'tcx>(
 fn compute_sig_of_foreign_fn_decl<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: DefId,
-    decl: &hir::FnDecl,
+    decl: &'tcx hir::FnDecl,
     abi: abi::Abi,
 ) -> ty::PolyFnSig<'tcx> {
     let unsafety = if abi == abi::Abi::RustIntrinsic {
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 4becb42d30551..b489ccf179c0e 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -159,7 +159,7 @@ impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
 
         // Clean the crate, translating the entire libsyntax AST to one that is
         // understood by rustdoc.
-        let mut module = self.module.clean(cx);
+        let mut module = self.module.as_ref().unwrap().clean(cx);
         let mut masked_crates = FxHashSet::default();
 
         match module.inner {
@@ -600,7 +600,7 @@ pub struct Module {
     pub is_crate: bool,
 }
 
-impl Clean<Item> for doctree::Module {
+impl Clean<Item> for doctree::Module<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         let name = if self.name.is_some() {
             self.name.expect("No name provided").clean(cx)
@@ -620,7 +620,7 @@ impl Clean<Item> for doctree::Module {
         items.extend(self.unions.iter().map(|x| x.clean(cx)));
         items.extend(self.enums.iter().map(|x| x.clean(cx)));
         items.extend(self.fns.iter().map(|x| x.clean(cx)));
-        items.extend(self.foreigns.iter().flat_map(|x| x.clean(cx)));
+        items.extend(self.foreigns.iter().map(|x| x.clean(cx)));
         items.extend(self.mods.iter().map(|x| x.clean(cx)));
         items.extend(self.typedefs.iter().map(|x| x.clean(cx)));
         items.extend(self.existentials.iter().map(|x| x.clean(cx)));
@@ -1920,10 +1920,10 @@ pub struct Function {
     pub ret_types: Vec<Type>,
 }
 
-impl Clean<Item> for doctree::Function {
+impl Clean<Item> for doctree::Function<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         let (generics, decl) = enter_impl_trait(cx, || {
-            (self.generics.clean(cx), (&self.decl, self.body).clean(cx))
+            (self.generics.clean(cx), (self.decl, self.body).clean(cx))
         });
 
         let did = cx.tcx.hir().local_def_id_from_hir_id(self.id);
@@ -2128,7 +2128,7 @@ pub struct Trait {
     pub is_auto: bool,
 }
 
-impl Clean<Item> for doctree::Trait {
+impl Clean<Item> for doctree::Trait<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         let attrs = self.attrs.clean(cx);
         let is_spotlight = attrs.has_doc_flag(sym::spotlight);
@@ -2143,7 +2143,7 @@ impl Clean<Item> for doctree::Trait {
             inner: TraitItem(Trait {
                 auto: self.is_auto.clean(cx),
                 unsafety: self.unsafety,
-                items: self.items.clean(cx),
+                items: self.items.iter().map(|ti| ti.clean(cx)).collect(),
                 generics: self.generics.clean(cx),
                 bounds: self.bounds.clean(cx),
                 is_spotlight,
@@ -2159,7 +2159,7 @@ pub struct TraitAlias {
     pub bounds: Vec<GenericBound>,
 }
 
-impl Clean<Item> for doctree::TraitAlias {
+impl Clean<Item> for doctree::TraitAlias<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         let attrs = self.attrs.clean(cx);
         Item {
@@ -2809,7 +2809,8 @@ impl Clean<Type> for hir::Ty {
                     let mut ty_substs = FxHashMap::default();
                     let mut lt_substs = FxHashMap::default();
                     let mut ct_substs = FxHashMap::default();
-                    provided_params.with_generic_args(|generic_args| {
+                    let generic_args = provided_params.generic_args();
+                    {
                         let mut indices: GenericParamCount = Default::default();
                         for param in generics.params.iter() {
                             match param.kind {
@@ -2852,11 +2853,11 @@ impl Clean<Type> for hir::Ty {
                                             _ => None,
                                         }
                                     });
-                                    if let Some(ty) = type_.cloned() {
+                                    if let Some(ty) = type_ {
                                         ty_substs.insert(ty_param_def_id, ty.clean(cx));
                                     } else if let Some(default) = default.clone() {
                                         ty_substs.insert(ty_param_def_id,
-                                                         default.into_inner().clean(cx));
+                                                         default.clean(cx));
                                     }
                                     indices.types += 1;
                                 }
@@ -2876,7 +2877,7 @@ impl Clean<Type> for hir::Ty {
                                             _ => None,
                                         }
                                     });
-                                    if let Some(ct) = const_.cloned() {
+                                    if let Some(ct) = const_ {
                                         ct_substs.insert(const_param_def_id, ct.clean(cx));
                                     }
                                     // FIXME(const_generics:defaults)
@@ -2884,26 +2885,26 @@ impl Clean<Type> for hir::Ty {
                                 }
                             }
                         }
-                    });
+                    }
                     return cx.enter_alias(ty_substs, lt_substs, ct_substs, || ty.clean(cx));
                 }
                 resolve_type(cx, path.clean(cx), self.hir_id)
             }
             TyKind::Path(hir::QPath::Resolved(Some(ref qself), ref p)) => {
-                let mut segments: Vec<_> = p.segments.clone().into();
-                segments.pop();
-                let trait_path = hir::Path {
-                    span: p.span,
+                let segments = if p.is_global() { &p.segments[1..] } else { &p.segments };
+                let trait_segments = &segments[..segments.len() - 1];
+                let trait_path = self::Path {
+                    global: p.is_global(),
                     res: Res::Def(
                         DefKind::Trait,
                         cx.tcx.associated_item(p.res.def_id()).container.id(),
                     ),
-                    segments: segments.into(),
+                    segments: trait_segments.clean(cx),
                 };
                 Type::QPath {
                     name: p.segments.last().expect("segments were empty").ident.name.clean(cx),
                     self_type: box qself.clean(cx),
-                    trait_: box resolve_type(cx, trait_path.clean(cx), self.hir_id)
+                    trait_: box resolve_type(cx, trait_path, self.hir_id)
                 }
             }
             TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => {
@@ -3234,7 +3235,7 @@ pub struct Union {
     pub fields_stripped: bool,
 }
 
-impl Clean<Item> for doctree::Struct {
+impl Clean<Item> for doctree::Struct<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         Item {
             name: Some(self.name.clean(cx)),
@@ -3254,7 +3255,7 @@ impl Clean<Item> for doctree::Struct {
     }
 }
 
-impl Clean<Item> for doctree::Union {
+impl Clean<Item> for doctree::Union<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         Item {
             name: Some(self.name.clean(cx)),
@@ -3301,7 +3302,7 @@ pub struct Enum {
     pub variants_stripped: bool,
 }
 
-impl Clean<Item> for doctree::Enum {
+impl Clean<Item> for doctree::Enum<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         Item {
             name: Some(self.name.clean(cx)),
@@ -3325,7 +3326,7 @@ pub struct Variant {
     pub kind: VariantKind,
 }
 
-impl Clean<Item> for doctree::Variant {
+impl Clean<Item> for doctree::Variant<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         Item {
             name: Some(self.name.clean(cx)),
@@ -3537,7 +3538,7 @@ impl Clean<PathSegment> for hir::PathSegment {
     fn clean(&self, cx: &DocContext<'_>) -> PathSegment {
         PathSegment {
             name: self.ident.name.clean(cx),
-            args: self.with_generic_args(|generic_args| generic_args.clean(cx))
+            args: self.generic_args().clean(cx),
         }
     }
 }
@@ -3630,7 +3631,7 @@ pub struct Typedef {
     pub generics: Generics,
 }
 
-impl Clean<Item> for doctree::Typedef {
+impl Clean<Item> for doctree::Typedef<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         Item {
             name: Some(self.name.clean(cx)),
@@ -3654,7 +3655,7 @@ pub struct Existential {
     pub generics: Generics,
 }
 
-impl Clean<Item> for doctree::Existential {
+impl Clean<Item> for doctree::Existential<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         Item {
             name: Some(self.name.clean(cx)),
@@ -3704,7 +3705,7 @@ pub struct Static {
     pub expr: String,
 }
 
-impl Clean<Item> for doctree::Static {
+impl Clean<Item> for doctree::Static<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         debug!("cleaning static {}: {:?}", self.name.clean(cx), self);
         Item {
@@ -3730,7 +3731,7 @@ pub struct Constant {
     pub expr: String,
 }
 
-impl Clean<Item> for doctree::Constant {
+impl Clean<Item> for doctree::Constant<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         Item {
             name: Some(self.name.clean(cx)),
@@ -3800,11 +3801,11 @@ pub fn get_auto_trait_and_blanket_impls(
         .chain(BlanketImplFinder::new(cx).get_blanket_impls(ty, param_env_def_id))
 }
 
-impl Clean<Vec<Item>> for doctree::Impl {
+impl Clean<Vec<Item>> for doctree::Impl<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
         let mut ret = Vec::new();
         let trait_ = self.trait_.clean(cx);
-        let items = self.items.clean(cx);
+        let items = self.items.iter().map(|ii| ii.clean(cx)).collect::<Vec<_>>();
 
         // If this impl block is an implementation of the Deref trait, then we
         // need to try inlining the target's inherent impl blocks as well.
@@ -3901,7 +3902,7 @@ fn build_deref_target_impls(cx: &DocContext<'_>,
     }
 }
 
-impl Clean<Vec<Item>> for doctree::ExternCrate {
+impl Clean<Vec<Item>> for doctree::ExternCrate<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
 
         let please_inline = self.vis.node.is_pub() && self.attrs.iter().any(|a| {
@@ -3940,7 +3941,7 @@ impl Clean<Vec<Item>> for doctree::ExternCrate {
     }
 }
 
-impl Clean<Vec<Item>> for doctree::Import {
+impl Clean<Vec<Item>> for doctree::Import<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
         // We consider inlining the documentation of `pub use` statements, but we
         // forcefully don't inline if this is not public or if the
@@ -4016,22 +4017,11 @@ pub struct ImportSource {
     pub did: Option<DefId>,
 }
 
-impl Clean<Vec<Item>> for hir::ForeignMod {
-    fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
-        let mut items = self.items.clean(cx);
-        for item in &mut items {
-            if let ForeignFunctionItem(ref mut f) = item.inner {
-                f.header.abi = self.abi;
-            }
-        }
-        items
-    }
-}
-
-impl Clean<Item> for hir::ForeignItem {
+impl Clean<Item> for doctree::ForeignItem<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
-        let inner = match self.node {
+        let inner = match self.kind {
             hir::ForeignItemKind::Fn(ref decl, ref names, ref generics) => {
+                let abi = cx.tcx.hir().get_foreign_abi(self.id);
                 let (generics, decl) = enter_impl_trait(cx, || {
                     (generics.clean(cx), (&**decl, &names[..]).clean(cx))
                 });
@@ -4041,7 +4031,7 @@ impl Clean<Item> for hir::ForeignItem {
                     generics,
                     header: hir::FnHeader {
                         unsafety: hir::Unsafety::Unsafe,
-                        abi: Abi::Rust,
+                        abi,
                         constness: hir::Constness::NotConst,
                         asyncness: hir::IsAsync::NotAsync,
                     },
@@ -4061,16 +4051,14 @@ impl Clean<Item> for hir::ForeignItem {
             }
         };
 
-        let local_did = cx.tcx.hir().local_def_id_from_hir_id(self.hir_id);
-
         Item {
-            name: Some(self.ident.clean(cx)),
+            name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
-            source: self.span.clean(cx),
-            def_id: local_did,
+            source: self.whence.clean(cx),
+            def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
             visibility: self.vis.clean(cx),
-            stability: get_stability(cx, local_did),
-            deprecation: get_deprecation(cx, local_did),
+            stability: self.stab.clean(cx),
+            deprecation: self.depr.clean(cx),
             inner,
         }
     }
@@ -4245,7 +4233,7 @@ pub struct Macro {
     pub imported_from: Option<String>,
 }
 
-impl Clean<Item> for doctree::Macro {
+impl Clean<Item> for doctree::Macro<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         let name = self.name.clean(cx);
         Item {
@@ -4274,7 +4262,7 @@ pub struct ProcMacro {
     pub helpers: Vec<String>,
 }
 
-impl Clean<Item> for doctree::ProcMacro {
+impl Clean<Item> for doctree::ProcMacro<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         Item {
             name: Some(self.name.clean(cx)),
diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs
index 7a528e50e9c3f..51deb4e9b9747 100644
--- a/src/librustdoc/doctree.rs
+++ b/src/librustdoc/doctree.rs
@@ -7,52 +7,55 @@ use syntax::ast::{Name, NodeId};
 use syntax::attr;
 use syntax::ext::base::MacroKind;
 use syntax::ptr::P;
-use syntax::source_map::Spanned;
 use syntax_pos::{self, Span};
 
 use rustc::hir;
 use rustc::hir::def_id::CrateNum;
 
-pub struct Module {
+pub struct Module<'hir> {
     pub name: Option<Name>,
-    pub attrs: hir::HirVec<ast::Attribute>,
+    pub attrs: &'hir hir::HirVec<ast::Attribute>,
     pub where_outer: Span,
     pub where_inner: Span,
-    pub extern_crates: Vec<ExternCrate>,
-    pub imports: Vec<Import>,
-    pub structs: Vec<Struct>,
-    pub unions: Vec<Union>,
-    pub enums: Vec<Enum>,
-    pub fns: Vec<Function>,
-    pub mods: Vec<Module>,
+    pub extern_crates: Vec<ExternCrate<'hir>>,
+    pub imports: Vec<Import<'hir>>,
+    pub structs: Vec<Struct<'hir>>,
+    pub unions: Vec<Union<'hir>>,
+    pub enums: Vec<Enum<'hir>>,
+    pub fns: Vec<Function<'hir>>,
+    pub mods: Vec<Module<'hir>>,
     pub id: NodeId,
-    pub typedefs: Vec<Typedef>,
-    pub existentials: Vec<Existential>,
-    pub statics: Vec<Static>,
-    pub constants: Vec<Constant>,
-    pub traits: Vec<Trait>,
-    pub vis: hir::Visibility,
+    pub typedefs: Vec<Typedef<'hir>>,
+    pub existentials: Vec<Existential<'hir>>,
+    pub statics: Vec<Static<'hir>>,
+    pub constants: Vec<Constant<'hir>>,
+    pub traits: Vec<Trait<'hir>>,
+    pub vis: &'hir hir::Visibility,
     pub stab: Option<attr::Stability>,
     pub depr: Option<attr::Deprecation>,
-    pub impls: Vec<Impl>,
-    pub foreigns: Vec<hir::ForeignMod>,
-    pub macros: Vec<Macro>,
-    pub proc_macros: Vec<ProcMacro>,
-    pub trait_aliases: Vec<TraitAlias>,
+    pub impls: Vec<Impl<'hir>>,
+    pub foreigns: Vec<ForeignItem<'hir>>,
+    pub macros: Vec<Macro<'hir>>,
+    pub proc_macros: Vec<ProcMacro<'hir>>,
+    pub trait_aliases: Vec<TraitAlias<'hir>>,
     pub is_crate: bool,
 }
 
-impl Module {
-    pub fn new(name: Option<Name>) -> Module {
+impl Module<'hir> {
+    pub fn new(
+        name: Option<Name>,
+        attrs: &'hir hir::HirVec<ast::Attribute>,
+        vis: &'hir hir::Visibility,
+    ) -> Module<'hir> {
         Module {
             name       : name,
             id: ast::CRATE_NODE_ID,
-            vis: Spanned { span: syntax_pos::DUMMY_SP, node: hir::VisibilityKind::Inherited },
+            vis,
             stab: None,
             depr: None,
             where_outer: syntax_pos::DUMMY_SP,
             where_inner: syntax_pos::DUMMY_SP,
-            attrs      : hir::HirVec::new(),
+            attrs,
             extern_crates: Vec::new(),
             imports    :   Vec::new(),
             structs    :   Vec::new(),
@@ -85,167 +88,178 @@ pub enum StructType {
     Unit,
 }
 
-pub struct Struct {
-    pub vis: hir::Visibility,
+pub struct Struct<'hir> {
+    pub vis: &'hir hir::Visibility,
     pub stab: Option<attr::Stability>,
     pub depr: Option<attr::Deprecation>,
     pub id: hir::HirId,
     pub struct_type: StructType,
     pub name: Name,
-    pub generics: hir::Generics,
-    pub attrs: hir::HirVec<ast::Attribute>,
-    pub fields: hir::HirVec<hir::StructField>,
+    pub generics: &'hir hir::Generics,
+    pub attrs: &'hir hir::HirVec<ast::Attribute>,
+    pub fields: &'hir [hir::StructField],
     pub whence: Span,
 }
 
-pub struct Union {
-    pub vis: hir::Visibility,
+pub struct Union<'hir> {
+    pub vis: &'hir hir::Visibility,
     pub stab: Option<attr::Stability>,
     pub depr: Option<attr::Deprecation>,
     pub id: hir::HirId,
     pub struct_type: StructType,
     pub name: Name,
-    pub generics: hir::Generics,
-    pub attrs: hir::HirVec<ast::Attribute>,
-    pub fields: hir::HirVec<hir::StructField>,
+    pub generics: &'hir hir::Generics,
+    pub attrs: &'hir hir::HirVec<ast::Attribute>,
+    pub fields: &'hir [hir::StructField],
     pub whence: Span,
 }
 
-pub struct Enum {
-    pub vis: hir::Visibility,
+pub struct Enum<'hir> {
+    pub vis: &'hir hir::Visibility,
     pub stab: Option<attr::Stability>,
     pub depr: Option<attr::Deprecation>,
-    pub variants: hir::HirVec<Variant>,
-    pub generics: hir::Generics,
-    pub attrs: hir::HirVec<ast::Attribute>,
+    pub variants: Vec<Variant<'hir>>,
+    pub generics: &'hir hir::Generics,
+    pub attrs: &'hir hir::HirVec<ast::Attribute>,
     pub id: hir::HirId,
     pub whence: Span,
     pub name: Name,
 }
 
-pub struct Variant {
+pub struct Variant<'hir> {
     pub name: Name,
     pub id: hir::HirId,
-    pub attrs: hir::HirVec<ast::Attribute>,
-    pub def: hir::VariantData,
+    pub attrs: &'hir hir::HirVec<ast::Attribute>,
+    pub def: &'hir hir::VariantData,
     pub stab: Option<attr::Stability>,
     pub depr: Option<attr::Deprecation>,
     pub whence: Span,
 }
 
-pub struct Function {
-    pub decl: hir::FnDecl,
-    pub attrs: hir::HirVec<ast::Attribute>,
+pub struct Function<'hir> {
+    pub decl: &'hir hir::FnDecl,
+    pub attrs: &'hir hir::HirVec<ast::Attribute>,
     pub id: hir::HirId,
     pub name: Name,
-    pub vis: hir::Visibility,
+    pub vis: &'hir hir::Visibility,
     pub stab: Option<attr::Stability>,
     pub depr: Option<attr::Deprecation>,
     pub header: hir::FnHeader,
     pub whence: Span,
-    pub generics: hir::Generics,
+    pub generics: &'hir hir::Generics,
     pub body: hir::BodyId,
 }
 
-pub struct Typedef {
-    pub ty: P<hir::Ty>,
-    pub gen: hir::Generics,
+pub struct Typedef<'hir> {
+    pub ty: &'hir P<hir::Ty>,
+    pub gen: &'hir hir::Generics,
     pub name: Name,
     pub id: hir::HirId,
-    pub attrs: hir::HirVec<ast::Attribute>,
+    pub attrs: &'hir hir::HirVec<ast::Attribute>,
     pub whence: Span,
-    pub vis: hir::Visibility,
+    pub vis: &'hir hir::Visibility,
     pub stab: Option<attr::Stability>,
     pub depr: Option<attr::Deprecation>,
 }
 
-pub struct Existential {
-    pub exist_ty: hir::ExistTy,
+pub struct Existential<'hir> {
+    pub exist_ty: &'hir hir::ExistTy,
     pub name: Name,
     pub id: hir::HirId,
-    pub attrs: hir::HirVec<ast::Attribute>,
+    pub attrs: &'hir hir::HirVec<ast::Attribute>,
     pub whence: Span,
-    pub vis: hir::Visibility,
+    pub vis: &'hir hir::Visibility,
     pub stab: Option<attr::Stability>,
     pub depr: Option<attr::Deprecation>,
 }
 
 #[derive(Debug)]
-pub struct Static {
-    pub type_: P<hir::Ty>,
+pub struct Static<'hir> {
+    pub type_: &'hir P<hir::Ty>,
     pub mutability: hir::Mutability,
     pub expr: hir::BodyId,
     pub name: Name,
-    pub attrs: hir::HirVec<ast::Attribute>,
-    pub vis: hir::Visibility,
+    pub attrs: &'hir hir::HirVec<ast::Attribute>,
+    pub vis: &'hir hir::Visibility,
     pub stab: Option<attr::Stability>,
     pub depr: Option<attr::Deprecation>,
     pub id: hir::HirId,
     pub whence: Span,
 }
 
-pub struct Constant {
-    pub type_: P<hir::Ty>,
+pub struct Constant<'hir> {
+    pub type_: &'hir P<hir::Ty>,
     pub expr: hir::BodyId,
     pub name: Name,
-    pub attrs: hir::HirVec<ast::Attribute>,
-    pub vis: hir::Visibility,
+    pub attrs: &'hir hir::HirVec<ast::Attribute>,
+    pub vis: &'hir hir::Visibility,
     pub stab: Option<attr::Stability>,
     pub depr: Option<attr::Deprecation>,
     pub id: hir::HirId,
     pub whence: Span,
 }
 
-pub struct Trait {
+pub struct Trait<'hir> {
     pub is_auto: hir::IsAuto,
     pub unsafety: hir::Unsafety,
     pub name: Name,
-    pub items: hir::HirVec<hir::TraitItem>,
-    pub generics: hir::Generics,
-    pub bounds: hir::HirVec<hir::GenericBound>,
-    pub attrs: hir::HirVec<ast::Attribute>,
+    pub items: Vec<&'hir hir::TraitItem>,
+    pub generics: &'hir hir::Generics,
+    pub bounds: &'hir hir::HirVec<hir::GenericBound>,
+    pub attrs: &'hir hir::HirVec<ast::Attribute>,
     pub id: hir::HirId,
     pub whence: Span,
-    pub vis: hir::Visibility,
+    pub vis: &'hir hir::Visibility,
     pub stab: Option<attr::Stability>,
     pub depr: Option<attr::Deprecation>,
 }
 
-pub struct TraitAlias {
+pub struct TraitAlias<'hir> {
     pub name: Name,
-    pub generics: hir::Generics,
-    pub bounds: hir::HirVec<hir::GenericBound>,
-    pub attrs: hir::HirVec<ast::Attribute>,
+    pub generics: &'hir hir::Generics,
+    pub bounds: &'hir hir::HirVec<hir::GenericBound>,
+    pub attrs: &'hir hir::HirVec<ast::Attribute>,
     pub id: hir::HirId,
     pub whence: Span,
-    pub vis: hir::Visibility,
+    pub vis: &'hir hir::Visibility,
     pub stab: Option<attr::Stability>,
     pub depr: Option<attr::Deprecation>,
 }
 
 #[derive(Debug)]
-pub struct Impl {
+pub struct Impl<'hir> {
     pub unsafety: hir::Unsafety,
     pub polarity: hir::ImplPolarity,
     pub defaultness: hir::Defaultness,
-    pub generics: hir::Generics,
-    pub trait_: Option<hir::TraitRef>,
-    pub for_: P<hir::Ty>,
-    pub items: hir::HirVec<hir::ImplItem>,
-    pub attrs: hir::HirVec<ast::Attribute>,
+    pub generics: &'hir hir::Generics,
+    pub trait_: &'hir Option<hir::TraitRef>,
+    pub for_: &'hir P<hir::Ty>,
+    pub items: Vec<&'hir hir::ImplItem>,
+    pub attrs: &'hir hir::HirVec<ast::Attribute>,
     pub whence: Span,
-    pub vis: hir::Visibility,
+    pub vis: &'hir hir::Visibility,
     pub stab: Option<attr::Stability>,
     pub depr: Option<attr::Deprecation>,
     pub id: hir::HirId,
 }
 
+pub struct ForeignItem<'hir> {
+    pub vis: &'hir hir::Visibility,
+    pub stab: Option<attr::Stability>,
+    pub depr: Option<attr::Deprecation>,
+    pub id: hir::HirId,
+    pub name: Name,
+    pub kind: &'hir hir::ForeignItemKind,
+    pub attrs: &'hir hir::HirVec<ast::Attribute>,
+    pub whence: Span,
+}
+
 // For Macro we store the DefId instead of the NodeId, since we also create
 // these imported macro_rules (which only have a DUMMY_NODE_ID).
-pub struct Macro {
+pub struct Macro<'hir> {
     pub name: Name,
     pub def_id: hir::def_id::DefId,
-    pub attrs: hir::HirVec<ast::Attribute>,
+    pub attrs: &'hir hir::HirVec<ast::Attribute>,
     pub whence: Span,
     pub matchers: hir::HirVec<Span>,
     pub stab: Option<attr::Stability>,
@@ -253,31 +267,31 @@ pub struct Macro {
     pub imported_from: Option<Name>,
 }
 
-pub struct ExternCrate {
+pub struct ExternCrate<'hir> {
     pub name: Name,
     pub cnum: CrateNum,
     pub path: Option<String>,
-    pub vis: hir::Visibility,
-    pub attrs: hir::HirVec<ast::Attribute>,
+    pub vis: &'hir hir::Visibility,
+    pub attrs: &'hir hir::HirVec<ast::Attribute>,
     pub whence: Span,
 }
 
-pub struct Import {
+pub struct Import<'hir> {
     pub name: Name,
     pub id: hir::HirId,
-    pub vis: hir::Visibility,
-    pub attrs: hir::HirVec<ast::Attribute>,
-    pub path: hir::Path,
+    pub vis: &'hir hir::Visibility,
+    pub attrs: &'hir hir::HirVec<ast::Attribute>,
+    pub path: &'hir hir::Path,
     pub glob: bool,
     pub whence: Span,
 }
 
-pub struct ProcMacro {
+pub struct ProcMacro<'hir> {
     pub name: Name,
     pub id: hir::HirId,
     pub kind: MacroKind,
     pub helpers: Vec<Name>,
-    pub attrs: hir::HirVec<ast::Attribute>,
+    pub attrs: &'hir hir::HirVec<ast::Attribute>,
     pub whence: Span,
     pub stab: Option<attr::Stability>,
     pub depr: Option<attr::Deprecation>,
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index ff76579d67d21..c94149d31020a 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -29,8 +29,7 @@ use crate::doctree::*;
 // framework from syntax?.
 
 pub struct RustdocVisitor<'a, 'tcx> {
-    pub module: Module,
-    pub attrs: hir::HirVec<ast::Attribute>,
+    pub module: Option<Module<'tcx>>,
     pub cx: &'a core::DocContext<'tcx>,
     view_item_stack: FxHashSet<hir::HirId>,
     inlining: bool,
@@ -47,8 +46,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         let mut stack = FxHashSet::default();
         stack.insert(hir::CRATE_HIR_ID);
         RustdocVisitor {
-            module: Module::new(None),
-            attrs: hir::HirVec::new(),
+            module: None,
             cx,
             view_item_stack: stack,
             inlining: false,
@@ -77,92 +75,91 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             .and_then(|def_id| self.cx.tcx.lookup_deprecation(def_id))
     }
 
-    pub fn visit(&mut self, krate: &hir::Crate) {
-        self.attrs = krate.attrs.clone();
-
-        self.module = self.visit_mod_contents(krate.span,
-                                              krate.attrs.clone(),
-                                              Spanned { span: syntax_pos::DUMMY_SP,
+    pub fn visit(&mut self, krate: &'tcx hir::Crate) {
+        let mut module = self.visit_mod_contents(krate.span,
+                                              &krate.attrs,
+                                              &Spanned { span: syntax_pos::DUMMY_SP,
                                                         node: hir::VisibilityKind::Public },
                                               hir::CRATE_HIR_ID,
                                               &krate.module,
                                               None);
         // Attach the crate's exported macros to the top-level module:
-        let macro_exports: Vec<_> =
-            krate.exported_macros.iter().map(|def| self.visit_local_macro(def, None)).collect();
-        self.module.macros.extend(macro_exports);
-        self.module.is_crate = true;
+        module.macros.extend(
+            krate.exported_macros.iter().map(|def| self.visit_local_macro(def, None)),
+        );
+        module.is_crate = true;
+        self.module = Some(module);
 
         self.cx.renderinfo.borrow_mut().exact_paths = self.exact_paths.take().unwrap();
     }
 
-    pub fn visit_variant_data(&mut self, item: &hir::Item,
-                              name: ast::Name, sd: &hir::VariantData,
-                              generics: &hir::Generics) -> Struct {
+    pub fn visit_variant_data(&mut self, item: &'tcx hir::Item,
+                              name: ast::Name, sd: &'tcx hir::VariantData,
+                              generics: &'tcx hir::Generics) -> Struct<'tcx> {
         debug!("Visiting struct");
         let struct_type = struct_type_from_def(&*sd);
         Struct {
             id: item.hir_id,
             struct_type,
             name,
-            vis: item.vis.clone(),
+            vis: &item.vis,
             stab: self.stability(item.hir_id),
             depr: self.deprecation(item.hir_id),
-            attrs: item.attrs.clone(),
-            generics: generics.clone(),
-            fields: sd.fields().iter().cloned().collect(),
+            attrs: &item.attrs,
+            generics,
+            fields: sd.fields(),
             whence: item.span
         }
     }
 
-    pub fn visit_union_data(&mut self, item: &hir::Item,
-                            name: ast::Name, sd: &hir::VariantData,
-                            generics: &hir::Generics) -> Union {
+    pub fn visit_union_data(&mut self, item: &'tcx hir::Item,
+                            name: ast::Name, sd: &'tcx hir::VariantData,
+                            generics: &'tcx hir::Generics) -> Union<'tcx> {
         debug!("Visiting union");
         let struct_type = struct_type_from_def(&*sd);
         Union {
             id: item.hir_id,
             struct_type,
             name,
-            vis: item.vis.clone(),
+            vis: &item.vis,
             stab: self.stability(item.hir_id),
             depr: self.deprecation(item.hir_id),
-            attrs: item.attrs.clone(),
-            generics: generics.clone(),
-            fields: sd.fields().iter().cloned().collect(),
+            attrs: &item.attrs,
+            generics,
+            fields: sd.fields(),
             whence: item.span
         }
     }
 
-    pub fn visit_enum_def(&mut self, it: &hir::Item,
-                          name: ast::Name, def: &hir::EnumDef,
-                          params: &hir::Generics) -> Enum {
+    pub fn visit_enum_def(&mut self, it: &'tcx hir::Item,
+                          name: ast::Name, def: &'tcx hir::EnumDef,
+                          generics: &'tcx hir::Generics) -> Enum<'tcx> {
         debug!("Visiting enum");
         Enum {
             name,
             variants: def.variants.iter().map(|v| Variant {
                 name: v.node.ident.name,
                 id: v.node.id,
-                attrs: v.node.attrs.clone(),
+                attrs: &v.node.attrs,
                 stab: self.stability(v.node.id),
                 depr: self.deprecation(v.node.id),
-                def: v.node.data.clone(),
+                def: &v.node.data,
                 whence: v.span,
             }).collect(),
-            vis: it.vis.clone(),
+            vis: &it.vis,
             stab: self.stability(it.hir_id),
             depr: self.deprecation(it.hir_id),
-            generics: params.clone(),
-            attrs: it.attrs.clone(),
+            generics,
+            attrs: &it.attrs,
             id: it.hir_id,
             whence: it.span,
         }
     }
 
-    pub fn visit_fn(&mut self, om: &mut Module, item: &hir::Item,
-                    name: ast::Name, fd: &hir::FnDecl,
+    pub fn visit_fn(&mut self, om: &mut Module<'tcx>, item: &'tcx hir::Item,
+                    name: ast::Name, decl: &'tcx hir::FnDecl,
                     header: hir::FnHeader,
-                    gen: &hir::Generics,
+                    generics: &'tcx hir::Generics,
                     body: hir::BodyId) {
         debug!("Visiting fn");
         let macro_kind = item.attrs.iter().filter_map(|a| {
@@ -208,7 +205,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                     id: item.hir_id,
                     kind,
                     helpers,
-                    attrs: item.attrs.clone(),
+                    attrs: &item.attrs,
                     whence: item.span,
                     stab: self.stability(item.hir_id),
                     depr: self.deprecation(item.hir_id),
@@ -217,14 +214,14 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             None => {
                 om.fns.push(Function {
                     id: item.hir_id,
-                    vis: item.vis.clone(),
+                    vis: &item.vis,
                     stab: self.stability(item.hir_id),
                     depr: self.deprecation(item.hir_id),
-                    attrs: item.attrs.clone(),
-                    decl: fd.clone(),
+                    attrs: &item.attrs,
+                    decl,
                     name,
                     whence: item.span,
-                    generics: gen.clone(),
+                    generics,
                     header,
                     body,
                 });
@@ -232,15 +229,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         }
     }
 
-    pub fn visit_mod_contents(&mut self, span: Span, attrs: hir::HirVec<ast::Attribute>,
-                              vis: hir::Visibility, id: hir::HirId,
-                              m: &hir::Mod,
-                              name: Option<ast::Name>) -> Module {
-        let mut om = Module::new(name);
+    pub fn visit_mod_contents(&mut self, span: Span, attrs: &'tcx hir::HirVec<ast::Attribute>,
+                              vis: &'tcx hir::Visibility, id: hir::HirId,
+                              m: &'tcx hir::Mod,
+                              name: Option<ast::Name>) -> Module<'tcx> {
+        let mut om = Module::new(name, attrs, vis);
         om.where_outer = span;
         om.where_inner = m.inner;
-        om.attrs = attrs;
-        om.vis = vis.clone();
         om.stab = self.stability(id);
         om.depr = self.deprecation(id);
         om.id = self.cx.tcx.hir().hir_to_node_id(id);
@@ -269,7 +264,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                           res: Res,
                           renamed: Option<ast::Ident>,
                           glob: bool,
-                          om: &mut Module,
+                          om: &mut Module<'tcx>,
                           please_inline: bool) -> bool {
 
         fn inherits_doc_hidden(cx: &core::DocContext<'_>, mut node: hir::HirId) -> bool {
@@ -359,14 +354,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 true
             }
             Node::ForeignItem(it) if !glob => {
-                // Generate a fresh `extern {}` block if we want to inline a foreign item.
-                om.foreigns.push(hir::ForeignMod {
-                    abi: tcx.hir().get_foreign_abi(it.hir_id),
-                    items: vec![hir::ForeignItem {
-                        ident: renamed.unwrap_or(it.ident),
-                        .. it.clone()
-                    }].into(),
-                });
+                let prev = mem::replace(&mut self.inlining, true);
+                self.visit_foreign_item(it, renamed, om);
+                self.inlining = prev;
                 true
             }
             Node::MacroDef(def) if !glob => {
@@ -379,8 +369,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         ret
     }
 
-    pub fn visit_item(&mut self, item: &hir::Item,
-                      renamed: Option<ast::Ident>, om: &mut Module) {
+    pub fn visit_item(&mut self, item: &'tcx hir::Item,
+                      renamed: Option<ast::Ident>, om: &mut Module<'tcx>) {
         debug!("Visiting item {:?}", item);
         let ident = renamed.unwrap_or(item.ident);
 
@@ -391,15 +381,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
 
         match item.node {
             hir::ItemKind::ForeignMod(ref fm) => {
-                // If inlining we only want to include public functions.
-                om.foreigns.push(if self.inlining {
-                    hir::ForeignMod {
-                        abi: fm.abi,
-                        items: fm.items.iter().filter(|i| i.vis.node.is_pub()).cloned().collect(),
-                    }
-                } else {
-                    fm.clone()
-                });
+                for item in &fm.items {
+                    self.visit_foreign_item(item, None, om);
+                }
             }
             // If we're inlining, skip private items.
             _ if self.inlining && !item.vis.node.is_pub() => {}
@@ -411,8 +395,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                                 .unwrap_or(LOCAL_CRATE),
                     name: ident.name,
                     path: orig_name.map(|x|x.to_string()),
-                    vis: item.vis.clone(),
-                    attrs: item.attrs.clone(),
+                    vis: &item.vis,
+                    attrs: &item.attrs,
                     whence: item.span,
                 })
             }
@@ -454,17 +438,17 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 om.imports.push(Import {
                     name: ident.name,
                     id: item.hir_id,
-                    vis: item.vis.clone(),
-                    attrs: item.attrs.clone(),
-                    path: (**path).clone(),
+                    vis: &item.vis,
+                    attrs: &item.attrs,
+                    path,
                     glob: is_glob,
                     whence: item.span,
                 });
             }
             hir::ItemKind::Mod(ref m) => {
                 om.mods.push(self.visit_mod_contents(item.span,
-                                                     item.attrs.clone(),
-                                                     item.vis.clone(),
+                                                     &item.attrs,
+                                                     &item.vis,
                                                      item.hir_id,
                                                      m,
                                                      Some(ident.name)));
@@ -479,13 +463,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 self.visit_fn(om, item, ident.name, &**fd, header, gen, body),
             hir::ItemKind::Ty(ref ty, ref gen) => {
                 let t = Typedef {
-                    ty: ty.clone(),
-                    gen: gen.clone(),
+                    ty,
+                    gen,
                     name: ident.name,
                     id: item.hir_id,
-                    attrs: item.attrs.clone(),
+                    attrs: &item.attrs,
                     whence: item.span,
-                    vis: item.vis.clone(),
+                    vis: &item.vis,
                     stab: self.stability(item.hir_id),
                     depr: self.deprecation(item.hir_id),
                 };
@@ -493,75 +477,75 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             },
             hir::ItemKind::Existential(ref exist_ty) => {
                 let t = Existential {
-                    exist_ty: exist_ty.clone(),
+                    exist_ty,
                     name: ident.name,
                     id: item.hir_id,
-                    attrs: item.attrs.clone(),
+                    attrs: &item.attrs,
                     whence: item.span,
-                    vis: item.vis.clone(),
+                    vis: &item.vis,
                     stab: self.stability(item.hir_id),
                     depr: self.deprecation(item.hir_id),
                 };
                 om.existentials.push(t);
             },
-            hir::ItemKind::Static(ref ty, ref mut_, ref exp) => {
+            hir::ItemKind::Static(ref type_, mutability, expr) => {
                 let s = Static {
-                    type_: ty.clone(),
-                    mutability: mut_.clone(),
-                    expr: exp.clone(),
+                    type_,
+                    mutability,
+                    expr,
                     id: item.hir_id,
                     name: ident.name,
-                    attrs: item.attrs.clone(),
+                    attrs: &item.attrs,
                     whence: item.span,
-                    vis: item.vis.clone(),
+                    vis: &item.vis,
                     stab: self.stability(item.hir_id),
                     depr: self.deprecation(item.hir_id),
                 };
                 om.statics.push(s);
             },
-            hir::ItemKind::Const(ref ty, ref exp) => {
+            hir::ItemKind::Const(ref type_, expr) => {
                 let s = Constant {
-                    type_: ty.clone(),
-                    expr: exp.clone(),
+                    type_,
+                    expr,
                     id: item.hir_id,
                     name: ident.name,
-                    attrs: item.attrs.clone(),
+                    attrs: &item.attrs,
                     whence: item.span,
-                    vis: item.vis.clone(),
+                    vis: &item.vis,
                     stab: self.stability(item.hir_id),
                     depr: self.deprecation(item.hir_id),
                 };
                 om.constants.push(s);
             },
-            hir::ItemKind::Trait(is_auto, unsafety, ref gen, ref b, ref item_ids) => {
+            hir::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref item_ids) => {
                 let items = item_ids.iter()
-                                    .map(|ti| self.cx.tcx.hir().trait_item(ti.id).clone())
+                                    .map(|ti| self.cx.tcx.hir().trait_item(ti.id))
                                     .collect();
                 let t = Trait {
                     is_auto,
                     unsafety,
                     name: ident.name,
                     items,
-                    generics: gen.clone(),
-                    bounds: b.iter().cloned().collect(),
+                    generics,
+                    bounds,
                     id: item.hir_id,
-                    attrs: item.attrs.clone(),
+                    attrs: &item.attrs,
                     whence: item.span,
-                    vis: item.vis.clone(),
+                    vis: &item.vis,
                     stab: self.stability(item.hir_id),
                     depr: self.deprecation(item.hir_id),
                 };
                 om.traits.push(t);
             },
-            hir::ItemKind::TraitAlias(ref gen, ref b) => {
+            hir::ItemKind::TraitAlias(ref generics, ref bounds) => {
                 let t = TraitAlias {
                     name: ident.name,
-                    generics: gen.clone(),
-                    bounds: b.iter().cloned().collect(),
+                    generics,
+                    bounds,
                     id: item.hir_id,
-                    attrs: item.attrs.clone(),
+                    attrs: &item.attrs,
                     whence: item.span,
-                    vis: item.vis.clone(),
+                    vis: &item.vis,
                     stab: self.stability(item.hir_id),
                     depr: self.deprecation(item.hir_id),
                 };
@@ -571,28 +555,28 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             hir::ItemKind::Impl(unsafety,
                           polarity,
                           defaultness,
-                          ref gen,
-                          ref tr,
-                          ref ty,
+                          ref generics,
+                          ref trait_,
+                          ref for_,
                           ref item_ids) => {
                 // Don't duplicate impls when inlining or if it's implementing a trait, we'll pick
                 // them up regardless of where they're located.
-                if !self.inlining && tr.is_none() {
+                if !self.inlining && trait_.is_none() {
                     let items = item_ids.iter()
-                                        .map(|ii| self.cx.tcx.hir().impl_item(ii.id).clone())
+                                        .map(|ii| self.cx.tcx.hir().impl_item(ii.id))
                                         .collect();
                     let i = Impl {
                         unsafety,
                         polarity,
                         defaultness,
-                        generics: gen.clone(),
-                        trait_: tr.clone(),
-                        for_: ty.clone(),
+                        generics,
+                        trait_,
+                        for_,
                         items,
-                        attrs: item.attrs.clone(),
+                        attrs: &item.attrs,
                         id: item.hir_id,
                         whence: item.span,
-                        vis: item.vis.clone(),
+                        vis: &item.vis,
                         stab: self.stability(item.hir_id),
                         depr: self.deprecation(item.hir_id),
                     };
@@ -602,12 +586,31 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         }
     }
 
+    fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem,
+                      renamed: Option<ast::Ident>, om: &mut Module<'tcx>) {
+        // If inlining we only want to include public functions.
+        if self.inlining && !item.vis.node.is_pub() {
+            return;
+        }
+
+        om.foreigns.push(ForeignItem {
+            id: item.hir_id,
+            name: renamed.unwrap_or(item.ident).name,
+            kind: &item.node,
+            vis: &item.vis,
+            stab: self.stability(item.hir_id),
+            depr: self.deprecation(item.hir_id),
+            attrs: &item.attrs,
+            whence: item.span
+        });
+    }
+
     // Convert each `exported_macro` into a doc item.
     fn visit_local_macro(
         &self,
-        def: &hir::MacroDef,
+        def: &'tcx hir::MacroDef,
         renamed: Option<ast::Name>
-    ) -> Macro {
+    ) -> Macro<'tcx> {
         debug!("visit_local_macro: {}", def.name);
         let tts = def.body.trees().collect::<Vec<_>>();
         // Extract the spans of all matchers. They represent the "interface" of the macro.
@@ -616,7 +619,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         Macro {
 
             def_id: self.cx.tcx.hir().local_def_id_from_hir_id(def.hir_id),
-            attrs: def.attrs.clone(),
+            attrs: &def.attrs,
             name: renamed.unwrap_or(def.name),
             whence: def.span,
             matchers,
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 55db8da327673..337b84247361d 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -12,6 +12,8 @@
 #![deny(unused_lifetimes)]
 
 #![feature(bind_by_move_pattern_guards)]
+#![feature(const_fn)]
+#![feature(const_transmute)]
 #![feature(crate_visibility_modifier)]
 #![feature(label_break_value)]
 #![feature(nll)]
diff --git a/src/libsyntax/ptr.rs b/src/libsyntax/ptr.rs
index d577243fb3dcd..f0cfa5a84a827 100644
--- a/src/libsyntax/ptr.rs
+++ b/src/libsyntax/ptr.rs
@@ -133,8 +133,15 @@ impl<T: Encodable> Encodable for P<T> {
 }
 
 impl<T> P<[T]> {
-    pub fn new() -> P<[T]> {
-        P { ptr: Default::default() }
+    pub const fn new() -> P<[T]> {
+        // HACK(eddyb) bypass the lack of a `const fn` to create an empty `Box<[T]>`
+        // (as trait methods, `default` in this case, can't be `const fn` yet).
+        P {
+            ptr: unsafe {
+                use std::ptr::NonNull;
+                std::mem::transmute(NonNull::<[T; 0]>::dangling() as NonNull<[T]>)
+            },
+        }
     }
 
     #[inline(never)]
diff --git a/src/test/ui/issues/issue-4736.stderr b/src/test/ui/issues/issue-4736.stderr
index b4ac12643bcac..257ec914a61ca 100644
--- a/src/test/ui/issues/issue-4736.stderr
+++ b/src/test/ui/issues/issue-4736.stderr
@@ -1,8 +1,13 @@
 error[E0560]: struct `NonCopyable` has no field named `p`
   --> $DIR/issue-4736.rs:4:26
    |
+LL | struct NonCopyable(());
+   |        ----------- `NonCopyable` defined here
+...
 LL |     let z = NonCopyable{ p: () };
-   |                          ^ help: a field with a similar name exists: `0`
+   |             -----------  ^ field does not exist
+   |             |
+   |             `NonCopyable` is a tuple struct, use the appropriate syntax: `NonCopyable(/* fields */)`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/numeric/numeric-fields.stderr b/src/test/ui/numeric/numeric-fields.stderr
index 13c18d740fc1c..5202393f559c9 100644
--- a/src/test/ui/numeric/numeric-fields.stderr
+++ b/src/test/ui/numeric/numeric-fields.stderr
@@ -1,10 +1,13 @@
 error[E0560]: struct `S` has no field named `0b1`
   --> $DIR/numeric-fields.rs:4:15
    |
+LL | struct S(u8, u16);
+   |        - `S` defined here
+...
 LL |     let s = S{0b1: 10, 0: 11};
-   |               ^^^ `S` does not have this field
-   |
-   = note: available fields are: `0`, `1`
+   |             - ^^^ field does not exist
+   |             |
+   |             `S` is a tuple struct, use the appropriate syntax: `S(/* fields */)`
 
 error[E0026]: struct `S` does not have a field named `0x1`
   --> $DIR/numeric-fields.rs:7:17