From 778d5f2074b05c013e15fabc25daf4e37a174bf7 Mon Sep 17 00:00:00 2001
From: Clar Charr <clar@charr.xyz>
Date: Sat, 9 Sep 2017 16:48:40 -0400
Subject: [PATCH 01/24] Add Cow<str> -> Box<Error> impls.

---
 src/libstd/error.rs | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/src/libstd/error.rs b/src/libstd/error.rs
index 401552a6ec417..6d64ea0d50332 100644
--- a/src/libstd/error.rs
+++ b/src/libstd/error.rs
@@ -53,6 +53,7 @@
 
 use alloc::allocator;
 use any::TypeId;
+use borrow::Cow;
 use cell;
 use char;
 use fmt::{self, Debug, Display};
@@ -217,6 +218,20 @@ impl<'a> From<&'a str> for Box<Error> {
     }
 }
 
+#[stable(feature = "cow_box_error", since = "1.22.0")]
+impl<'a, 'b> From<Cow<'b, str>> for Box<Error + Send + Sync + 'a> {
+    fn from(err: Cow<'b, str>) -> Box<Error + Send + Sync + 'a> {
+        From::from(String::from(err))
+    }
+}
+
+#[stable(feature = "cow_box_error", since = "1.22.0")]
+impl<'a> From<Cow<'a, str>> for Box<Error> {
+    fn from(err: Cow<'a, str>) -> Box<Error> {
+        From::from(String::from(err))
+    }
+}
+
 #[unstable(feature = "never_type_impls", issue = "35121")]
 impl Error for ! {
     fn description(&self) -> &str { *self }

From edf1622bb4f3bd2ba8c8cd13c12a22e7d776120f Mon Sep 17 00:00:00 2001
From: oyvindln <oyvindln@users.noreply.github.com>
Date: Wed, 13 Sep 2017 20:11:02 +0200
Subject: [PATCH 02/24] Add proper help line for inline threshold

Also remove a period on a different help line for consistency
---
 src/librustc/session/config.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 59f600f39077c..a4b13bb2f4dbc 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -905,7 +905,7 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
     debug_assertions: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "explicitly enable the cfg(debug_assertions) directive"),
     inline_threshold: Option<usize> = (None, parse_opt_uint, [TRACKED],
-        "set the inlining threshold for"),
+        "set the threshold for inlining a function (default: 225)"),
     panic: Option<PanicStrategy> = (None, parse_panic_strategy,
         [TRACKED], "panic strategy to compile crate with"),
 }
@@ -1052,7 +1052,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
     linker_flavor: Option<LinkerFlavor> = (None, parse_linker_flavor, [UNTRACKED],
                                            "Linker flavor"),
     fuel: Option<(String, u64)> = (None, parse_optimization_fuel, [TRACKED],
-        "Set the optimization fuel quota for a crate."),
+        "Set the optimization fuel quota for a crate"),
     print_fuel: Option<String> = (None, parse_opt_string, [TRACKED],
         "Make Rustc print the total optimization fuel used by a crate."),
     remap_path_prefix_from: Vec<String> = (vec![], parse_string_push, [TRACKED],

From e89748e54f059e72b4ab4b6948a992f273c64cc6 Mon Sep 17 00:00:00 2001
From: oyvindln <oyvindln@users.noreply.github.com>
Date: Wed, 13 Sep 2017 22:50:47 +0200
Subject: [PATCH 03/24] Remove the other period and start with lowercase for
 more consistency

---
 src/librustc/session/config.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index a4b13bb2f4dbc..4cc2a087d81b5 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -1052,9 +1052,9 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
     linker_flavor: Option<LinkerFlavor> = (None, parse_linker_flavor, [UNTRACKED],
                                            "Linker flavor"),
     fuel: Option<(String, u64)> = (None, parse_optimization_fuel, [TRACKED],
-        "Set the optimization fuel quota for a crate"),
+        "set the optimization fuel quota for a crate"),
     print_fuel: Option<String> = (None, parse_opt_string, [TRACKED],
-        "Make Rustc print the total optimization fuel used by a crate."),
+        "make Rustc print the total optimization fuel used by a crate"),
     remap_path_prefix_from: Vec<String> = (vec![], parse_string_push, [TRACKED],
         "add a source pattern to the file path remapping config"),
     remap_path_prefix_to: Vec<String> = (vec![], parse_string_push, [TRACKED],

From 7859c9ef442055c477e7788a74f971ac68e8bd67 Mon Sep 17 00:00:00 2001
From: Ulrik Sverdrup <bluss@users.noreply.github.com>
Date: Sun, 17 Sep 2017 10:19:11 +0200
Subject: [PATCH 04/24] std: Document thread builder panics for nul bytes in
 thread names

This seems to have been undocumented. Mention this where the name is set
(Builder::name) and where the panic could happen (Builder::spawn).

Thread::new is private and I think the builder is the only user where
this matters. A short comment was added to "document" Thread::new too.
---
 src/libstd/thread/mod.rs | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs
index 4912ff93abdb3..a084c7fbce157 100644
--- a/src/libstd/thread/mod.rs
+++ b/src/libstd/thread/mod.rs
@@ -287,6 +287,8 @@ impl Builder {
     /// Names the thread-to-be. Currently the name is used for identification
     /// only in panic messages.
     ///
+    /// The name must not contain null bytes (`\0`).
+    ///
     /// For more information about named threads, see
     /// [this module-level documentation][naming-threads].
     ///
@@ -355,6 +357,10 @@ impl Builder {
     /// [`io::Result`]: ../../std/io/type.Result.html
     /// [`JoinHandle`]: ../../std/thread/struct.JoinHandle.html
     ///
+    /// # Panics
+    ///
+    /// Panics if a thread name was set and it contained null bytes.
+    ///
     /// # Examples
     ///
     /// ```
@@ -941,6 +947,7 @@ pub struct Thread {
 
 impl Thread {
     // Used only internally to construct a thread object without spawning
+    // Panics if the name contains nuls.
     pub(crate) fn new(name: Option<String>) -> Thread {
         let cname = name.map(|n| {
             CString::new(n).expect("thread name may not contain interior null bytes")

From 7b932d2e127b3b694e8cd2a6ae30d78cc3436547 Mon Sep 17 00:00:00 2001
From: Michal Budzynski <budziq@gmail.com>
Date: Sun, 17 Sep 2017 01:42:15 +0200
Subject: [PATCH 05/24] stabilized vec_splice (fixes #32310)

---
 .../unstable-book/src/library-features/splice.md    |  6 +++---
 src/liballoc/vec.rs                                 | 13 ++++++-------
 2 files changed, 9 insertions(+), 10 deletions(-)

diff --git a/src/doc/unstable-book/src/library-features/splice.md b/src/doc/unstable-book/src/library-features/splice.md
index dae4475257a02..f2d32c8803876 100644
--- a/src/doc/unstable-book/src/library-features/splice.md
+++ b/src/doc/unstable-book/src/library-features/splice.md
@@ -6,8 +6,8 @@ The tracking issue for this feature is: [#32310]
 
 ------------------------
 
-The `splice()` method on `Vec` and `String` allows you to replace a range
-of values in a vector or string with another range of values, and returns
+The `splice()` method on `String` allows you to replace a range
+of values in a string with another range of values, and returns
 the replaced values.
 
 A simple example:
@@ -20,4 +20,4 @@ let beta_offset = s.find('β').unwrap_or(s.len());
 // Replace the range up until the β from the string
 s.splice(..beta_offset, "Α is capital alpha; ");
 assert_eq!(s, "Α is capital alpha; β is beta");
-```
\ No newline at end of file
+```
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs
index 45574bad9ac07..75d54b8207606 100644
--- a/src/liballoc/vec.rs
+++ b/src/liballoc/vec.rs
@@ -1943,7 +1943,6 @@ impl<T> Vec<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(splice)]
     /// let mut v = vec![1, 2, 3];
     /// let new = [7, 8];
     /// let u: Vec<_> = v.splice(..2, new.iter().cloned()).collect();
@@ -1951,7 +1950,7 @@ impl<T> Vec<T> {
     /// assert_eq!(u, &[1, 2]);
     /// ```
     #[inline]
-    #[unstable(feature = "splice", reason = "recently added", issue = "32310")]
+    #[stable(feature = "vec_splice", since = "1.22.0")]
     pub fn splice<R, I>(&mut self, range: R, replace_with: I) -> Splice<I::IntoIter>
         where R: RangeArgument<usize>, I: IntoIterator<Item=T>
     {
@@ -2554,13 +2553,13 @@ impl<'a, T> InPlace<T> for PlaceBack<'a, T> {
 /// [`splice()`]: struct.Vec.html#method.splice
 /// [`Vec`]: struct.Vec.html
 #[derive(Debug)]
-#[unstable(feature = "splice", reason = "recently added", issue = "32310")]
+#[stable(feature = "vec_splice", since = "1.22.0")]
 pub struct Splice<'a, I: Iterator + 'a> {
     drain: Drain<'a, I::Item>,
     replace_with: I,
 }
 
-#[unstable(feature = "splice", reason = "recently added", issue = "32310")]
+#[stable(feature = "vec_splice", since = "1.22.0")]
 impl<'a, I: Iterator> Iterator for Splice<'a, I> {
     type Item = I::Item;
 
@@ -2573,18 +2572,18 @@ impl<'a, I: Iterator> Iterator for Splice<'a, I> {
     }
 }
 
-#[unstable(feature = "splice", reason = "recently added", issue = "32310")]
+#[stable(feature = "vec_splice", since = "1.22.0")]
 impl<'a, I: Iterator> DoubleEndedIterator for Splice<'a, I> {
     fn next_back(&mut self) -> Option<Self::Item> {
         self.drain.next_back()
     }
 }
 
-#[unstable(feature = "splice", reason = "recently added", issue = "32310")]
+#[stable(feature = "vec_splice", since = "1.22.0")]
 impl<'a, I: Iterator> ExactSizeIterator for Splice<'a, I> {}
 
 
-#[unstable(feature = "splice", reason = "recently added", issue = "32310")]
+#[stable(feature = "vec_splice", since = "1.22.0")]
 impl<'a, I: Iterator> Drop for Splice<'a, I> {
     fn drop(&mut self) {
         // exhaust drain first

From 6b167f98d9dcfef79519d79d03930062215158fc Mon Sep 17 00:00:00 2001
From: Michal Budzynski <budziq@gmail.com>
Date: Sun, 17 Sep 2017 10:41:24 +0200
Subject: [PATCH 06/24] Updated tracking issue for String::splice and its
 unstable-book entry

---
 src/doc/unstable-book/src/library-features/splice.md | 7 +++----
 src/liballoc/string.rs                               | 2 +-
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/src/doc/unstable-book/src/library-features/splice.md b/src/doc/unstable-book/src/library-features/splice.md
index f2d32c8803876..2e4bb1a5257c9 100644
--- a/src/doc/unstable-book/src/library-features/splice.md
+++ b/src/doc/unstable-book/src/library-features/splice.md
@@ -1,14 +1,13 @@
 # `splice`
 
-The tracking issue for this feature is: [#32310]
+The tracking issue for this feature is: [#44643]
 
-[#32310]: https://github.com/rust-lang/rust/issues/32310
+[#44643]: https://github.com/rust-lang/rust/issues/44643
 
 ------------------------
 
 The `splice()` method on `String` allows you to replace a range
-of values in a string with another range of values, and returns
-the replaced values.
+of values in a string with another range of values.
 
 A simple example:
 
diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs
index 46b96df1eabd7..6d0bb264df186 100644
--- a/src/liballoc/string.rs
+++ b/src/liballoc/string.rs
@@ -1451,7 +1451,7 @@ impl String {
     /// s.splice(..beta_offset, "Α is capital alpha; ");
     /// assert_eq!(s, "Α is capital alpha; β is beta");
     /// ```
-    #[unstable(feature = "splice", reason = "recently added", issue = "32310")]
+    #[unstable(feature = "splice", reason = "recently added", issue = "44643")]
     pub fn splice<R>(&mut self, range: R, replace_with: &str)
         where R: RangeArgument<usize>
     {

From 2633b85ab2c89822d2c227fc9e81c6ec1c0ed9b6 Mon Sep 17 00:00:00 2001
From: Ixrec <ericrhitchcock@gmail.com>
Date: Sun, 17 Sep 2017 17:03:56 +0100
Subject: [PATCH 07/24] Replace str's transmute() calls with pointer casts

After the following conversation in #rust-lang:
```
[14:43:50] <Ixrec> TIL the implementation of from_utf_unchecked is literally just "mem::transmute(x)"
[14:43:59] <Ixrec> no wonder people keep saying transmute is overpowered
[15:15:30] <eddyb> Ixrec: it should be a pointer cast lol
[15:15:46] <eddyb> unless it doesn't let you
[16:50:34] <Ixrec> https://play.rust-lang.org/?gist=d1e6b629ad9ec1baf64ce261c63845e6&version=stable seems like it does let me
[16:52:35] <eddyb> Ixrec: yeah that's the preferred impl
[16:52:46] <eddyb> Ixrec: it just wasn't in 1.0
[16:52:50] <eddyb> IIRC
[16:53:00] <eddyb> (something something fat pointers)
```
Since I already wrote half of the preferred impls in the playground, might as well make an actual PR.
---
 src/libcore/str/mod.rs | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index d4fef45ae4e8f..60f3640446cab 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -404,7 +404,7 @@ unsafe fn from_raw_parts_mut<'a>(p: *mut u8, len: usize) -> &'a mut str {
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub unsafe fn from_utf8_unchecked(v: &[u8]) -> &str {
-    mem::transmute(v)
+    &*(v as *const [u8] as *const str)
 }
 
 /// Converts a slice of bytes to a string slice without checking
@@ -429,7 +429,7 @@ pub unsafe fn from_utf8_unchecked(v: &[u8]) -> &str {
 #[inline]
 #[stable(feature = "str_mut_extras", since = "1.20.0")]
 pub unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str {
-    mem::transmute(v)
+    &*(v as *mut [u8] as *mut str)
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -2447,12 +2447,12 @@ impl StrExt for str {
 
     #[inline]
     fn as_bytes(&self) -> &[u8] {
-        unsafe { mem::transmute(self) }
+        unsafe { &*(self as *const str as *const [u8]) }
     }
 
     #[inline]
     unsafe fn as_bytes_mut(&mut self) -> &mut [u8] {
-        mem::transmute(self)
+        &mut *(self as *mut str as *mut [u8])
     }
 
     fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> {

From 38fa340ba263612a6f7351d4800d6d4f57ac1cdf Mon Sep 17 00:00:00 2001
From: Ixrec <ericrhitchcock@gmail.com>
Date: Sun, 17 Sep 2017 17:11:42 +0100
Subject: [PATCH 08/24] missed a 'mut'

---
 src/libcore/str/mod.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 60f3640446cab..862085c7228af 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -429,7 +429,7 @@ pub unsafe fn from_utf8_unchecked(v: &[u8]) -> &str {
 #[inline]
 #[stable(feature = "str_mut_extras", since = "1.20.0")]
 pub unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str {
-    &*(v as *mut [u8] as *mut str)
+    &mut *(v as *mut [u8] as *mut str)
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]

From 2787a285bd211ecbf75fd95d990226242005d848 Mon Sep 17 00:00:00 2001
From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
Date: Wed, 13 Sep 2017 12:20:39 +0200
Subject: [PATCH 09/24] Add `<*const T>::align_offset` and use it in `memchr`

---
 src/libcore/intrinsics.rs       | 33 +--------------
 src/libcore/ptr.rs              | 75 ++++++++++++++++++++++++++++++++-
 src/libcore/str/mod.rs          |  3 +-
 src/libstd/lib.rs               |  1 +
 src/libstd/sys_common/memchr.rs |  9 ++--
 5 files changed, 80 insertions(+), 41 deletions(-)

diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index f7f1dd12d28b1..bc82f0230e5b4 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -1381,38 +1381,7 @@ extern "rust-intrinsic" {
 }
 
 #[cfg(stage0)]
-/// Computes the byte offset that needs to be applied to `ptr` in order to
-/// make it aligned to `align`.
-/// If it is not possible to align `ptr`, the implementation returns
-/// `usize::max_value()`.
-///
-/// There are no guarantees whatsover that offsetting the pointer will not
-/// overflow or go beyond the allocation that `ptr` points into.
-/// It is up to the caller to ensure that the returned offset is correct
-/// in all terms other than alignment.
-///
-/// # Examples
-///
-/// Accessing adjacent `u8` as `u16`
-///
-/// ```
-/// # #![feature(core_intrinsics)]
-/// # fn foo(n: usize) {
-/// # use std::intrinsics::align_offset;
-/// # use std::mem::align_of;
-/// # unsafe {
-/// let x = [5u8, 6u8, 7u8, 8u8, 9u8];
-/// let ptr = &x[n] as *const u8;
-/// let offset = align_offset(ptr as *const (), align_of::<u16>());
-/// if offset < x.len() - n - 1 {
-///     let u16_ptr = ptr.offset(offset as isize) as *const u16;
-///     assert_ne!(*u16_ptr, 500);
-/// } else {
-///     // while the pointer can be aligned via `offset`, it would point
-///     // outside the allocation
-/// }
-/// # } }
-/// ```
+/// remove me after the next release
 pub unsafe fn align_offset(ptr: *const (), align: usize) -> usize {
     let offset = ptr as usize % align;
     if offset == 0 {
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index dd01534ec02d9..4041a3760e5ca 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -1064,7 +1064,43 @@ impl<T: ?Sized> *const T {
         copy_nonoverlapping(self, dest, count)
     }
 
-
+    /// Computes the byte offset that needs to be applied in order to
+    /// make the pointer aligned to `align`.
+    /// If it is not possible to align the pointer, the implementation returns
+    /// `usize::max_value()`.
+    ///
+    /// There are no guarantees whatsover that offsetting the pointer will not
+    /// overflow or go beyond the allocation that the pointer points into.
+    /// It is up to the caller to ensure that the returned offset is correct
+    /// in all terms other than alignment.
+    ///
+    /// # Examples
+    ///
+    /// Accessing adjacent `u8` as `u16`
+    ///
+    /// ```
+    /// # #![feature(align_offset)]
+    /// # fn foo(n: usize) {
+    /// # use std::mem::align_of;
+    /// # unsafe {
+    /// let x = [5u8, 6u8, 7u8, 8u8, 9u8];
+    /// let ptr = &x[n] as *const u8;
+    /// let offset = ptr.align_offset(align_of::<u16>());
+    /// if offset < x.len() - n - 1 {
+    ///     let u16_ptr = ptr.offset(offset as isize) as *const u16;
+    ///     assert_ne!(*u16_ptr, 500);
+    /// } else {
+    ///     // while the pointer can be aligned via `offset`, it would point
+    ///     // outside the allocation
+    /// }
+    /// # } }
+    /// ```
+    #[unstable(feature = "align_offset", issue = "44488")]
+    pub fn align_offset(self, align: usize) -> usize {
+        unsafe {
+            intrinsics::align_offset(self as *const _, align)
+        }
+    }
 }
 
 #[lang = "mut_ptr"]
@@ -1284,6 +1320,43 @@ impl<T: ?Sized> *mut T {
         }
     }
 
+    /// Computes the byte offset that needs to be applied in order to
+    /// make the pointer aligned to `align`.
+    /// If it is not possible to align the pointer, the implementation returns
+    /// `usize::max_value()`.
+    ///
+    /// There are no guarantees whatsover that offsetting the pointer will not
+    /// overflow or go beyond the allocation that the pointer points into.
+    /// It is up to the caller to ensure that the returned offset is correct
+    /// in all terms other than alignment.
+    ///
+    /// # Examples
+    ///
+    /// Accessing adjacent `u8` as `u16`
+    ///
+    /// ```
+    /// # #![feature(align_offset)]
+    /// # fn foo(n: usize) {
+    /// # use std::mem::align_of;
+    /// # unsafe {
+    /// let x = [5u8, 6u8, 7u8, 8u8, 9u8];
+    /// let ptr = &x[n] as *const u8;
+    /// let offset = ptr.align_offset(align_of::<u16>());
+    /// if offset < x.len() - n - 1 {
+    ///     let u16_ptr = ptr.offset(offset as isize) as *const u16;
+    ///     assert_ne!(*u16_ptr, 500);
+    /// } else {
+    ///     // while the pointer can be aligned via `offset`, it would point
+    ///     // outside the allocation
+    /// }
+    /// # } }
+    /// ```
+    #[unstable(feature = "align_offset", issue = "44488")]
+    pub fn align_offset(self, align: usize) -> usize {
+        unsafe {
+            intrinsics::align_offset(self as *const _, align)
+        }
+    }
 
     /// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).
     ///
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index d4fef45ae4e8f..0d907d11cfba1 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -23,7 +23,6 @@ use fmt;
 use iter::{Map, Cloned, FusedIterator};
 use slice::{self, SliceIndex};
 use mem;
-use intrinsics::align_offset;
 
 pub mod pattern;
 
@@ -1515,7 +1514,7 @@ fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> {
             let ptr = v.as_ptr();
             let align = unsafe {
                 // the offset is safe, because `index` is guaranteed inbounds
-                align_offset(ptr.offset(index as isize) as *const (), usize_bytes)
+                ptr.offset(index as isize).align_offset(usize_bytes)
             };
             if align == 0 {
                 while index < blocks_end {
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 1a0f8b8d2177e..a3eecd46e9051 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -242,6 +242,7 @@
 #![feature(allocator_internals)]
 #![feature(allow_internal_unsafe)]
 #![feature(allow_internal_unstable)]
+#![feature(align_offset)]
 #![feature(asm)]
 #![feature(box_syntax)]
 #![feature(cfg_target_has_atomic)]
diff --git a/src/libstd/sys_common/memchr.rs b/src/libstd/sys_common/memchr.rs
index 3824a5fb5284c..50f998eb4867d 100644
--- a/src/libstd/sys_common/memchr.rs
+++ b/src/libstd/sys_common/memchr.rs
@@ -65,15 +65,12 @@ pub mod fallback {
         let usize_bytes = mem::size_of::<usize>();
 
         // search up to an aligned boundary
-        let align = (ptr as usize) & (usize_bytes- 1);
-        let mut offset;
-        if align > 0 {
-            offset = cmp::min(usize_bytes - align, len);
+        let mut offset = ptr.align_offset(usize_bytes);
+        if offset > 0 {
+            offset = cmp::min(offset, len);
             if let Some(index) = text[..offset].iter().position(|elt| *elt == x) {
                 return Some(index);
             }
-        } else {
-            offset = 0;
         }
 
         // search the body of the text

From e47279f51212a749d7cfe1d38a27f10a842d97a5 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Sun, 17 Sep 2017 22:11:37 +0200
Subject: [PATCH 10/24] Add more links and put the link character to the left

---
 src/librustdoc/html/render.rs          |  8 +++++---
 src/librustdoc/html/static/rustdoc.css | 12 ++++++++++--
 2 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index c09ce4c4bd31a..bf0fe5f6e9d98 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -2671,8 +2671,9 @@ fn item_struct(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
                 let ns_id = derive_id(format!("{}.{}",
                                               field.name.as_ref().unwrap(),
                                               ItemType::StructField.name_space()));
-                write!(w, "<span id='{id}' class=\"{item_type}\">
-                           <span id='{ns_id}' class='invisible'>
+                write!(w, "<span id=\"{id}\" class=\"{item_type} small-section-header\">
+                           <a href=\"#{id}\" class=\"anchor field\"></a>
+                           <span id=\"{ns_id}\" class='invisible'>
                            <code>{name}: {ty}</code>
                            </span></span>",
                        item_type = ItemType::StructField,
@@ -2793,7 +2794,8 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
             let ns_id = derive_id(format!("{}.{}",
                                           variant.name.as_ref().unwrap(),
                                           ItemType::Variant.name_space()));
-            write!(w, "<span id='{id}' class='variant'>\
+            write!(w, "<span id=\"{id}\" class=\"variant small-section-header\">\
+                       <a href=\"#{id}\" class=\"anchor field\"></a>\
                        <span id='{ns_id}' class='invisible'><code>{name}",
                    id = id,
                    ns_id = ns_id,
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index c15051376bf27..50c0424aa5fcc 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -288,6 +288,7 @@ nav.sub {
 
 .docblock {
 	margin-left: 24px;
+	position: relative;
 }
 
 .content .out-of-band {
@@ -456,8 +457,13 @@ a {
 }
 .anchor {
 	display: none;
+	position: absolute;
+	left: -25px;
 }
-.anchor:after {
+.anchor.field {
+	left: -20px;
+}
+.anchor:before {
 	content: '\2002\00a7\2002';
 }
 
@@ -625,7 +631,9 @@ a.test-arrow:hover{
 	text-decoration: none;
 }
 
-.section-header:hover a:after {
+.section-header:hover a:before {
+	position: absolute;
+	left: -25px;
 	content: '\2002\00a7\2002';
 }
 

From ebd0e4f1996053c1d63709b169682ee8586ae65f Mon Sep 17 00:00:00 2001
From: Will Speak <lithiumflame@gmail.com>
Date: Mon, 18 Sep 2017 07:38:32 +0100
Subject: [PATCH 11/24] Add Example of `IntoIterator` as Trait Bound to Docs

Part of #44600.
---
 src/libcore/iter/traits.rs | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs
index 2af129a67bddf..7ef50396c82bf 100644
--- a/src/libcore/iter/traits.rs
+++ b/src/libcore/iter/traits.rs
@@ -196,6 +196,23 @@ pub trait FromIterator<A>: Sized {
 ///     assert_eq!(i as i32, n);
 /// }
 /// ```
+///
+/// It is common to use `IntoIterator` as a trait bound. This allows
+/// the input collection type to change, so long as it is still an
+/// iterator. Additional bounds can be specified by restricting on
+/// `Item`:
+///
+/// ```rust
+/// fn collect_as_strings<T>(collection: T) -> Vec<String>
+///     where T: IntoIterator,
+///           T::Item : std::fmt::Debug,
+/// {
+///     collection
+///         .into_iter()
+///         .map(|item| format!("{:?}", item))
+///         .collect()
+/// }
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait IntoIterator {
     /// The type of the elements being iterated over.

From 3cf28f3002470f61a471c69b869e4f55ae1766f7 Mon Sep 17 00:00:00 2001
From: Michael Woerister <michaelwoerister@posteo>
Date: Tue, 15 Aug 2017 17:05:25 +0200
Subject: [PATCH 12/24] Use DefId instead of NodeId as identifier in
 resolve_lifetime::Region.

These Region values end up in crate metadata so they should not use NodeId.
---
 .../error_reporting/different_lifetimes.rs    | 12 ++---
 src/librustc/middle/resolve_lifetime.rs       | 50 ++++++++++++-------
 src/librustc_typeck/astconv.rs                | 16 +++---
 src/librustdoc/clean/mod.rs                   |  3 +-
 src/librustdoc/core.rs                        |  6 +--
 5 files changed, 52 insertions(+), 35 deletions(-)

diff --git a/src/librustc/infer/error_reporting/different_lifetimes.rs b/src/librustc/infer/error_reporting/different_lifetimes.rs
index 536715ffadb15..ef28b5b42b0dd 100644
--- a/src/librustc/infer/error_reporting/different_lifetimes.rs
+++ b/src/librustc/infer/error_reporting/different_lifetimes.rs
@@ -245,10 +245,8 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindNestedTypeVisitor<'a, 'gcx, 'tcx> {
                     // region at the right depth with the same index
                     (Some(rl::Region::EarlyBound(_, id)), ty::BrNamed(def_id, _)) => {
                         debug!("EarlyBound self.infcx.tcx.hir.local_def_id(id)={:?} \
-                                        def_id={:?}",
-                               self.infcx.tcx.hir.local_def_id(id),
-                               def_id);
-                        if self.infcx.tcx.hir.local_def_id(id) == def_id {
+                                        def_id={:?}", id, def_id);
+                        if id == def_id {
                             self.found_type = Some(arg);
                             return; // we can stop visiting now
                         }
@@ -260,11 +258,9 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindNestedTypeVisitor<'a, 'gcx, 'tcx> {
                     (Some(rl::Region::LateBound(debruijn_index, id)), ty::BrNamed(def_id, _)) => {
                         debug!("FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}",
                                debruijn_index.depth);
-                        debug!("self.infcx.tcx.hir.local_def_id(id)={:?}",
-                               self.infcx.tcx.hir.local_def_id(id));
+                        debug!("self.infcx.tcx.hir.local_def_id(id)={:?}", id);
                         debug!("def_id={:?}", def_id);
-                        if debruijn_index.depth == self.depth &&
-                           self.infcx.tcx.hir.local_def_id(id) == def_id {
+                        if debruijn_index.depth == self.depth && id == def_id {
                             self.found_type = Some(arg);
                             return; // we can stop visiting now
                         }
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index 657c30289ebb5..2d201e5935ec7 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -39,22 +39,24 @@ use hir::intravisit::{self, Visitor, NestedVisitorMap};
 #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
 pub enum Region {
     Static,
-    EarlyBound(/* index */ u32, /* lifetime decl */ ast::NodeId),
-    LateBound(ty::DebruijnIndex, /* lifetime decl */ ast::NodeId),
+    EarlyBound(/* index */ u32, /* lifetime decl */ DefId),
+    LateBound(ty::DebruijnIndex, /* lifetime decl */ DefId),
     LateBoundAnon(ty::DebruijnIndex, /* anon index */ u32),
-    Free(DefId, /* lifetime decl */ ast::NodeId),
+    Free(DefId, /* lifetime decl */ DefId),
 }
 
 impl Region {
-    fn early(index: &mut u32, def: &hir::LifetimeDef) -> (ast::Name, Region) {
+    fn early(hir_map: &Map, index: &mut u32, def: &hir::LifetimeDef) -> (ast::Name, Region) {
         let i = *index;
         *index += 1;
-        (def.lifetime.name, Region::EarlyBound(i, def.lifetime.id))
+        let def_id = hir_map.local_def_id(def.lifetime.id);
+        (def.lifetime.name, Region::EarlyBound(i, def_id))
     }
 
-    fn late(def: &hir::LifetimeDef) -> (ast::Name, Region) {
+    fn late(hir_map: &Map, def: &hir::LifetimeDef) -> (ast::Name, Region) {
         let depth = ty::DebruijnIndex::new(1);
-        (def.lifetime.name, Region::LateBound(depth, def.lifetime.id))
+        let def_id = hir_map.local_def_id(def.lifetime.id);
+        (def.lifetime.name, Region::LateBound(depth, def_id))
     }
 
     fn late_anon(index: &Cell<u32>) -> Region {
@@ -64,7 +66,7 @@ impl Region {
         Region::LateBoundAnon(depth, i)
     }
 
-    fn id(&self) -> Option<ast::NodeId> {
+    fn id(&self) -> Option<DefId> {
         match *self {
             Region::Static |
             Region::LateBoundAnon(..) => None,
@@ -337,7 +339,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                     0
                 };
                 let lifetimes = generics.lifetimes.iter().map(|def| {
-                    Region::early(&mut index, def)
+                    Region::early(self.hir_map, &mut index, def)
                 }).collect();
                 let scope = Scope::Binder {
                     lifetimes,
@@ -368,7 +370,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
         match ty.node {
             hir::TyBareFn(ref c) => {
                 let scope = Scope::Binder {
-                    lifetimes: c.lifetimes.iter().map(Region::late).collect(),
+                    lifetimes: c.lifetimes.iter().map(|def| {
+                            Region::late(self.hir_map, def)
+                        }).collect(),
                     s: self.scope
                 };
                 self.with(scope, |old_scope, this| {
@@ -467,7 +471,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                     if !bound_lifetimes.is_empty() {
                         self.trait_ref_hack = true;
                         let scope = Scope::Binder {
-                            lifetimes: bound_lifetimes.iter().map(Region::late).collect(),
+                            lifetimes: bound_lifetimes.iter().map(|def| {
+                                    Region::late(self.hir_map, def)
+                                }).collect(),
                             s: self.scope
                         };
                         let result = self.with(scope, |old_scope, this| {
@@ -512,7 +518,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                           "nested quantification of lifetimes");
             }
             let scope = Scope::Binder {
-                lifetimes: trait_ref.bound_lifetimes.iter().map(Region::late).collect(),
+                lifetimes: trait_ref.bound_lifetimes.iter().map(|def| {
+                        Region::late(self.hir_map, def)
+                    }).collect(),
                 s: self.scope
             };
             self.with(scope, |old_scope, this| {
@@ -647,10 +655,13 @@ fn extract_labels(ctxt: &mut LifetimeContext, body: &hir::Body) {
                 Scope::Binder { ref lifetimes, s } => {
                     // FIXME (#24278): non-hygienic comparison
                     if let Some(def) = lifetimes.get(&label) {
+                        let node_id = hir_map.as_local_node_id(def.id().unwrap())
+                                             .unwrap();
+
                         signal_shadowing_problem(
                             sess,
                             label,
-                            original_lifetime(hir_map.span(def.id().unwrap())),
+                            original_lifetime(hir_map.span(node_id)),
                             shadower_label(label_span));
                         return;
                     }
@@ -749,7 +760,8 @@ fn object_lifetime_defaults_for_item(hir_map: &Map, generics: &hir::Generics)
                     generics.lifetimes.iter().enumerate().find(|&(_, def)| {
                         def.lifetime.name == name
                     }).map_or(Set1::Many, |(i, def)| {
-                        Set1::One(Region::EarlyBound(i as u32, def.lifetime.id))
+                        let def_id = hir_map.local_def_id(def.lifetime.id);
+                        Set1::One(Region::EarlyBound(i as u32, def_id))
                     })
                 }
             }
@@ -835,9 +847,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
 
         let lifetimes = generics.lifetimes.iter().map(|def| {
             if self.map.late_bound.contains(&def.lifetime.id) {
-                Region::late(def)
+                Region::late(self.hir_map, def)
             } else {
-                Region::early(&mut index, def)
+                Region::early(self.hir_map, &mut index, def)
             }
         }).collect();
 
@@ -1483,10 +1495,14 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
 
                 Scope::Binder { ref lifetimes, s } => {
                     if let Some(&def) = lifetimes.get(&lifetime.name) {
+                        let node_id = self.hir_map
+                                          .as_local_node_id(def.id().unwrap())
+                                          .unwrap();
+
                         signal_shadowing_problem(
                             self.sess,
                             lifetime.name,
-                            original_lifetime(self.hir_map.span(def.id().unwrap())),
+                            original_lifetime(self.hir_map.span(node_id)),
                             shadower_lifetime(&lifetime));
                         return;
                     }
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 8f8663385b020..5256bb2278117 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -96,6 +96,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
         -> ty::Region<'tcx>
     {
         let tcx = self.tcx();
+        let lifetime_name = |def_id| {
+            tcx.hir.name(tcx.hir.as_local_node_id(def_id).unwrap())
+        };
+
         let hir_id = tcx.hir.node_to_hir_id(lifetime.id);
         let r = match tcx.named_region(hir_id) {
             Some(rl::Region::Static) => {
@@ -103,9 +107,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
             }
 
             Some(rl::Region::LateBound(debruijn, id)) => {
-                let name = tcx.hir.name(id);
+                let name = lifetime_name(id);
                 tcx.mk_region(ty::ReLateBound(debruijn,
-                    ty::BrNamed(tcx.hir.local_def_id(id), name)))
+                    ty::BrNamed(id, name)))
             }
 
             Some(rl::Region::LateBoundAnon(debruijn, index)) => {
@@ -113,19 +117,19 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
             }
 
             Some(rl::Region::EarlyBound(index, id)) => {
-                let name = tcx.hir.name(id);
+                let name = lifetime_name(id);
                 tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
-                    def_id: tcx.hir.local_def_id(id),
+                    def_id: id,
                     index,
                     name,
                 }))
             }
 
             Some(rl::Region::Free(scope, id)) => {
-                let name = tcx.hir.name(id);
+                let name = lifetime_name(id);
                 tcx.mk_region(ty::ReFree(ty::FreeRegion {
                     scope,
-                    bound_region: ty::BrNamed(tcx.hir.local_def_id(id), name)
+                    bound_region: ty::BrNamed(id, name)
                 }))
 
                     // (*) -- not late-bound, won't change
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 3be0937340899..73ab286f185aa 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1835,7 +1835,8 @@ impl Clean<Type> for hir::Ty {
                     for (i, lt_param) in generics.lifetimes.iter().enumerate() {
                         if let Some(lt) = provided_params.lifetimes.get(i).cloned() {
                             if !lt.is_elided() {
-                                lt_substs.insert(lt_param.lifetime.id, lt.clean(cx));
+                                let lt_def_id = cx.tcx.hir.local_def_id(lt_param.lifetime.id);
+                                lt_substs.insert(lt_def_id, lt.clean(cx));
                             }
                         }
                     }
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 0c0748cf673c1..277e2909ba9ed 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -24,7 +24,7 @@ use rustc_trans::back::link;
 use rustc_resolve as resolve;
 use rustc_metadata::cstore::CStore;
 
-use syntax::{ast, codemap};
+use syntax::codemap;
 use syntax::feature_gate::UnstableFeatures;
 use syntax::fold::Folder;
 use errors;
@@ -65,7 +65,7 @@ pub struct DocContext<'a, 'tcx: 'a> {
     /// Table type parameter definition -> substituted type
     pub ty_substs: RefCell<FxHashMap<Def, clean::Type>>,
     /// Table node id of lifetime parameter definition -> substituted lifetime
-    pub lt_substs: RefCell<FxHashMap<ast::NodeId, clean::Lifetime>>,
+    pub lt_substs: RefCell<FxHashMap<DefId, clean::Lifetime>>,
 }
 
 impl<'a, 'tcx> DocContext<'a, 'tcx> {
@@ -77,7 +77,7 @@ impl<'a, 'tcx> DocContext<'a, 'tcx> {
     /// the substitutions for a type alias' RHS.
     pub fn enter_alias<F, R>(&self,
                              ty_substs: FxHashMap<Def, clean::Type>,
-                             lt_substs: FxHashMap<ast::NodeId, clean::Lifetime>,
+                             lt_substs: FxHashMap<DefId, clean::Lifetime>,
                              f: F) -> R
     where F: FnOnce() -> R {
         let (old_tys, old_lts) =

From e6c9a53d1a148fe4cd2cf9e0e1329289163d2284 Mon Sep 17 00:00:00 2001
From: Michael Woerister <michaelwoerister@posteo>
Date: Mon, 14 Aug 2017 18:19:42 +0200
Subject: [PATCH 13/24] incr.comp.: Compute hashes of all query results.

---
 src/librustc/ich/hcx.rs                       |  82 +++++-
 src/librustc/ich/impls_cstore.rs              |   7 +
 src/librustc/ich/impls_hir.rs                 |  54 +++-
 src/librustc/ich/impls_ty.rs                  | 255 +++++++++++++++---
 src/librustc/ich/mod.rs                       |   5 +-
 src/librustc/lint/levels.rs                   |  61 +++++
 src/librustc/lint/mod.rs                      |  17 ++
 src/librustc/middle/reachable.rs              |  10 +-
 src/librustc/middle/region.rs                 |  43 +++
 .../traits/specialize/specialization_graph.rs |  34 +++
 src/librustc/ty/fast_reject.rs                |  94 ++++++-
 src/librustc/ty/layout.rs                     | 130 +++++++++
 src/librustc/ty/maps.rs                       |  24 +-
 src/librustc/ty/trait_def.rs                  |  17 +-
 src/librustc_data_structures/stable_hasher.rs |  28 +-
 src/librustc_mir/transform/erase_regions.rs   |  42 ++-
 src/libsyntax/ast.rs                          |   9 +-
 17 files changed, 828 insertions(+), 84 deletions(-)

diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs
index 5c011042deeee..767868ffda318 100644
--- a/src/librustc/ich/hcx.rs
+++ b/src/librustc/ich/hcx.rs
@@ -13,9 +13,10 @@ use hir::def_id::DefId;
 use hir::map::DefPathHash;
 use ich::{self, CachingCodemapView};
 use session::config::DebugInfoLevel::NoDebugInfo;
-use ty::TyCtxt;
-use util::nodemap::{NodeMap, ItemLocalMap};
+use ty::{self, TyCtxt, fast_reject};
+use util::nodemap::{NodeMap, NodeSet, ItemLocalMap};
 
+use std::cmp::Ord;
 use std::hash as std_hash;
 use std::collections::{HashMap, HashSet, BTreeMap};
 
@@ -47,6 +48,7 @@ pub struct StableHashingContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
 #[derive(PartialEq, Eq, Clone, Copy)]
 pub enum NodeIdHashingMode {
     Ignore,
+    CheckedIgnore,
     HashDefPath,
     HashTraitsInScope,
 }
@@ -148,7 +150,7 @@ impl<'a, 'gcx, 'tcx> StableHashingContext<'a, 'gcx, 'tcx> {
             self.overflow_checks_enabled = true;
         }
         let prev_hash_node_ids = self.node_id_hashing_mode;
-        self.node_id_hashing_mode = NodeIdHashingMode::Ignore;
+        self.node_id_hashing_mode = NodeIdHashingMode::CheckedIgnore;
 
         f(self);
 
@@ -202,6 +204,9 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ast::N
         let hir_id = hcx.tcx.hir.node_to_hir_id(*self);
         match hcx.node_id_hashing_mode {
             NodeIdHashingMode::Ignore => {
+                // Don't do anything.
+            }
+            NodeIdHashingMode::CheckedIgnore => {
                 // Most NodeIds in the HIR can be ignored, but if there is a
                 // corresponding entry in the `trait_map` we need to hash that.
                 // Make sure we don't ignore too much by checking that there is
@@ -321,7 +326,7 @@ pub fn hash_stable_hashmap<'a, 'gcx, 'tcx, K, V, R, SK, F, W>(
     let mut keys: Vec<_> = map.keys()
                               .map(|k| (extract_stable_key(hcx, k), k))
                               .collect();
-    keys.sort_unstable_by_key(|&(ref stable_key, _)| stable_key.clone());
+    keys.sort_unstable_by(|&(ref sk1, _), &(ref sk2, _)| sk1.cmp(sk2));
     keys.len().hash_stable(hcx, hasher);
     for (stable_key, key) in keys {
         stable_key.hash_stable(hcx, hasher);
@@ -354,8 +359,25 @@ pub fn hash_stable_nodemap<'a, 'tcx, 'gcx, V, W>(
     where V: HashStable<StableHashingContext<'a, 'gcx, 'tcx>>,
           W: StableHasherResult,
 {
-    hash_stable_hashmap(hcx, hasher, map, |hcx, node_id| {
-        hcx.tcx.hir.definitions().node_to_hir_id(*node_id).local_id
+    let definitions = hcx.tcx.hir.definitions();
+    hash_stable_hashmap(hcx, hasher, map, |_, node_id| {
+        let hir_id = definitions.node_to_hir_id(*node_id);
+        let owner_def_path_hash = definitions.def_path_hash(hir_id.owner);
+        (owner_def_path_hash, hir_id.local_id)
+    });
+}
+
+pub fn hash_stable_nodeset<'a, 'tcx, 'gcx, W>(
+    hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+    hasher: &mut StableHasher<W>,
+    map: &NodeSet)
+    where W: StableHasherResult,
+{
+    let definitions = hcx.tcx.hir.definitions();
+    hash_stable_hashset(hcx, hasher, map, |_, node_id| {
+        let hir_id = definitions.node_to_hir_id(*node_id);
+        let owner_def_path_hash = definitions.def_path_hash(hir_id.owner);
+        (owner_def_path_hash, hir_id.local_id)
     });
 }
 
@@ -386,10 +408,56 @@ pub fn hash_stable_btreemap<'a, 'tcx, 'gcx, K, V, SK, F, W>(
     let mut keys: Vec<_> = map.keys()
                               .map(|k| (extract_stable_key(hcx, k), k))
                               .collect();
-    keys.sort_unstable_by_key(|&(ref stable_key, _)| stable_key.clone());
+    keys.sort_unstable_by(|&(ref sk1, _), &(ref sk2, _)| sk1.cmp(sk2));
     keys.len().hash_stable(hcx, hasher);
     for (stable_key, key) in keys {
         stable_key.hash_stable(hcx, hasher);
         map[key].hash_stable(hcx, hasher);
     }
 }
+
+pub fn hash_stable_trait_impls<'a, 'tcx, 'gcx, W, R>(
+    hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+    hasher: &mut StableHasher<W>,
+    blanket_impls: &Vec<DefId>,
+    non_blanket_impls: &HashMap<fast_reject::SimplifiedType, Vec<DefId>, R>)
+    where W: StableHasherResult,
+          R: std_hash::BuildHasher,
+{
+    {
+        let mut blanket_impls: AccumulateVec<[_; 8]> = blanket_impls
+            .iter()
+            .map(|&def_id| hcx.def_path_hash(def_id))
+            .collect();
+
+        if blanket_impls.len() > 1 {
+            blanket_impls.sort_unstable();
+        }
+
+        blanket_impls.hash_stable(hcx, hasher);
+    }
+
+    {
+        let tcx = hcx.tcx();
+        let mut keys: AccumulateVec<[_; 8]> =
+            non_blanket_impls.keys()
+                             .map(|k| (k, k.map_def(|d| tcx.def_path_hash(d))))
+                             .collect();
+        keys.sort_unstable_by(|&(_, ref k1), &(_, ref k2)| k1.cmp(k2));
+        keys.len().hash_stable(hcx, hasher);
+        for (key, ref stable_key) in keys {
+            stable_key.hash_stable(hcx, hasher);
+            let mut impls : AccumulateVec<[_; 8]> = non_blanket_impls[key]
+                .iter()
+                .map(|&impl_id| hcx.def_path_hash(impl_id))
+                .collect();
+
+            if impls.len() > 1 {
+                impls.sort_unstable();
+            }
+
+            impls.hash_stable(hcx, hasher);
+        }
+    }
+}
+
diff --git a/src/librustc/ich/impls_cstore.rs b/src/librustc/ich/impls_cstore.rs
index e95dbdd15c5f0..dad5c35c1e814 100644
--- a/src/librustc/ich/impls_cstore.rs
+++ b/src/librustc/ich/impls_cstore.rs
@@ -38,3 +38,10 @@ impl_stable_hash_for!(enum middle::cstore::LinkagePreference {
     RequireDynamic,
     RequireStatic
 });
+
+impl_stable_hash_for!(struct middle::cstore::ExternCrate {
+    def_id,
+    span,
+    direct,
+    path_len
+});
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index 411f5e26e4d05..a4cbcf0411199 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -13,13 +13,12 @@
 
 use hir;
 use hir::def_id::{DefId, CrateNum, CRATE_DEF_INDEX};
-use ich::{StableHashingContext, NodeIdHashingMode};
-use std::mem;
-
-use syntax::ast;
-
+use ich::{self, StableHashingContext, NodeIdHashingMode};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
                                            StableHasherResult};
+use std::mem;
+use syntax::ast;
+use util::nodemap::DefIdSet;
 
 impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for DefId {
     #[inline]
@@ -30,6 +29,16 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for DefId
     }
 }
 
+impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for DefIdSet
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        ich::hash_stable_hashset(hcx, hasher, self, |hcx, def_id| {
+            hcx.def_path_hash(*def_id)
+        });
+    }
+}
 
 impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::HirId {
     #[inline]
@@ -235,7 +244,7 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::T
             hir::TyTypeof(..)      |
             hir::TyErr             |
             hir::TyInfer           => {
-                NodeIdHashingMode::Ignore
+                NodeIdHashingMode::CheckedIgnore
             }
             hir::TyPath(..) => {
                 NodeIdHashingMode::HashTraitsInScope
@@ -403,7 +412,7 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::P
             hir::PatKind::Lit(..)     |
             hir::PatKind::Range(..)   |
             hir::PatKind::Slice(..)   => {
-                NodeIdHashingMode::Ignore
+                NodeIdHashingMode::CheckedIgnore
             }
             hir::PatKind::Path(..)        |
             hir::PatKind::Struct(..)      |
@@ -574,21 +583,21 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::E
                 hir::ExprRepeat(..)     |
                 hir::ExprTup(..)        => {
                     // For these we only hash the span when debuginfo is on.
-                    (false, NodeIdHashingMode::Ignore)
+                    (false, NodeIdHashingMode::CheckedIgnore)
                 }
                 // For the following, spans might be significant because of
                 // panic messages indicating the source location.
                 hir::ExprBinary(op, ..) => {
-                    (hcx.binop_can_panic_at_runtime(op.node), NodeIdHashingMode::Ignore)
+                    (hcx.binop_can_panic_at_runtime(op.node), NodeIdHashingMode::CheckedIgnore)
                 }
                 hir::ExprUnary(op, _) => {
-                    (hcx.unop_can_panic_at_runtime(op), NodeIdHashingMode::Ignore)
+                    (hcx.unop_can_panic_at_runtime(op), NodeIdHashingMode::CheckedIgnore)
                 }
                 hir::ExprAssignOp(op, ..) => {
-                    (hcx.binop_can_panic_at_runtime(op.node), NodeIdHashingMode::Ignore)
+                    (hcx.binop_can_panic_at_runtime(op.node), NodeIdHashingMode::CheckedIgnore)
                 }
                 hir::ExprIndex(..) => {
-                    (true, NodeIdHashingMode::Ignore)
+                    (true, NodeIdHashingMode::CheckedIgnore)
                 }
                 // For these we don't care about the span, but want to hash the
                 // trait in scope
@@ -899,7 +908,7 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::I
             hir::ItemStatic(..)      |
             hir::ItemConst(..)       |
             hir::ItemFn(..)          => {
-                (NodeIdHashingMode::Ignore, hcx.hash_spans())
+                (NodeIdHashingMode::CheckedIgnore, hcx.hash_spans())
             }
             hir::ItemUse(..) => {
                 (NodeIdHashingMode::HashTraitsInScope, false)
@@ -916,7 +925,7 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::I
             hir::ItemEnum(..)        |
             hir::ItemStruct(..)      |
             hir::ItemUnion(..)       => {
-                (NodeIdHashingMode::Ignore, false)
+                (NodeIdHashingMode::CheckedIgnore, false)
             }
         };
 
@@ -1160,3 +1169,20 @@ for ::middle::lang_items::LangItem {
         ::std::hash::Hash::hash(self, hasher);
     }
 }
+
+impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+for hir::TraitCandidate {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
+            let hir::TraitCandidate {
+                def_id,
+                import_id,
+            } = *self;
+
+            def_id.hash_stable(hcx, hasher);
+            import_id.hash_stable(hcx, hasher);
+        });
+    }
+}
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index e933ca4c2b551..53a071fe48030 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -11,12 +11,13 @@
 //! This module contains `HashStable` implementations for various data types
 //! from rustc::ty in no particular order.
 
-use ich::StableHashingContext;
+use ich::{self, StableHashingContext, NodeIdHashingMode};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
                                            StableHasherResult};
 use std::hash as std_hash;
 use std::mem;
 use middle::region;
+use traits;
 use ty;
 
 impl<'a, 'gcx, 'tcx, T> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
@@ -304,7 +305,9 @@ for ::middle::const_val::ConstVal<'gcx> {
             }
             Function(def_id, substs) => {
                 def_id.hash_stable(hcx, hasher);
-                substs.hash_stable(hcx, hasher);
+                hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
+                    substs.hash_stable(hcx, hasher);
+                });
             }
             Aggregate(Struct(ref name_values)) => {
                 let mut values = name_values.to_vec();
@@ -338,6 +341,54 @@ impl_stable_hash_for!(struct ty::Const<'tcx> {
     val
 });
 
+impl_stable_hash_for!(struct ::middle::const_val::ConstEvalErr<'tcx> {
+    span,
+    kind
+});
+
+impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+for ::middle::const_val::ErrKind<'gcx> {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        use middle::const_val::ErrKind::*;
+
+        mem::discriminant(self).hash_stable(hcx, hasher);
+
+        match *self {
+            CannotCast |
+            MissingStructField |
+            NonConstPath |
+            ExpectedConstTuple |
+            ExpectedConstStruct |
+            IndexedNonVec |
+            IndexNotUsize |
+            MiscBinaryOp |
+            MiscCatchAll |
+            IndexOpFeatureGated |
+            TypeckError => {
+                // nothing to do
+            }
+            UnimplementedConstVal(s) => {
+                s.hash_stable(hcx, hasher);
+            }
+            IndexOutOfBounds { len, index } => {
+                len.hash_stable(hcx, hasher);
+                index.hash_stable(hcx, hasher);
+            }
+            Math(ref const_math_err) => {
+                const_math_err.hash_stable(hcx, hasher);
+            }
+            LayoutError(ref layout_error) => {
+                layout_error.hash_stable(hcx, hasher);
+            }
+            ErroneousReferencedConstant(ref const_val) => {
+                const_val.hash_stable(hcx, hasher);
+            }
+        }
+    }
+}
+
 impl_stable_hash_for!(struct ty::ClosureSubsts<'tcx> { substs });
 
 impl_stable_hash_for!(struct ty::GeneratorInterior<'tcx> { witness });
@@ -414,7 +465,6 @@ impl_stable_hash_for!(struct ty::TypeParameterDef {
     pure_wrt_drop
 });
 
-
 impl<'a, 'gcx, 'tcx, T> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
 for ::middle::resolve_lifetime::Set1<T>
     where T: HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
@@ -470,19 +520,21 @@ for region::Scope
                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
-        match *self {
-            region::Scope::Node(node_id) |
-            region::Scope::Destruction(node_id) => {
-                node_id.hash_stable(hcx, hasher);
-            }
-            region::Scope::CallSite(body_id) |
-            region::Scope::Arguments(body_id) => {
-                body_id.hash_stable(hcx, hasher);
-            }
-            region::Scope::Remainder(block_remainder) => {
-                block_remainder.hash_stable(hcx, hasher);
-            }
-        }
+        hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
+            match *self {
+                region::Scope::Node(node_id) |
+                region::Scope::Destruction(node_id) => {
+                    node_id.hash_stable(hcx, hasher);
+                }
+                region::Scope::CallSite(body_id) |
+                region::Scope::Arguments(body_id) => {
+                    body_id.hash_stable(hcx, hasher);
+                }
+                region::Scope::Remainder(block_remainder) => {
+                    block_remainder.hash_stable(hcx, hasher);
+                }
+            }
+        })
     }
 }
 
@@ -520,6 +572,7 @@ for ty::TypeVariants<'gcx>
             TyBool  |
             TyChar  |
             TyStr   |
+            TyError |
             TyNever => {
                 // Nothing more to hash.
             }
@@ -585,10 +638,8 @@ for ty::TypeVariants<'gcx>
             TyParam(param_ty) => {
                 param_ty.hash_stable(hcx, hasher);
             }
-
-            TyError     |
             TyInfer(..) => {
-                bug!("ty::TypeVariants::hash_stable() - Unexpected variant.")
+                bug!("ty::TypeVariants::hash_stable() - Unexpected variant {:?}.", *self)
             }
         }
     }
@@ -636,26 +687,6 @@ impl_stable_hash_for!(struct ty::ExistentialProjection<'tcx> {
     ty
 });
 
-impl_stable_hash_for!(enum ty::fast_reject::SimplifiedType {
-    BoolSimplifiedType,
-    CharSimplifiedType,
-    IntSimplifiedType(int_ty),
-    UintSimplifiedType(int_ty),
-    FloatSimplifiedType(float_ty),
-    AdtSimplifiedType(def_id),
-    StrSimplifiedType,
-    ArraySimplifiedType,
-    PtrSimplifiedType,
-    NeverSimplifiedType,
-    TupleSimplifiedType(size),
-    TraitSimplifiedType(def_id),
-    ClosureSimplifiedType(def_id),
-    GeneratorSimplifiedType(def_id),
-    AnonSimplifiedType(def_id),
-    FunctionSimplifiedType(params),
-    ParameterSimplifiedType
-});
-
 impl_stable_hash_for!(struct ty::Instance<'tcx> {
     def,
     substs
@@ -697,3 +728,149 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ty::In
     }
 }
 
+impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ty::TraitDef {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        let ty::TraitDef {
+            // We already have the def_path_hash below, no need to hash it twice
+            def_id: _,
+            unsafety,
+            paren_sugar,
+            has_default_impl,
+            def_path_hash,
+        } = *self;
+
+        unsafety.hash_stable(hcx, hasher);
+        paren_sugar.hash_stable(hcx, hasher);
+        has_default_impl.hash_stable(hcx, hasher);
+        def_path_hash.hash_stable(hcx, hasher);
+    }
+}
+
+impl_stable_hash_for!(struct ty::Destructor {
+    did
+});
+
+impl_stable_hash_for!(struct ty::DtorckConstraint<'tcx> {
+    outlives,
+    dtorck_types
+});
+
+
+impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ty::CrateVariancesMap {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        let ty::CrateVariancesMap {
+            ref dependencies,
+            ref variances,
+            // This is just an irrelevant helper value.
+            empty_variance: _,
+        } = *self;
+
+        dependencies.hash_stable(hcx, hasher);
+
+        ich::hash_stable_hashmap(hcx, hasher, variances, |hcx, def_id| {
+            hcx.def_path_hash(*def_id)
+        });
+    }
+}
+
+impl_stable_hash_for!(struct ty::AssociatedItem {
+    def_id,
+    name,
+    kind,
+    vis,
+    defaultness,
+    container,
+    method_has_self_argument
+});
+
+impl_stable_hash_for!(enum ty::AssociatedKind {
+    Const,
+    Method,
+    Type
+});
+
+impl_stable_hash_for!(enum ty::AssociatedItemContainer {
+    TraitContainer(def_id),
+    ImplContainer(def_id)
+});
+
+
+impl<'a, 'gcx, 'tcx, T> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+for ty::steal::Steal<T>
+    where T: HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        self.borrow().hash_stable(hcx, hasher);
+    }
+}
+
+impl_stable_hash_for!(struct ty::ParamEnv<'tcx> {
+    caller_bounds,
+    reveal
+});
+
+impl_stable_hash_for!(enum traits::Reveal {
+    UserFacing,
+    All
+});
+
+impl_stable_hash_for!(enum ::middle::privacy::AccessLevel {
+    Reachable,
+    Exported,
+    Public
+});
+
+impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+for ::middle::privacy::AccessLevels {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
+            let ::middle::privacy::AccessLevels {
+                ref map
+            } = *self;
+
+            ich::hash_stable_nodemap(hcx, hasher, map);
+        });
+    }
+}
+
+impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+for ty::CrateInherentImpls {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        let ty::CrateInherentImpls {
+            ref inherent_impls,
+        } = *self;
+
+        ich::hash_stable_hashmap(hcx, hasher, inherent_impls, |hcx, def_id| {
+            hcx.def_path_hash(*def_id)
+        });
+    }
+}
+
+impl_stable_hash_for!(enum ::session::CompileIncomplete {
+    Stopped,
+    Errored(error_reported)
+});
+
+impl_stable_hash_for!(struct ::util::common::ErrorReported {});
+
+impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+for ::middle::reachable::ReachableSet {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        let ::middle::reachable::ReachableSet(ref reachable_set) = *self;
+
+        ich::hash_stable_nodeset(hcx, hasher, reachable_set);
+    }
+}
+
diff --git a/src/librustc/ich/mod.rs b/src/librustc/ich/mod.rs
index dcf84be0eeb3a..c24064eb27c58 100644
--- a/src/librustc/ich/mod.rs
+++ b/src/librustc/ich/mod.rs
@@ -13,8 +13,9 @@
 pub use self::fingerprint::Fingerprint;
 pub use self::caching_codemap_view::CachingCodemapView;
 pub use self::hcx::{StableHashingContext, NodeIdHashingMode, hash_stable_hashmap,
-                    hash_stable_hashset, hash_stable_nodemap,
-                    hash_stable_btreemap, hash_stable_itemlocalmap};
+                    hash_stable_hashset, hash_stable_nodemap, hash_stable_nodeset,
+                    hash_stable_btreemap, hash_stable_itemlocalmap,
+                    hash_stable_trait_impls};
 mod fingerprint;
 mod caching_codemap_view;
 mod hcx;
diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs
index c5863b5618feb..e953afd799dbf 100644
--- a/src/librustc/lint/levels.rs
+++ b/src/librustc/lint/levels.rs
@@ -12,9 +12,12 @@ use std::cmp;
 
 use errors::DiagnosticBuilder;
 use hir::HirId;
+use ich::{self, StableHashingContext};
 use lint::builtin;
 use lint::context::CheckLintNameResult;
 use lint::{self, Lint, LintId, Level, LintSource};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
+                                           StableHasherResult};
 use session::Session;
 use syntax::ast;
 use syntax::attr;
@@ -382,3 +385,61 @@ impl LintLevelMap {
         })
     }
 }
+
+impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for LintLevelMap {
+    #[inline]
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        let LintLevelMap {
+            ref sets,
+            ref id_to_set,
+        } = *self;
+
+        let definitions = hcx.tcx().hir.definitions();
+        ich::hash_stable_hashmap(hcx, hasher, id_to_set, |_, hir_id| {
+            (definitions.def_path_hash(hir_id.owner), hir_id.local_id)
+        });
+
+        let LintLevelSets {
+            ref list,
+            lint_cap,
+        } = *sets;
+
+        lint_cap.hash_stable(hcx, hasher);
+
+        hcx.while_hashing_spans(true, |hcx| {
+            list.len().hash_stable(hcx, hasher);
+
+            // We are working under the assumption here that the list of
+            // lint-sets is built in a deterministic order.
+            for lint_set in list {
+                ::std::mem::discriminant(lint_set).hash_stable(hcx, hasher);
+
+                match *lint_set {
+                    LintSet::CommandLine { ref specs } => {
+                        ich::hash_stable_hashmap(hcx, hasher, specs, |_, lint_id| {
+                            lint_id.lint_name_raw()
+                        });
+                    }
+                    LintSet::Node { ref specs, parent } => {
+                        ich::hash_stable_hashmap(hcx, hasher, specs, |_, lint_id| {
+                            lint_id.lint_name_raw()
+                        });
+                        parent.hash_stable(hcx, hasher);
+                    }
+                }
+            }
+        })
+    }
+}
+
+impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for LintId {
+    #[inline]
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        self.lint_name_raw().hash_stable(hcx, hasher);
+    }
+}
+
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index c64e1c08082a5..42b5e2dd83de5 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -305,6 +305,10 @@ impl LintId {
         }
     }
 
+    pub fn lint_name_raw(&self) -> &'static str {
+        self.lint.name
+    }
+
     /// Get the name of the lint.
     pub fn to_string(&self) -> String {
         self.lint.name_lower()
@@ -317,6 +321,13 @@ pub enum Level {
     Allow, Warn, Deny, Forbid
 }
 
+impl_stable_hash_for!(enum self::Level {
+    Allow,
+    Warn,
+    Deny,
+    Forbid
+});
+
 impl Level {
     /// Convert a level to a lower-case string.
     pub fn as_str(self) -> &'static str {
@@ -354,6 +365,12 @@ pub enum LintSource {
     CommandLine(Symbol),
 }
 
+impl_stable_hash_for!(enum self::LintSource {
+    Default,
+    Node(name, span),
+    CommandLine(text)
+});
+
 pub type LevelSource = (Level, LintSource);
 
 pub mod builtin;
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index 7c44245090197..fa29dda86ddd0 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -369,7 +369,13 @@ impl<'a, 'tcx: 'a> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a,
     }
 }
 
-fn reachable_set<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) -> Rc<NodeSet> {
+// We introduce a new-type here, so we can have a specialized HashStable
+// implementation for it.
+#[derive(Clone)]
+pub struct ReachableSet(pub Rc<NodeSet>);
+
+
+fn reachable_set<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) -> ReachableSet {
     debug_assert!(crate_num == LOCAL_CRATE);
 
     let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
@@ -414,7 +420,7 @@ fn reachable_set<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) ->
     reachable_context.propagate();
 
     // Return the set of reachable symbols.
-    Rc::new(reachable_context.reachable_symbols)
+    ReachableSet(Rc::new(reachable_context.reachable_symbols))
 }
 
 pub fn provide(providers: &mut Providers) {
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index ae9866edc53b2..562536ced3ce9 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -14,6 +14,7 @@
 //! Most of the documentation on regions can be found in
 //! `middle/infer/region_inference/README.md`
 
+use ich::{self, StableHashingContext, NodeIdHashingMode};
 use util::nodemap::{FxHashMap, FxHashSet};
 use ty;
 
@@ -31,6 +32,8 @@ use hir::def_id::DefId;
 use hir::intravisit::{self, Visitor, NestedVisitorMap};
 use hir::{Block, Arm, Pat, PatKind, Stmt, Expr, Local};
 use mir::transform::MirSource;
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
+                                           StableHasherResult};
 
 /// Scope represents a statically-describable scope that can be
 /// used to bound the lifetime/region for values.
@@ -1235,3 +1238,43 @@ pub fn provide(providers: &mut Providers) {
         ..*providers
     };
 }
+
+impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ScopeTree {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        let ScopeTree {
+            root_body,
+            root_parent,
+            ref parent_map,
+            ref var_map,
+            ref destruction_scopes,
+            ref rvalue_scopes,
+            ref closure_tree,
+            ref yield_in_scope,
+        } = *self;
+
+        hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
+            root_body.hash_stable(hcx, hasher);
+            root_parent.hash_stable(hcx, hasher);
+        });
+
+        ich::hash_stable_hashmap(hcx, hasher, parent_map, |hcx, scope| {
+            let mut hasher = StableHasher::new();
+            scope.hash_stable(hcx, &mut hasher);
+            let stable: u64 = hasher.finish();
+            stable
+        });
+
+        ich::hash_stable_itemlocalmap(hcx, hasher, var_map);
+        ich::hash_stable_itemlocalmap(hcx, hasher, destruction_scopes);
+        ich::hash_stable_itemlocalmap(hcx, hasher, rvalue_scopes);
+        ich::hash_stable_itemlocalmap(hcx, hasher, closure_tree);
+        ich::hash_stable_hashmap(hcx, hasher, yield_in_scope, |hcx, scope| {
+            let mut hasher = StableHasher::new();
+            scope.hash_stable(hcx, &mut hasher);
+            let stable: u64 = hasher.finish();
+            stable
+        });
+    }
+}
diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs
index 2640542ad1059..ecaf14659ae6b 100644
--- a/src/librustc/traits/specialize/specialization_graph.rs
+++ b/src/librustc/traits/specialize/specialization_graph.rs
@@ -11,6 +11,9 @@
 use super::OverlapError;
 
 use hir::def_id::DefId;
+use ich::{self, StableHashingContext};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
+                                           StableHasherResult};
 use traits;
 use ty::{self, TyCtxt, TypeFoldable};
 use ty::fast_reject::{self, SimplifiedType};
@@ -365,3 +368,34 @@ pub fn ancestors(tcx: TyCtxt,
         current_source: Some(Node::Impl(start_from_impl)),
     }
 }
+
+impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for Children {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        let Children {
+            ref nonblanket_impls,
+            ref blanket_impls,
+        } = *self;
+
+        ich::hash_stable_trait_impls(hcx, hasher, blanket_impls, nonblanket_impls);
+    }
+}
+
+impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for Graph {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        let Graph {
+            ref parent,
+            ref children,
+        } = *self;
+
+        ich::hash_stable_hashmap(hcx, hasher, parent, |hcx, def_id| {
+            hcx.def_path_hash(*def_id)
+        });
+        ich::hash_stable_hashmap(hcx, hasher, children, |hcx, def_id| {
+            hcx.def_path_hash(*def_id)
+        });
+    }
+}
diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs
index 353a1cd5355b9..86ae4bb92df07 100644
--- a/src/librustc/ty/fast_reject.rs
+++ b/src/librustc/ty/fast_reject.rs
@@ -9,29 +9,44 @@
 // except according to those terms.
 
 use hir::def_id::DefId;
-use ty::{self, Ty, TyCtxt};
+use ich::StableHashingContext;
+use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
+                                           HashStable};
+use std::fmt::Debug;
+use std::hash::Hash;
+use std::mem;
 use syntax::ast;
+use ty::{self, Ty, TyCtxt};
 
-use self::SimplifiedType::*;
+use self::SimplifiedTypeGen::*;
 
-/// See `simplify_type
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-pub enum SimplifiedType {
+pub type SimplifiedType = SimplifiedTypeGen<DefId>;
+
+/// See `simplify_type`
+///
+/// Note that we keep this type generic over the type of identifier it uses
+/// because we sometimes need to use SimplifiedTypeGen values as stable sorting
+/// keys (in which case we use a DefPathHash as id-type) but in the general case
+/// the non-stable but fast to construct DefId-version is the better choice.
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+pub enum SimplifiedTypeGen<D>
+    where D: Copy + Debug + Ord + Eq + Hash
+{
     BoolSimplifiedType,
     CharSimplifiedType,
     IntSimplifiedType(ast::IntTy),
     UintSimplifiedType(ast::UintTy),
     FloatSimplifiedType(ast::FloatTy),
-    AdtSimplifiedType(DefId),
+    AdtSimplifiedType(D),
     StrSimplifiedType,
     ArraySimplifiedType,
     PtrSimplifiedType,
     NeverSimplifiedType,
     TupleSimplifiedType(usize),
-    TraitSimplifiedType(DefId),
-    ClosureSimplifiedType(DefId),
-    GeneratorSimplifiedType(DefId),
-    AnonSimplifiedType(DefId),
+    TraitSimplifiedType(D),
+    ClosureSimplifiedType(D),
+    GeneratorSimplifiedType(D),
+    AnonSimplifiedType(D),
     FunctionSimplifiedType(usize),
     ParameterSimplifiedType,
 }
@@ -101,3 +116,62 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
         ty::TyInfer(_) | ty::TyError => None,
     }
 }
+
+impl<D: Copy + Debug + Ord + Eq + Hash> SimplifiedTypeGen<D> {
+    pub fn map_def<U, F>(self, map: F) -> SimplifiedTypeGen<U>
+        where F: Fn(D) -> U,
+              U: Copy + Debug + Ord + Eq + Hash,
+    {
+        match self {
+            BoolSimplifiedType => BoolSimplifiedType,
+            CharSimplifiedType => CharSimplifiedType,
+            IntSimplifiedType(t) => IntSimplifiedType(t),
+            UintSimplifiedType(t) => UintSimplifiedType(t),
+            FloatSimplifiedType(t) => FloatSimplifiedType(t),
+            AdtSimplifiedType(d) => AdtSimplifiedType(map(d)),
+            StrSimplifiedType => StrSimplifiedType,
+            ArraySimplifiedType => ArraySimplifiedType,
+            PtrSimplifiedType => PtrSimplifiedType,
+            NeverSimplifiedType => NeverSimplifiedType,
+            TupleSimplifiedType(n) => TupleSimplifiedType(n),
+            TraitSimplifiedType(d) => TraitSimplifiedType(map(d)),
+            ClosureSimplifiedType(d) => ClosureSimplifiedType(map(d)),
+            GeneratorSimplifiedType(d) => GeneratorSimplifiedType(map(d)),
+            AnonSimplifiedType(d) => AnonSimplifiedType(map(d)),
+            FunctionSimplifiedType(n) => FunctionSimplifiedType(n),
+            ParameterSimplifiedType => ParameterSimplifiedType,
+        }
+    }
+}
+
+impl<'a, 'gcx, 'tcx, D> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for SimplifiedTypeGen<D>
+    where D: Copy + Debug + Ord + Eq + Hash +
+             HashStable<StableHashingContext<'a, 'gcx, 'tcx>>,
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        mem::discriminant(self).hash_stable(hcx, hasher);
+        match *self {
+            BoolSimplifiedType |
+            CharSimplifiedType |
+            StrSimplifiedType |
+            ArraySimplifiedType |
+            PtrSimplifiedType |
+            NeverSimplifiedType |
+            ParameterSimplifiedType => {
+                // nothing to do
+            }
+            IntSimplifiedType(t) => t.hash_stable(hcx, hasher),
+            UintSimplifiedType(t) => t.hash_stable(hcx, hasher),
+            FloatSimplifiedType(t) => t.hash_stable(hcx, hasher),
+            AdtSimplifiedType(d) => d.hash_stable(hcx, hasher),
+            TupleSimplifiedType(n) => n.hash_stable(hcx, hasher),
+            TraitSimplifiedType(d) => d.hash_stable(hcx, hasher),
+            ClosureSimplifiedType(d) => d.hash_stable(hcx, hasher),
+            GeneratorSimplifiedType(d) => d.hash_stable(hcx, hasher),
+            AnonSimplifiedType(d) => d.hash_stable(hcx, hasher),
+            FunctionSimplifiedType(n) => n.hash_stable(hcx, hasher),
+        }
+    }
+}
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index 84d7745a64f0a..1ae1e7007ac5e 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -23,8 +23,13 @@ use std::cmp;
 use std::fmt;
 use std::i64;
 use std::iter;
+use std::mem;
 use std::ops::Deref;
 
+use ich::StableHashingContext;
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
+                                           StableHasherResult};
+
 /// Parsed [Data layout](http://llvm.org/docs/LangRef.html#data-layout)
 /// for a target, which contains everything needed to compute layouts.
 pub struct TargetDataLayout {
@@ -2300,3 +2305,128 @@ impl<'a, 'tcx> TyLayout<'tcx> {
         cx.layout_of(cx.normalize_projections(self.field_type(cx, i)))
     }
 }
+
+impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for Layout
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        use ty::layout::Layout::*;
+        mem::discriminant(self).hash_stable(hcx, hasher);
+
+        match *self {
+            Scalar { value, non_zero } => {
+                value.hash_stable(hcx, hasher);
+                non_zero.hash_stable(hcx, hasher);
+            }
+            Vector { element, count } => {
+                element.hash_stable(hcx, hasher);
+                count.hash_stable(hcx, hasher);
+            }
+            Array { sized, align, primitive_align, element_size, count } => {
+                sized.hash_stable(hcx, hasher);
+                align.hash_stable(hcx, hasher);
+                primitive_align.hash_stable(hcx, hasher);
+                element_size.hash_stable(hcx, hasher);
+                count.hash_stable(hcx, hasher);
+            }
+            FatPointer { ref metadata, non_zero } => {
+                metadata.hash_stable(hcx, hasher);
+                non_zero.hash_stable(hcx, hasher);
+            }
+            CEnum { discr, signed, non_zero, min, max } => {
+                discr.hash_stable(hcx, hasher);
+                signed.hash_stable(hcx, hasher);
+                non_zero.hash_stable(hcx, hasher);
+                min.hash_stable(hcx, hasher);
+                max.hash_stable(hcx, hasher);
+            }
+            Univariant { ref variant, non_zero } => {
+                variant.hash_stable(hcx, hasher);
+                non_zero.hash_stable(hcx, hasher);
+            }
+            UntaggedUnion { ref variants } => {
+                variants.hash_stable(hcx, hasher);
+            }
+            General { discr, ref variants, size, align, primitive_align } => {
+                discr.hash_stable(hcx, hasher);
+                variants.hash_stable(hcx, hasher);
+                size.hash_stable(hcx, hasher);
+                align.hash_stable(hcx, hasher);
+                primitive_align.hash_stable(hcx, hasher);
+            }
+            RawNullablePointer { nndiscr, ref value } => {
+                nndiscr.hash_stable(hcx, hasher);
+                value.hash_stable(hcx, hasher);
+            }
+            StructWrappedNullablePointer {
+                nndiscr,
+                ref nonnull,
+                ref discrfield,
+                ref discrfield_source
+            } => {
+                nndiscr.hash_stable(hcx, hasher);
+                nonnull.hash_stable(hcx, hasher);
+                discrfield.hash_stable(hcx, hasher);
+                discrfield_source.hash_stable(hcx, hasher);
+            }
+        }
+    }
+}
+
+impl_stable_hash_for!(enum ::ty::layout::Integer {
+    I1,
+    I8,
+    I16,
+    I32,
+    I64,
+    I128
+});
+
+impl_stable_hash_for!(enum ::ty::layout::Primitive {
+    Int(integer),
+    F32,
+    F64,
+    Pointer
+});
+
+impl_stable_hash_for!(struct ::ty::layout::Align {
+    abi,
+    pref
+});
+
+impl_stable_hash_for!(struct ::ty::layout::Size {
+    raw
+});
+
+impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for LayoutError<'gcx>
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        use ty::layout::LayoutError::*;
+        mem::discriminant(self).hash_stable(hcx, hasher);
+
+        match *self {
+            Unknown(t) |
+            SizeOverflow(t) => t.hash_stable(hcx, hasher)
+        }
+    }
+}
+
+impl_stable_hash_for!(struct ::ty::layout::Struct {
+    align,
+    primitive_align,
+    packed,
+    sized,
+    offsets,
+    memory_index,
+    min_size
+});
+
+impl_stable_hash_for!(struct ::ty::layout::Union {
+    align,
+    primitive_align,
+    min_size,
+    packed
+});
diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs
index bf17b82535cc1..48502dc2e8c84 100644
--- a/src/librustc/ty/maps.rs
+++ b/src/librustc/ty/maps.rs
@@ -14,11 +14,13 @@ use hir::def_id::{CrateNum, DefId, LOCAL_CRATE, DefIndex};
 use hir::def::{Def, Export};
 use hir::{self, TraitCandidate, ItemLocalId};
 use hir::svh::Svh;
+use ich::{Fingerprint, StableHashingContext};
 use lint;
 use middle::const_val;
 use middle::cstore::{ExternCrate, LinkagePreference, NativeLibrary};
 use middle::cstore::{NativeLibraryKind, DepKind, CrateSource};
 use middle::privacy::AccessLevels;
+use middle::reachable::ReachableSet;
 use middle::region;
 use middle::resolve_lifetime::{Region, ObjectLifetimeDefault};
 use middle::stability::{self, DeprecationEntry};
@@ -36,7 +38,7 @@ use ty::item_path;
 use ty::steal::Steal;
 use ty::subst::Substs;
 use ty::fast_reject::SimplifiedType;
-use util::nodemap::{DefIdSet, NodeSet, DefIdMap};
+use util::nodemap::{DefIdSet, DefIdMap};
 use util::common::{profq_msg, ProfileQueriesMsg};
 
 use rustc_data_structures::indexed_set::IdxSetBuf;
@@ -44,6 +46,7 @@ use rustc_back::PanicStrategy;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use std::cell::{RefCell, RefMut, Cell};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use std::fmt::Debug;
 use std::hash::Hash;
 use std::marker::PhantomData;
@@ -925,9 +928,8 @@ macro_rules! define_maps {
                     span = key.default_span(tcx)
                 }
 
+                let dep_node = Self::to_dep_node(tcx, &key);
                 let res = tcx.cycle_check(span, Query::$name(key), || {
-                    let dep_node = Self::to_dep_node(tcx, &key);
-
                     tcx.sess.diagnostic().track_diagnostics(|| {
                         if dep_node.kind.is_anon() {
                             tcx.dep_graph.with_anon_task(dep_node.kind, || {
@@ -951,6 +953,20 @@ macro_rules! define_maps {
 
                 tcx.dep_graph.read_index(dep_node_index);
 
+                // In incremental mode, hash the result of the query. We don't
+                // do anything with the hash yet, but we are computing it
+                // anyway so that
+                //  - we make sure that the infrastructure works and
+                //  - we can get an idea of the runtime cost.
+                if !dep_node.kind.is_anon() && tcx.sess.opts.incremental.is_some() {
+                    let mut hcx = StableHashingContext::new(tcx);
+                    let mut hasher = StableHasher::new();
+
+                    result.hash_stable(&mut hcx, &mut hasher);
+
+                    let _: Fingerprint = hasher.finish();
+                }
+
                 let value = QueryValue {
                     value: result,
                     index: dep_node_index,
@@ -1300,7 +1316,7 @@ define_maps! { <'tcx>
     /// Performs the privacy check and computes "access levels".
     [] fn privacy_access_levels: PrivacyAccessLevels(CrateNum) -> Rc<AccessLevels>,
 
-    [] fn reachable_set: reachability_dep_node(CrateNum) -> Rc<NodeSet>,
+    [] fn reachable_set: reachability_dep_node(CrateNum) -> ReachableSet,
 
     /// Per-body `region::ScopeTree`. The `DefId` should be the owner-def-id for the body;
     /// in the case of closures, this will be redirected to the enclosing function.
diff --git a/src/librustc/ty/trait_def.rs b/src/librustc/ty/trait_def.rs
index 3aadacfe826fd..9ae6c3516a5cf 100644
--- a/src/librustc/ty/trait_def.rs
+++ b/src/librustc/ty/trait_def.rs
@@ -11,13 +11,15 @@
 use hir;
 use hir::def_id::DefId;
 use hir::map::DefPathHash;
+use ich::{self, StableHashingContext};
 use traits::specialization_graph;
 use ty::fast_reject;
 use ty::fold::TypeFoldable;
 use ty::{Ty, TyCtxt};
 
 use rustc_data_structures::fx::FxHashMap;
-
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
+                                           StableHasherResult};
 use std::rc::Rc;
 
 /// A trait's definition with type information.
@@ -183,3 +185,16 @@ pub(super) fn trait_impls_of_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         non_blanket_impls: non_blanket_impls,
     })
 }
+
+impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for TraitImpls {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        let TraitImpls {
+            ref blanket_impls,
+            ref non_blanket_impls,
+        } = *self;
+
+        ich::hash_stable_trait_impls(hcx, hasher, blanket_impls, non_blanket_impls);
+    }
+}
diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs
index 33c4a041cff88..0d0cf67248944 100644
--- a/src/librustc_data_structures/stable_hasher.rs
+++ b/src/librustc_data_structures/stable_hasher.rs
@@ -365,8 +365,24 @@ impl<T, CTX> HashStable<CTX> for Option<T>
     }
 }
 
+impl<T1, T2, CTX> HashStable<CTX> for Result<T1, T2>
+    where T1: HashStable<CTX>,
+          T2: HashStable<CTX>,
+{
+    #[inline]
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          ctx: &mut CTX,
+                                          hasher: &mut StableHasher<W>) {
+        mem::discriminant(self).hash_stable(ctx, hasher);
+        match *self {
+            Ok(ref x) => x.hash_stable(ctx, hasher),
+            Err(ref x) => x.hash_stable(ctx, hasher),
+        }
+    }
+}
+
 impl<'a, T, CTX> HashStable<CTX> for &'a T
-    where T: HashStable<CTX>
+    where T: HashStable<CTX> + ?Sized
 {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
@@ -425,3 +441,13 @@ impl<I: ::indexed_vec::Idx, T, CTX> HashStable<CTX> for ::indexed_vec::IndexVec<
         }
     }
 }
+
+
+impl<I: ::indexed_vec::Idx, CTX> HashStable<CTX> for ::indexed_set::IdxSetBuf<I>
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          ctx: &mut CTX,
+                                          hasher: &mut StableHasher<W>) {
+        self.words().hash_stable(ctx, hasher);
+    }
+}
diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs
index dc18cdd8f0dd6..6ed928ca09deb 100644
--- a/src/librustc_mir/transform/erase_regions.rs
+++ b/src/librustc_mir/transform/erase_regions.rs
@@ -15,7 +15,8 @@
 //! "types-as-contracts"-validation, namely, AcquireValid, ReleaseValid, and EndRegion.
 
 use rustc::ty::subst::Substs;
-use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::{self, Ty, TyCtxt, ClosureSubsts};
+use rustc::middle::const_val::ConstVal;
 use rustc::mir::*;
 use rustc::mir::visit::{MutVisitor, Lookup};
 use rustc::mir::transform::{MirPass, MirSource};
@@ -79,6 +80,45 @@ impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> {
         self.super_statement(block, statement, location);
         self.in_validation_statement = false;
     }
+
+    fn visit_const_val(&mut self,
+                       const_val: &mut ConstVal<'tcx>,
+                       _: Location) {
+        erase_const_val(self.tcx, const_val);
+        self.super_const_val(const_val);
+
+        fn erase_const_val<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                     const_val: &mut ConstVal<'tcx>) {
+            match *const_val {
+                ConstVal::Float(_)    |
+                ConstVal::Integral(_) |
+                ConstVal::Str(_)      |
+                ConstVal::ByteStr(_)  |
+                ConstVal::Bool(_)     |
+                ConstVal::Char(_)     |
+                ConstVal::Variant(_)  => {
+                    // nothing to do
+                }
+                ConstVal::Function(_, ref mut substs) => {
+                    *substs = tcx.erase_regions(&{*substs});
+                }
+                ConstVal::Struct(ref mut field_map) => {
+                    for (_, field_val) in field_map {
+                        erase_const_val(tcx, field_val);
+                    }
+                }
+                ConstVal::Tuple(ref mut fields) |
+                ConstVal::Array(ref mut fields) => {
+                    for field_val in fields {
+                        erase_const_val(tcx, field_val);
+                    }
+                }
+                ConstVal::Repeat(ref mut expr, _) => {
+                    erase_const_val(tcx, &mut **expr);
+                }
+            }
+        }
+    }
 }
 
 pub struct EraseRegions;
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 5248f874a6e97..496be8b3eb23e 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -1221,7 +1221,8 @@ pub enum ImplItemKind {
     Macro(Mac),
 }
 
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy,
+         PartialOrd, Ord)]
 pub enum IntTy {
     Is,
     I8,
@@ -1274,7 +1275,8 @@ impl IntTy {
     }
 }
 
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy,
+         PartialOrd, Ord)]
 pub enum UintTy {
     Us,
     U8,
@@ -1324,7 +1326,8 @@ impl fmt::Display for UintTy {
     }
 }
 
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy,
+         PartialOrd, Ord)]
 pub enum FloatTy {
     F32,
     F64,

From 3cc3ae22bddc4fb24c790b58700a699c764ebd0e Mon Sep 17 00:00:00 2001
From: Michael Woerister <michaelwoerister@posteo>
Date: Thu, 7 Sep 2017 16:11:58 +0200
Subject: [PATCH 14/24] incr.comp.: Move result fingerprinting to
 DepGraph::with_task().

This makes sure that we don't introduce strange cases where we have
nodes outside the query system that could break red/green tracking
and it will allow to keep red/green neatly encapsulated within the
DepGraph implementation.
---
 src/librustc/dep_graph/graph.rs               | 36 +++++++++++++------
 src/librustc/dep_graph/safe.rs                |  7 ++++
 src/librustc/ich/hcx.rs                       | 10 ++++--
 src/librustc/ty/maps.rs                       | 17 +--------
 src/librustc/ty/mod.rs                        |  4 +++
 src/librustc_data_structures/stable_hasher.rs | 28 +++++++++++++--
 src/librustc_trans/base.rs                    | 31 +++++++++++++++-
 src/librustc_trans/context.rs                 | 14 ++++++++
 src/librustc_typeck/variance/constraints.rs   | 20 ++++++++---
 9 files changed, 130 insertions(+), 37 deletions(-)

diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs
index 34cb1d2a6d795..7679b7e7971eb 100644
--- a/src/librustc/dep_graph/graph.rs
+++ b/src/librustc/dep_graph/graph.rs
@@ -9,11 +9,15 @@
 // except according to those terms.
 
 use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
+                                           StableHashingContextProvider};
 use session::config::OutputType;
 use std::cell::{Ref, RefCell};
 use std::rc::Rc;
 use util::common::{ProfileQueriesMsg, profq_msg};
 
+use ich::Fingerprint;
+
 use super::dep_node::{DepNode, DepKind, WorkProductId};
 use super::query::DepGraphQuery;
 use super::raii;
@@ -71,10 +75,6 @@ impl DepGraph {
         self.data.as_ref().map(|data| raii::IgnoreTask::new(&data.edges))
     }
 
-    pub fn in_task<'graph>(&'graph self, key: DepNode) -> Option<raii::DepTask<'graph>> {
-        self.data.as_ref().map(|data| raii::DepTask::new(&data.edges, key))
-    }
-
     pub fn with_ignore<OP,R>(&self, op: OP) -> R
         where OP: FnOnce() -> R
     {
@@ -109,24 +109,38 @@ impl DepGraph {
     ///   `arg` parameter.
     ///
     /// [README]: README.md
-    pub fn with_task<C, A, R>(&self,
-                              key: DepNode,
-                              cx: C,
-                              arg: A,
-                              task: fn(C, A) -> R)
-                              -> (R, DepNodeIndex)
-        where C: DepGraphSafe
+    pub fn with_task<C, A, R, HCX>(&self,
+                                   key: DepNode,
+                                   cx: C,
+                                   arg: A,
+                                   task: fn(C, A) -> R)
+                                   -> (R, DepNodeIndex)
+        where C: DepGraphSafe + StableHashingContextProvider<ContextType=HCX>,
+              R: HashStable<HCX>,
     {
         if let Some(ref data) = self.data {
             data.edges.borrow_mut().push_task(key);
             if cfg!(debug_assertions) {
                 profq_msg(ProfileQueriesMsg::TaskBegin(key.clone()))
             };
+
+            // In incremental mode, hash the result of the task. We don't
+            // do anything with the hash yet, but we are computing it
+            // anyway so that
+            //  - we make sure that the infrastructure works and
+            //  - we can get an idea of the runtime cost.
+            let mut hcx = cx.create_stable_hashing_context();
+
             let result = task(cx, arg);
             if cfg!(debug_assertions) {
                 profq_msg(ProfileQueriesMsg::TaskEnd)
             };
             let dep_node_index = data.edges.borrow_mut().pop_task(key);
+
+            let mut stable_hasher = StableHasher::new();
+            result.hash_stable(&mut hcx, &mut stable_hasher);
+            let _: Fingerprint = stable_hasher.finish();
+
             (result, dep_node_index)
         } else {
             (task(cx, arg), DepNodeIndex::INVALID)
diff --git a/src/librustc/dep_graph/safe.rs b/src/librustc/dep_graph/safe.rs
index bf224f89f0ddb..f82bf9be03390 100644
--- a/src/librustc/dep_graph/safe.rs
+++ b/src/librustc/dep_graph/safe.rs
@@ -58,6 +58,13 @@ impl<'a, A> DepGraphSafe for &'a A
 {
 }
 
+/// Mut ref to dep-graph-safe stuff should still be dep-graph-safe.
+impl<'a, A> DepGraphSafe for &'a mut A
+    where A: DepGraphSafe,
+{
+}
+
+
 /// No data here! :)
 impl DepGraphSafe for () {
 }
diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs
index 767868ffda318..f4fa376347ae9 100644
--- a/src/librustc/ich/hcx.rs
+++ b/src/librustc/ich/hcx.rs
@@ -26,8 +26,8 @@ use syntax::ext::hygiene::SyntaxContext;
 use syntax::symbol::Symbol;
 use syntax_pos::Span;
 
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
-                                           StableHasherResult};
+use rustc_data_structures::stable_hasher::{HashStable, StableHashingContextProvider,
+                                           StableHasher, StableHasherResult};
 use rustc_data_structures::accumulate_vec::AccumulateVec;
 
 /// This is the context state available during incr. comp. hashing. It contains
@@ -196,6 +196,12 @@ impl<'a, 'gcx, 'tcx> StableHashingContext<'a, 'gcx, 'tcx> {
     }
 }
 
+impl<'a, 'gcx, 'lcx> StableHashingContextProvider for ty::TyCtxt<'a, 'gcx, 'lcx> {
+    type ContextType = StableHashingContext<'a, 'gcx, 'lcx>;
+    fn create_stable_hashing_context(&self) -> Self::ContextType {
+        StableHashingContext::new(*self)
+    }
+}
 
 impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ast::NodeId {
     fn hash_stable<W: StableHasherResult>(&self,
diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs
index 48502dc2e8c84..c96ae862265df 100644
--- a/src/librustc/ty/maps.rs
+++ b/src/librustc/ty/maps.rs
@@ -14,7 +14,6 @@ use hir::def_id::{CrateNum, DefId, LOCAL_CRATE, DefIndex};
 use hir::def::{Def, Export};
 use hir::{self, TraitCandidate, ItemLocalId};
 use hir::svh::Svh;
-use ich::{Fingerprint, StableHashingContext};
 use lint;
 use middle::const_val;
 use middle::cstore::{ExternCrate, LinkagePreference, NativeLibrary};
@@ -46,7 +45,7 @@ use rustc_back::PanicStrategy;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use std::cell::{RefCell, RefMut, Cell};
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+
 use std::fmt::Debug;
 use std::hash::Hash;
 use std::marker::PhantomData;
@@ -953,20 +952,6 @@ macro_rules! define_maps {
 
                 tcx.dep_graph.read_index(dep_node_index);
 
-                // In incremental mode, hash the result of the query. We don't
-                // do anything with the hash yet, but we are computing it
-                // anyway so that
-                //  - we make sure that the infrastructure works and
-                //  - we can get an idea of the runtime cost.
-                if !dep_node.kind.is_anon() && tcx.sess.opts.incremental.is_some() {
-                    let mut hcx = StableHashingContext::new(tcx);
-                    let mut hasher = StableHasher::new();
-
-                    result.hash_stable(&mut hcx, &mut hasher);
-
-                    let _: Fingerprint = hasher.finish();
-                }
-
                 let value = QueryValue {
                     value: result,
                     index: dep_node_index,
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index e2df963f80fad..da00f12edacb0 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -2575,6 +2575,10 @@ pub struct SymbolName {
     pub name: InternedString
 }
 
+impl_stable_hash_for!(struct self::SymbolName {
+    name
+});
+
 impl Deref for SymbolName {
     type Target = str;
 
diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs
index 0d0cf67248944..f80cbfadf2e7f 100644
--- a/src/librustc_data_structures/stable_hasher.rs
+++ b/src/librustc_data_structures/stable_hasher.rs
@@ -192,6 +192,28 @@ impl<W> Hasher for StableHasher<W> {
 }
 
 
+/// Something that can provide a stable hashing context.
+pub trait StableHashingContextProvider {
+    type ContextType;
+    fn create_stable_hashing_context(&self) -> Self::ContextType;
+}
+
+impl<'a, T: StableHashingContextProvider> StableHashingContextProvider for &'a T {
+    type ContextType = T::ContextType;
+
+    fn create_stable_hashing_context(&self) -> Self::ContextType {
+        (**self).create_stable_hashing_context()
+    }
+}
+
+impl<'a, T: StableHashingContextProvider> StableHashingContextProvider for &'a mut T {
+    type ContextType = T::ContextType;
+
+    fn create_stable_hashing_context(&self) -> Self::ContextType {
+        (**self).create_stable_hashing_context()
+    }
+}
+
 /// Something that implements `HashStable<CTX>` can be hashed in a way that is
 /// stable across multiple compilation sessions.
 pub trait HashStable<CTX> {
@@ -292,7 +314,7 @@ impl<T: HashStable<CTX>, CTX> HashStable<CTX> for Vec<T> {
     }
 }
 
-impl<T: HashStable<CTX>, CTX> HashStable<CTX> for Box<T> {
+impl<T: ?Sized + HashStable<CTX>, CTX> HashStable<CTX> for Box<T> {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
                                           ctx: &mut CTX,
@@ -301,7 +323,7 @@ impl<T: HashStable<CTX>, CTX> HashStable<CTX> for Box<T> {
     }
 }
 
-impl<T: HashStable<CTX>, CTX> HashStable<CTX> for ::std::rc::Rc<T> {
+impl<T: ?Sized + HashStable<CTX>, CTX> HashStable<CTX> for ::std::rc::Rc<T> {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
                                           ctx: &mut CTX,
@@ -310,7 +332,7 @@ impl<T: HashStable<CTX>, CTX> HashStable<CTX> for ::std::rc::Rc<T> {
     }
 }
 
-impl<T: HashStable<CTX>, CTX> HashStable<CTX> for ::std::sync::Arc<T> {
+impl<T: ?Sized + HashStable<CTX>, CTX> HashStable<CTX> for ::std::sync::Arc<T> {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
                                           ctx: &mut CTX,
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index d86f88d4c7da0..1e1b9929f0e37 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -1070,7 +1070,6 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         let start_time = Instant::now();
         all_stats.extend(tcx.compile_codegen_unit(*cgu.name()));
         total_trans_time += start_time.elapsed();
-
         ongoing_translation.check_for_errors(tcx.sess);
     }
 
@@ -1565,5 +1564,35 @@ pub fn visibility_to_llvm(linkage: Visibility) -> llvm::Visibility {
         Visibility::Default => llvm::Visibility::Default,
         Visibility::Hidden => llvm::Visibility::Hidden,
         Visibility::Protected => llvm::Visibility::Protected,
+}
+
+// FIXME(mw): Anything that is produced via DepGraph::with_task() must implement
+//            the HashStable trait. Normally DepGraph::with_task() calls are
+//            hidden behind queries, but CGU creation is a special case in two
+//            ways: (1) it's not a query and (2) CGU are output nodes, so their
+//            Fingerprints are not actually needed. It remains to be clarified
+//            how exactly this case will be handled in the red/green system but
+//            for now we content ourselves with providing a no-op HashStable
+//            implementation for CGUs.
+mod temp_stable_hash_impls {
+    use rustc_data_structures::stable_hasher::{StableHasherResult, StableHasher,
+                                               HashStable};
+    use context::Stats;
+    use ModuleTranslation;
+
+    impl<HCX> HashStable<HCX> for Stats {
+        fn hash_stable<W: StableHasherResult>(&self,
+                                              _: &mut HCX,
+                                              _: &mut StableHasher<W>) {
+            // do nothing
+        }
+    }
+
+    impl<HCX> HashStable<HCX> for ModuleTranslation {
+        fn hash_stable<W: StableHasherResult>(&self,
+                                              _: &mut HCX,
+                                              _: &mut StableHasher<W>) {
+            // do nothing
+        }
     }
 }
diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs
index 8b18bf2e1ff1f..40fc07cfd4f62 100644
--- a/src/librustc_trans/context.rs
+++ b/src/librustc_trans/context.rs
@@ -14,6 +14,7 @@ use llvm::{ContextRef, ModuleRef, ValueRef};
 use rustc::dep_graph::{DepGraph, DepGraphSafe};
 use rustc::hir;
 use rustc::hir::def_id::DefId;
+use rustc::ich::StableHashingContext;
 use rustc::traits;
 use debuginfo;
 use callee;
@@ -25,6 +26,8 @@ use partitioning::CodegenUnit;
 use type_::Type;
 use rustc_data_structures::base_n;
 use rustc::middle::trans::Stats;
+use rustc_data_structures::stable_hasher::StableHashingContextProvider;
+use rustc::session::config::{self, NoDebugInfo, OutputFilenames};
 use rustc::session::Session;
 use rustc::session::config::{self, NoDebugInfo};
 use rustc::ty::layout::{LayoutCx, LayoutError, LayoutTyper, TyLayout};
@@ -134,6 +137,17 @@ impl<'a, 'tcx> CrateContext<'a, 'tcx> {
 impl<'a, 'tcx> DepGraphSafe for CrateContext<'a, 'tcx> {
 }
 
+impl<'a, 'tcx> DepGraphSafe for SharedCrateContext<'a, 'tcx> {
+}
+
+impl<'a, 'tcx> StableHashingContextProvider for SharedCrateContext<'a, 'tcx> {
+    type ContextType = StableHashingContext<'a, 'tcx, 'tcx>;
+
+    fn create_stable_hashing_context(&self) -> Self::ContextType {
+        StableHashingContext::new(self.tcx)
+    }
+}
+
 pub fn get_reloc_model(sess: &Session) -> llvm::RelocMode {
     let reloc_model_arg = match sess.opts.cg.relocation_model {
         Some(ref s) => &s[..],
diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs
index 70b989b6ab21c..4918dd78b3793 100644
--- a/src/librustc_typeck/variance/constraints.rs
+++ b/src/librustc_typeck/variance/constraints.rs
@@ -14,7 +14,8 @@
 //! We walk the set of items and, for each member, generate new constraints.
 
 use hir::def_id::DefId;
-use rustc::dep_graph::{AssertDepGraphSafe, DepKind};
+use rustc::dep_graph::{DepGraphSafe, DepKind};
+use rustc::ich::StableHashingContext;
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, Ty, TyCtxt};
 use syntax::ast;
@@ -22,6 +23,7 @@ use rustc::hir;
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
 
 use rustc_data_structures::transitive_relation::TransitiveRelation;
+use rustc_data_structures::stable_hasher::StableHashingContextProvider;
 
 use super::terms::*;
 use super::terms::VarianceTerm::*;
@@ -138,6 +140,16 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> {
     }
 }
 
+impl<'a, 'tcx> StableHashingContextProvider for ConstraintContext<'a, 'tcx> {
+    type ContextType = StableHashingContext<'a, 'tcx, 'tcx>;
+
+    fn create_stable_hashing_context(&self) -> Self::ContextType {
+         StableHashingContext::new(self.terms_cx.tcx)
+    }
+}
+
+impl<'a, 'tcx> DepGraphSafe for ConstraintContext<'a, 'tcx> {}
+
 impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
     fn visit_node_helper(&mut self, id: ast::NodeId) {
         let tcx = self.terms_cx.tcx;
@@ -151,14 +163,14 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
         // on dep-graph management.
         let dep_node = def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints);
         tcx.dep_graph.with_task(dep_node,
-                                AssertDepGraphSafe(self),
+                                self,
                                 def_id,
                                 visit_item_task);
 
-        fn visit_item_task<'a, 'tcx>(ccx: AssertDepGraphSafe<&mut ConstraintContext<'a, 'tcx>>,
+        fn visit_item_task<'a, 'tcx>(ccx: &mut ConstraintContext<'a, 'tcx>,
                                      def_id: DefId)
         {
-            ccx.0.build_constraints_for_item(def_id);
+            ccx.build_constraints_for_item(def_id);
         }
     }
 

From e3f913167c0f232478b945aa236aab8340be62a9 Mon Sep 17 00:00:00 2001
From: Michael Woerister <michaelwoerister@posteo>
Date: Tue, 12 Sep 2017 17:07:09 +0200
Subject: [PATCH 15/24] Fix issues uncovered by rebasing:

- Don't hash traits in scope as part of HIR hashing any more.
- Some queries returned DefIndexes from other crates.
- Provide a generic way of stably hashing maps (not used everywhere yet).
---
 src/librustc/dep_graph/dep_node.rs            |  12 ++
 src/librustc/ich/hcx.rs                       |  44 ++--
 src/librustc/ich/impls_cstore.rs              |   6 +
 src/librustc/ich/impls_hir.rs                 | 200 +++++++++---------
 src/librustc/ich/impls_misc.rs                |  26 +++
 src/librustc/ich/impls_syntax.rs              |  30 ++-
 src/librustc/ich/mod.rs                       |   1 +
 src/librustc/middle/cstore.rs                 |   2 +-
 src/librustc/middle/lang_items.rs             |   3 +-
 src/librustc/middle/stability.rs              |  12 ++
 src/librustc/ty/context.rs                    |  25 +--
 src/librustc/ty/maps.rs                       |   2 +-
 src/librustc_data_structures/stable_hasher.rs |  87 ++++++--
 src/librustc_incremental/calculate_svh/mod.rs |  53 +++--
 src/librustc_incremental/persist/hash.rs      |   2 +
 src/librustc_incremental/persist/load.rs      |   1 +
 src/librustc_metadata/creader.rs              |   5 +-
 src/librustc_metadata/cstore_impl.rs          |   2 +-
 src/librustc_metadata/decoder.rs              |   3 +-
 src/librustc_metadata/native_libs.rs          |   2 +-
 src/librustc_mir/transform/erase_regions.rs   |  42 +---
 .../ich_method_call_trait_scope.rs            |   5 +-
 22 files changed, 328 insertions(+), 237 deletions(-)
 create mode 100644 src/librustc/ich/impls_misc.rs

diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 06469c16bc22e..1dcc9272d4e02 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -633,6 +633,18 @@ impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefId,) {
     }
 }
 
+impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefIndex,) {
+    const CAN_RECONSTRUCT_QUERY_KEY: bool = true;
+
+    fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint {
+        tcx.hir.definitions().def_path_hash(self.0).0
+    }
+
+    fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String {
+        tcx.item_path_str(DefId::local(self.0))
+    }
+}
+
 impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefId, DefId) {
     const CAN_RECONSTRUCT_QUERY_KEY: bool = false;
 
diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs
index f4fa376347ae9..daf1ff8ad2b95 100644
--- a/src/librustc/ich/hcx.rs
+++ b/src/librustc/ich/hcx.rs
@@ -27,7 +27,8 @@ use syntax::symbol::Symbol;
 use syntax_pos::Span;
 
 use rustc_data_structures::stable_hasher::{HashStable, StableHashingContextProvider,
-                                           StableHasher, StableHasherResult};
+                                           StableHasher, StableHasherResult,
+                                           ToStableHashKey};
 use rustc_data_structures::accumulate_vec::AccumulateVec;
 
 /// This is the context state available during incr. comp. hashing. It contains
@@ -48,9 +49,7 @@ pub struct StableHashingContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
 #[derive(PartialEq, Eq, Clone, Copy)]
 pub enum NodeIdHashingMode {
     Ignore,
-    CheckedIgnore,
     HashDefPath,
-    HashTraitsInScope,
 }
 
 impl<'a, 'gcx, 'tcx> StableHashingContext<'a, 'gcx, 'tcx> {
@@ -150,7 +149,7 @@ impl<'a, 'gcx, 'tcx> StableHashingContext<'a, 'gcx, 'tcx> {
             self.overflow_checks_enabled = true;
         }
         let prev_hash_node_ids = self.node_id_hashing_mode;
-        self.node_id_hashing_mode = NodeIdHashingMode::CheckedIgnore;
+        self.node_id_hashing_mode = NodeIdHashingMode::Ignore;
 
         f(self);
 
@@ -207,41 +206,28 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ast::N
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
                                           hasher: &mut StableHasher<W>) {
-        let hir_id = hcx.tcx.hir.node_to_hir_id(*self);
         match hcx.node_id_hashing_mode {
             NodeIdHashingMode::Ignore => {
                 // Don't do anything.
             }
-            NodeIdHashingMode::CheckedIgnore => {
-                // Most NodeIds in the HIR can be ignored, but if there is a
-                // corresponding entry in the `trait_map` we need to hash that.
-                // Make sure we don't ignore too much by checking that there is
-                // no entry in a debug_assert!().
-                debug_assert!(hcx.tcx.in_scope_traits(hir_id).is_none());
-            }
             NodeIdHashingMode::HashDefPath => {
-                hir_id.hash_stable(hcx, hasher);
-            }
-            NodeIdHashingMode::HashTraitsInScope => {
-                if let Some(traits) = hcx.tcx.in_scope_traits(hir_id) {
-                    // The ordering of the candidates is not fixed. So we hash
-                    // the def-ids and then sort them and hash the collection.
-                    let mut candidates: AccumulateVec<[_; 8]> =
-                        traits.iter()
-                              .map(|&hir::TraitCandidate { def_id, import_id: _ }| {
-                                  hcx.def_path_hash(def_id)
-                              })
-                              .collect();
-                    if traits.len() > 1 {
-                        candidates.sort();
-                    }
-                    candidates.hash_stable(hcx, hasher);
-                }
+                hcx.tcx.hir.node_to_hir_id(*self).hash_stable(hcx, hasher);
             }
         }
     }
 }
 
+impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>> for ast::NodeId {
+    type KeyType = (DefPathHash, hir::ItemLocalId);
+
+    #[inline]
+    fn to_stable_hash_key(&self,
+                          hcx: &StableHashingContext<'a, 'gcx, 'tcx>)
+                          -> (DefPathHash, hir::ItemLocalId) {
+        hcx.tcx.hir.node_to_hir_id(*self).to_stable_hash_key(hcx)
+    }
+}
+
 impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for Span {
 
     // Hash a span in a stable way. We can't directly hash the span's BytePos
diff --git a/src/librustc/ich/impls_cstore.rs b/src/librustc/ich/impls_cstore.rs
index dad5c35c1e814..057a83ebbe352 100644
--- a/src/librustc/ich/impls_cstore.rs
+++ b/src/librustc/ich/impls_cstore.rs
@@ -45,3 +45,9 @@ impl_stable_hash_for!(struct middle::cstore::ExternCrate {
     direct,
     path_len
 });
+
+impl_stable_hash_for!(struct middle::cstore::CrateSource {
+    dylib,
+    rlib,
+    rmeta
+});
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index a4cbcf0411199..9da147472ce4e 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -12,13 +12,13 @@
 //! types in no particular order.
 
 use hir;
+use hir::map::DefPathHash;
 use hir::def_id::{DefId, CrateNum, CRATE_DEF_INDEX};
-use ich::{self, StableHashingContext, NodeIdHashingMode};
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
-                                           StableHasherResult};
+use ich::{StableHashingContext, NodeIdHashingMode};
+use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey,
+                                           StableHasher, StableHasherResult};
 use std::mem;
 use syntax::ast;
-use util::nodemap::DefIdSet;
 
 impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for DefId {
     #[inline]
@@ -29,14 +29,12 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for DefId
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for DefIdSet
-{
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
-                                          hasher: &mut StableHasher<W>) {
-        ich::hash_stable_hashset(hcx, hasher, self, |hcx, def_id| {
-            hcx.def_path_hash(*def_id)
-        });
+impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>> for DefId {
+    type KeyType = DefPathHash;
+
+    #[inline]
+    fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a, 'gcx, 'tcx>) -> DefPathHash {
+        hcx.tcx().def_path_hash(*self)
     }
 }
 
@@ -50,11 +48,22 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::H
             local_id,
         } = *self;
 
-        hcx.def_path_hash(DefId::local(owner)).hash_stable(hcx, hasher);
+        hcx.tcx().hir.definitions().def_path_hash(owner).hash_stable(hcx, hasher);
         local_id.hash_stable(hcx, hasher);
     }
 }
 
+impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>> for hir::HirId {
+    type KeyType = (DefPathHash, hir::ItemLocalId);
+
+    #[inline]
+    fn to_stable_hash_key(&self,
+                          hcx: &StableHashingContext<'a, 'gcx, 'tcx>)
+                          -> (DefPathHash, hir::ItemLocalId) {
+        let def_path_hash = hcx.tcx().hir.definitions().def_path_hash(self.owner);
+        (def_path_hash, self.local_id)
+    }
+}
 
 impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for CrateNum {
     #[inline]
@@ -68,8 +77,30 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for CrateN
     }
 }
 
+impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>> for CrateNum {
+    type KeyType = DefPathHash;
+
+    #[inline]
+    fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a, 'gcx, 'tcx>) -> DefPathHash {
+        let def_id = DefId { krate: *self, index: CRATE_DEF_INDEX };
+        def_id.to_stable_hash_key(hcx)
+    }
+}
+
 impl_stable_hash_for!(tuple_struct hir::ItemLocalId { index });
 
+impl<'a, 'gcx, 'lcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'lcx>>
+for hir::ItemLocalId {
+    type KeyType = hir::ItemLocalId;
+
+    #[inline]
+    fn to_stable_hash_key(&self,
+                          _: &StableHashingContext<'a, 'gcx, 'lcx>)
+                          -> hir::ItemLocalId {
+        *self
+    }
+}
+
 // The following implementations of HashStable for ItemId, TraitItemId, and
 // ImplItemId deserve special attention. Normally we do not hash NodeIds within
 // the HIR, since they just signify a HIR nodes own path. But ItemId et al
@@ -231,36 +262,13 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::T
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
                                           hasher: &mut StableHasher<W>) {
-        let node_id_hashing_mode = match self.node {
-            hir::TySlice(..)       |
-            hir::TyArray(..)       |
-            hir::TyPtr(..)         |
-            hir::TyRptr(..)        |
-            hir::TyBareFn(..)      |
-            hir::TyNever           |
-            hir::TyTup(..)         |
-            hir::TyTraitObject(..) |
-            hir::TyImplTrait(..)   |
-            hir::TyTypeof(..)      |
-            hir::TyErr             |
-            hir::TyInfer           => {
-                NodeIdHashingMode::CheckedIgnore
-            }
-            hir::TyPath(..) => {
-                NodeIdHashingMode::HashTraitsInScope
-            }
-        };
-
         hcx.while_hashing_hir_bodies(true, |hcx| {
             let hir::Ty {
-                id,
+                id: _,
                 ref node,
                 ref span,
             } = *self;
 
-            hcx.with_node_id_hashing_mode(node_id_hashing_mode, |hcx| {
-                id.hash_stable(hcx, hasher);
-            });
             node.hash_stable(hcx, hasher);
             span.hash_stable(hcx, hasher);
         })
@@ -317,13 +325,11 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::T
                                           hasher: &mut StableHasher<W>) {
         let hir::TraitRef {
             ref path,
-            ref_id,
+            // Don't hash the ref_id. It is tracked via the thing it is used to access
+            ref_id: _,
         } = *self;
 
         path.hash_stable(hcx, hasher);
-        hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashTraitsInScope, |hcx| {
-            ref_id.hash_stable(hcx, hasher);
-        });
     }
 }
 
@@ -357,7 +363,7 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::B
         let hir::Block {
             ref stmts,
             ref expr,
-            id,
+            id: _,
             hir_id: _,
             rules,
             span,
@@ -392,7 +398,6 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::B
         }
 
         expr.hash_stable(hcx, hasher);
-        id.hash_stable(hcx, hasher);
         rules.hash_stable(hcx, hasher);
         span.hash_stable(hcx, hasher);
         targeted_by_break.hash_stable(hcx, hasher);
@@ -403,34 +408,13 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::P
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
                                           hasher: &mut StableHasher<W>) {
-        let node_id_hashing_mode = match self.node {
-            hir::PatKind::Wild        |
-            hir::PatKind::Binding(..) |
-            hir::PatKind::Tuple(..)   |
-            hir::PatKind::Box(..)     |
-            hir::PatKind::Ref(..)     |
-            hir::PatKind::Lit(..)     |
-            hir::PatKind::Range(..)   |
-            hir::PatKind::Slice(..)   => {
-                NodeIdHashingMode::CheckedIgnore
-            }
-            hir::PatKind::Path(..)        |
-            hir::PatKind::Struct(..)      |
-            hir::PatKind::TupleStruct(..) => {
-                NodeIdHashingMode::HashTraitsInScope
-            }
-        };
-
         let hir::Pat {
-            id,
+            id: _,
             hir_id: _,
             ref node,
             ref span
         } = *self;
 
-        hcx.with_node_id_hashing_mode(node_id_hashing_mode, |hcx| {
-            id.hash_stable(hcx, hasher);
-        });
         node.hash_stable(hcx, hasher);
         span.hash_stable(hcx, hasher);
     }
@@ -552,14 +536,14 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::E
                                           hasher: &mut StableHasher<W>) {
         hcx.while_hashing_hir_bodies(true, |hcx| {
             let hir::Expr {
-                id,
+                id: _,
                 hir_id: _,
                 ref span,
                 ref node,
                 ref attrs
             } = *self;
 
-            let (spans_always_on, node_id_hashing_mode) = match *node {
+            let spans_always_on = match *node {
                 hir::ExprBox(..)        |
                 hir::ExprArray(..)      |
                 hir::ExprCall(..)       |
@@ -578,41 +562,33 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::E
                 hir::ExprBreak(..)      |
                 hir::ExprAgain(..)      |
                 hir::ExprRet(..)        |
-                hir::ExprYield(..)    |
+                hir::ExprYield(..)      |
                 hir::ExprInlineAsm(..)  |
                 hir::ExprRepeat(..)     |
-                hir::ExprTup(..)        => {
+                hir::ExprTup(..)        |
+                hir::ExprMethodCall(..) |
+                hir::ExprPath(..)       |
+                hir::ExprStruct(..)     |
+                hir::ExprField(..)      => {
                     // For these we only hash the span when debuginfo is on.
-                    (false, NodeIdHashingMode::CheckedIgnore)
+                    false
                 }
                 // For the following, spans might be significant because of
                 // panic messages indicating the source location.
                 hir::ExprBinary(op, ..) => {
-                    (hcx.binop_can_panic_at_runtime(op.node), NodeIdHashingMode::CheckedIgnore)
+                    hcx.binop_can_panic_at_runtime(op.node)
                 }
                 hir::ExprUnary(op, _) => {
-                    (hcx.unop_can_panic_at_runtime(op), NodeIdHashingMode::CheckedIgnore)
+                    hcx.unop_can_panic_at_runtime(op)
                 }
                 hir::ExprAssignOp(op, ..) => {
-                    (hcx.binop_can_panic_at_runtime(op.node), NodeIdHashingMode::CheckedIgnore)
+                    hcx.binop_can_panic_at_runtime(op.node)
                 }
                 hir::ExprIndex(..) => {
-                    (true, NodeIdHashingMode::CheckedIgnore)
-                }
-                // For these we don't care about the span, but want to hash the
-                // trait in scope
-                hir::ExprMethodCall(..) |
-                hir::ExprPath(..)       |
-                hir::ExprStruct(..)     |
-                hir::ExprField(..)      => {
-                    (false, NodeIdHashingMode::HashTraitsInScope)
+                    true
                 }
             };
 
-            hcx.with_node_id_hashing_mode(node_id_hashing_mode, |hcx| {
-                id.hash_stable(hcx, hasher);
-            });
-
             if spans_always_on {
                 hcx.while_hashing_spans(true, |hcx| {
                     span.hash_stable(hcx, hasher);
@@ -815,7 +791,7 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::V
                 // No fields to hash.
             }
             hir::Visibility::Restricted { ref path, id } => {
-                hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashTraitsInScope, |hcx| {
+                hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
                     id.hash_stable(hcx, hasher);
                 });
                 path.hash_stable(hcx, hasher);
@@ -904,16 +880,13 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::I
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
                                           hasher: &mut StableHasher<W>) {
-        let (node_id_hashing_mode, hash_spans) = match self.node {
+        let hash_spans = match self.node {
             hir::ItemStatic(..)      |
             hir::ItemConst(..)       |
             hir::ItemFn(..)          => {
-                (NodeIdHashingMode::CheckedIgnore, hcx.hash_spans())
+                hcx.hash_spans()
             }
-            hir::ItemUse(..) => {
-                (NodeIdHashingMode::HashTraitsInScope, false)
-            }
-
+            hir::ItemUse(..)         |
             hir::ItemExternCrate(..) |
             hir::ItemForeignMod(..)  |
             hir::ItemGlobalAsm(..)   |
@@ -925,14 +898,14 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::I
             hir::ItemEnum(..)        |
             hir::ItemStruct(..)      |
             hir::ItemUnion(..)       => {
-                (NodeIdHashingMode::CheckedIgnore, false)
+                false
             }
         };
 
         let hir::Item {
             name,
             ref attrs,
-            id,
+            id: _,
             hir_id: _,
             ref node,
             ref vis,
@@ -941,9 +914,6 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::I
 
         hcx.hash_hir_item_like(attrs, |hcx| {
             hcx.while_hashing_spans(hash_spans, |hcx| {
-                hcx.with_node_id_hashing_mode(node_id_hashing_mode, |hcx| {
-                    id.hash_stable(hcx, hasher);
-                });
                 name.hash_stable(hcx, hasher);
                 attrs.hash_stable(hcx, hasher);
                 node.hash_stable(hcx, hasher);
@@ -1049,6 +1019,18 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::B
     }
 }
 
+impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>> for hir::BodyId {
+    type KeyType = (DefPathHash, hir::ItemLocalId);
+
+    #[inline]
+    fn to_stable_hash_key(&self,
+                          hcx: &StableHashingContext<'a, 'gcx, 'tcx>)
+                          -> (DefPathHash, hir::ItemLocalId) {
+        let hir::BodyId { node_id } = *self;
+        node_id.to_stable_hash_key(hcx)
+    }
+}
+
 impl_stable_hash_for!(struct hir::InlineAsmOutput {
     constraint,
     is_rw,
@@ -1151,7 +1133,17 @@ for hir::def_id::DefIndex {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
                                           hasher: &mut StableHasher<W>) {
-        DefId::local(*self).hash_stable(hcx, hasher);
+        hcx.tcx().hir.definitions().def_path_hash(*self).hash_stable(hcx, hasher);
+    }
+}
+
+impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>>
+for hir::def_id::DefIndex {
+    type KeyType = DefPathHash;
+
+    #[inline]
+    fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a, 'gcx, 'tcx>) -> DefPathHash {
+         hcx.tcx().hir.definitions().def_path_hash(*self)
     }
 }
 
@@ -1170,6 +1162,11 @@ for ::middle::lang_items::LangItem {
     }
 }
 
+impl_stable_hash_for!(struct ::middle::lang_items::LanguageItems {
+    items,
+    missing
+});
+
 impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
 for hir::TraitCandidate {
     fn hash_stable<W: StableHasherResult>(&self,
@@ -1186,3 +1183,8 @@ for hir::TraitCandidate {
         });
     }
 }
+
+impl_stable_hash_for!(struct hir::Freevar {
+    def,
+    span
+});
diff --git a/src/librustc/ich/impls_misc.rs b/src/librustc/ich/impls_misc.rs
new file mode 100644
index 0000000000000..951315fb4a849
--- /dev/null
+++ b/src/librustc/ich/impls_misc.rs
@@ -0,0 +1,26 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! This module contains `HashStable` implementations for various data types
+//! that don't fit into any of the other impls_xxx modules.
+
+impl_stable_hash_for!(enum ::session::search_paths::PathKind {
+    Native,
+    Crate,
+    Dependency,
+    Framework,
+    ExternFlag,
+    All
+});
+
+impl_stable_hash_for!(enum ::rustc_back::PanicStrategy {
+    Abort,
+    Unwind
+});
diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs
index e52be70190c81..a75527c14bd69 100644
--- a/src/librustc/ich/impls_syntax.rs
+++ b/src/librustc/ich/impls_syntax.rs
@@ -18,17 +18,17 @@ use std::mem;
 
 use syntax::ast;
 use syntax::parse::token;
+use syntax::symbol::InternedString;
 use syntax::tokenstream;
 use syntax_pos::{Span, FileMap};
 
 use hir::def_id::{DefId, CrateNum, CRATE_DEF_INDEX};
 
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
-                                           StableHasherResult};
+use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey,
+                                           StableHasher, StableHasherResult};
 use rustc_data_structures::accumulate_vec::AccumulateVec;
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
-for ::syntax::symbol::InternedString {
+impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for InternedString {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
@@ -38,6 +38,17 @@ for ::syntax::symbol::InternedString {
     }
 }
 
+impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>> for InternedString {
+    type KeyType = InternedString;
+
+    #[inline]
+    fn to_stable_hash_key(&self,
+                          _: &StableHashingContext<'a, 'gcx, 'tcx>)
+                          -> InternedString {
+        self.clone()
+    }
+}
+
 impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ast::Name {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
@@ -47,6 +58,17 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ast::N
     }
 }
 
+impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>> for ast::Name {
+    type KeyType = InternedString;
+
+    #[inline]
+    fn to_stable_hash_key(&self,
+                          _: &StableHashingContext<'a, 'gcx, 'tcx>)
+                          -> InternedString {
+        self.as_str()
+    }
+}
+
 impl_stable_hash_for!(enum ::syntax::ast::AsmDialect {
     Att,
     Intel
diff --git a/src/librustc/ich/mod.rs b/src/librustc/ich/mod.rs
index c24064eb27c58..5558534b71d2e 100644
--- a/src/librustc/ich/mod.rs
+++ b/src/librustc/ich/mod.rs
@@ -24,6 +24,7 @@ mod impls_const_math;
 mod impls_cstore;
 mod impls_hir;
 mod impls_mir;
+mod impls_misc;
 mod impls_ty;
 mod impls_syntax;
 
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index bea6ef4dc11ce..7c60c6d6430e1 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -132,7 +132,7 @@ pub struct NativeLibrary {
     pub kind: NativeLibraryKind,
     pub name: Symbol,
     pub cfg: Option<ast::MetaItem>,
-    pub foreign_items: Vec<DefIndex>,
+    pub foreign_items: Vec<DefId>,
 }
 
 pub enum LoadedMacro {
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index 7a6f4fdbb03ac..0c0b9697338e9 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -192,8 +192,7 @@ pub fn extract(attrs: &[ast::Attribute]) -> Option<Symbol> {
 pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItems {
     let mut collector = LanguageItemCollector::new(tcx);
     for &cnum in tcx.crates().iter() {
-        for &(index, item_index) in tcx.defined_lang_items(cnum).iter() {
-            let def_id = DefId { krate: cnum, index: index };
+        for &(def_id, item_index) in tcx.defined_lang_items(cnum).iter() {
             collector.collect_item(item_index, def_id);
         }
     }
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index 977102ec1adca..89049958309a1 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -65,6 +65,11 @@ pub struct DeprecationEntry {
     origin: Option<HirId>,
 }
 
+impl_stable_hash_for!(struct self::DeprecationEntry {
+    attr,
+    origin
+});
+
 impl DeprecationEntry {
     fn local(attr: Deprecation, id: HirId) -> DeprecationEntry {
         DeprecationEntry {
@@ -102,6 +107,13 @@ pub struct Index<'tcx> {
     active_features: FxHashSet<Symbol>,
 }
 
+impl_stable_hash_for!(struct self::Index<'tcx> {
+    stab_map,
+    depr_map,
+    staged_api,
+    active_features
+});
+
 // A private tree-walker for producing an Index.
 struct Annotator<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 945a081442750..7edc55e8a9fe4 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -1083,6 +1083,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             None
         };
 
+        // FIXME(mw): Each of the Vecs in the trait_map should be brought into
+        // a deterministic order here. Otherwise we might end up with
+        // unnecessarily unstable incr. comp. hashes.
         let mut trait_map = FxHashMap();
         for (k, v) in resolutions.trait_map {
             let hir_id = hir.node_to_hir_id(k);
@@ -1171,17 +1174,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     }
 
     pub fn lang_items(self) -> Rc<middle::lang_items::LanguageItems> {
-        // FIXME(#42293) Right now we insert a `with_ignore` node in the dep
-        // graph here to ignore the fact that `get_lang_items` below depends on
-        // the entire crate.  For now this'll prevent false positives of
-        // recompiling too much when anything changes.
-        //
-        // Once red/green incremental compilation lands we should be able to
-        // remove this because while the crate changes often the lint level map
-        // will change rarely.
-        self.dep_graph.with_ignore(|| {
-            self.get_lang_items(LOCAL_CRATE)
-        })
+        self.get_lang_items(LOCAL_CRATE)
     }
 
     pub fn stability(self) -> Rc<stability::Index<'tcx>> {
@@ -2198,7 +2191,15 @@ pub fn provide(providers: &mut ty::maps::Providers) {
     };
     providers.get_lang_items = |tcx, id| {
         assert_eq!(id, LOCAL_CRATE);
-        Rc::new(middle::lang_items::collect(tcx))
+        // FIXME(#42293) Right now we insert a `with_ignore` node in the dep
+        // graph here to ignore the fact that `get_lang_items` below depends on
+        // the entire crate.  For now this'll prevent false positives of
+        // recompiling too much when anything changes.
+        //
+        // Once red/green incremental compilation lands we should be able to
+        // remove this because while the crate changes often the lint level map
+        // will change rarely.
+        tcx.dep_graph.with_ignore(|| Rc::new(middle::lang_items::collect(tcx)))
     };
     providers.freevars = |tcx, id| tcx.gcx.freevars.get(&id).cloned();
     providers.maybe_unused_trait_import = |tcx, id| {
diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs
index c96ae862265df..fc803d1c849b5 100644
--- a/src/librustc/ty/maps.rs
+++ b/src/librustc/ty/maps.rs
@@ -1400,7 +1400,7 @@ define_maps! { <'tcx>
     [] fn extern_mod_stmt_cnum: ExternModStmtCnum(DefId) -> Option<CrateNum>,
 
     [] fn get_lang_items: get_lang_items_node(CrateNum) -> Rc<LanguageItems>,
-    [] fn defined_lang_items: DefinedLangItems(CrateNum) -> Rc<Vec<(DefIndex, usize)>>,
+    [] fn defined_lang_items: DefinedLangItems(CrateNum) -> Rc<Vec<(DefId, usize)>>,
     [] fn missing_lang_items: MissingLangItems(CrateNum) -> Rc<Vec<LangItem>>,
     [] fn extern_const_body: ExternConstBody(DefId) -> &'tcx hir::Body,
     [] fn visible_parent_map: visible_parent_map_node(CrateNum)
diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs
index f80cbfadf2e7f..1b2d09bef934c 100644
--- a/src/librustc_data_structures/stable_hasher.rs
+++ b/src/librustc_data_structures/stable_hasher.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::hash::{Hash, Hasher};
+use std::hash::{Hash, Hasher, BuildHasher};
 use std::marker::PhantomData;
 use std::mem;
 use blake2b::Blake2bHasher;
@@ -222,6 +222,14 @@ pub trait HashStable<CTX> {
                                           hasher: &mut StableHasher<W>);
 }
 
+/// Implement this for types that can be turned into stable keys like, for
+/// example, for DefId that can be converted to a DefPathHash. This is used for
+/// bringing maps into a predictable order before hashing them.
+pub trait ToStableHashKey<HCX> {
+    type KeyType: Ord + Clone + Sized + HashStable<HCX>;
+    fn to_stable_hash_key(&self, hcx: &HCX) -> Self::KeyType;
+}
+
 // Implement HashStable by just calling `Hash::hash()`. This works fine for
 // self-contained values that don't depend on the hashing context `CTX`.
 macro_rules! impl_stable_hash_via_hash {
@@ -423,53 +431,88 @@ impl<T, CTX> HashStable<CTX> for ::std::mem::Discriminant<T> {
     }
 }
 
-impl<K, V, CTX> HashStable<CTX> for ::std::collections::BTreeMap<K, V>
-    where K: Ord + HashStable<CTX>,
-          V: HashStable<CTX>,
+impl<I: ::indexed_vec::Idx, T, CTX> HashStable<CTX> for ::indexed_vec::IndexVec<I, T>
+    where T: HashStable<CTX>,
 {
     fn hash_stable<W: StableHasherResult>(&self,
                                           ctx: &mut CTX,
                                           hasher: &mut StableHasher<W>) {
         self.len().hash_stable(ctx, hasher);
-        for (k, v) in self {
-            k.hash_stable(ctx, hasher);
+        for v in &self.raw {
             v.hash_stable(ctx, hasher);
         }
     }
 }
 
-impl<T, CTX> HashStable<CTX> for ::std::collections::BTreeSet<T>
-    where T: Ord + HashStable<CTX>,
+
+impl<I: ::indexed_vec::Idx, CTX> HashStable<CTX> for ::indexed_set::IdxSetBuf<I>
 {
     fn hash_stable<W: StableHasherResult>(&self,
                                           ctx: &mut CTX,
                                           hasher: &mut StableHasher<W>) {
-        self.len().hash_stable(ctx, hasher);
-        for v in self {
-            v.hash_stable(ctx, hasher);
-        }
+        self.words().hash_stable(ctx, hasher);
     }
 }
 
-impl<I: ::indexed_vec::Idx, T, CTX> HashStable<CTX> for ::indexed_vec::IndexVec<I, T>
-    where T: HashStable<CTX>,
+impl_stable_hash_via_hash!(::std::path::Path);
+impl_stable_hash_via_hash!(::std::path::PathBuf);
+
+impl<K, V, R, HCX> HashStable<HCX> for ::std::collections::HashMap<K, V, R>
+    where K: ToStableHashKey<HCX> + Eq + Hash,
+          V: HashStable<HCX>,
+          R: BuildHasher,
 {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          ctx: &mut CTX,
+                                          hcx: &mut HCX,
                                           hasher: &mut StableHasher<W>) {
-        self.len().hash_stable(ctx, hasher);
-        for v in &self.raw {
-            v.hash_stable(ctx, hasher);
-        }
+        let mut entries: Vec<_> = self.iter()
+                                      .map(|(k, v)| (k.to_stable_hash_key(hcx), v))
+                                      .collect();
+        entries.sort_unstable_by(|&(ref sk1, _), &(ref sk2, _)| sk1.cmp(sk2));
+        entries.hash_stable(hcx, hasher);
     }
 }
 
+impl<K, R, HCX> HashStable<HCX> for ::std::collections::HashSet<K, R>
+    where K: ToStableHashKey<HCX> + Eq + Hash,
+          R: BuildHasher,
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut HCX,
+                                          hasher: &mut StableHasher<W>) {
+        let mut keys: Vec<_> = self.iter()
+                                   .map(|k| k.to_stable_hash_key(hcx))
+                                   .collect();
+        keys.sort_unstable();
+        keys.hash_stable(hcx, hasher);
+    }
+}
 
-impl<I: ::indexed_vec::Idx, CTX> HashStable<CTX> for ::indexed_set::IdxSetBuf<I>
+impl<K, V, HCX> HashStable<HCX> for ::std::collections::BTreeMap<K, V>
+    where K: ToStableHashKey<HCX>,
+          V: HashStable<HCX>,
 {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          ctx: &mut CTX,
+                                          hcx: &mut HCX,
                                           hasher: &mut StableHasher<W>) {
-        self.words().hash_stable(ctx, hasher);
+        let mut entries: Vec<_> = self.iter()
+                                      .map(|(k, v)| (k.to_stable_hash_key(hcx), v))
+                                      .collect();
+        entries.sort_unstable_by(|&(ref sk1, _), &(ref sk2, _)| sk1.cmp(sk2));
+        entries.hash_stable(hcx, hasher);
+    }
+}
+
+impl<K, HCX> HashStable<HCX> for ::std::collections::BTreeSet<K>
+    where K: ToStableHashKey<HCX>,
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut HCX,
+                                          hasher: &mut StableHasher<W>) {
+        let mut keys: Vec<_> = self.iter()
+                                   .map(|k| k.to_stable_hash_key(hcx))
+                                   .collect();
+        keys.sort_unstable();
+        keys.hash_stable(hcx, hasher);
     }
 }
diff --git a/src/librustc_incremental/calculate_svh/mod.rs b/src/librustc_incremental/calculate_svh/mod.rs
index 94400890c5641..d8e201d3acdcf 100644
--- a/src/librustc_incremental/calculate_svh/mod.rs
+++ b/src/librustc_incremental/calculate_svh/mod.rs
@@ -31,7 +31,7 @@ use std::cell::RefCell;
 use std::hash::Hash;
 use rustc::dep_graph::{DepNode, DepKind};
 use rustc::hir;
-use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
+use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex};
 use rustc::hir::map::DefPathHash;
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::ich::{Fingerprint, StableHashingContext};
@@ -96,7 +96,7 @@ struct ComputeItemHashesVisitor<'a, 'tcx: 'a> {
 
 impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> {
     fn compute_and_store_ich_for_item_like<T>(&mut self,
-                                              dep_node: DepNode,
+                                              def_index: DefIndex,
                                               hash_bodies: bool,
                                               item_like: T)
         where T: HashStable<StableHashingContext<'a, 'tcx, 'tcx>>
@@ -108,6 +108,8 @@ impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> {
             return
         }
 
+        let def_path_hash = self.hcx.tcx().hir.definitions().def_path_hash(def_index);
+
         let mut hasher = IchHasher::new();
         self.hcx.while_hashing_hir_bodies(hash_bodies, |hcx| {
             item_like.hash_stable(hcx, &mut hasher);
@@ -115,6 +117,11 @@ impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> {
 
         let bytes_hashed = hasher.bytes_hashed();
         let item_hash = hasher.finish();
+        let dep_node = if hash_bodies {
+            def_path_hash.to_dep_node(DepKind::HirBody)
+        } else {
+            def_path_hash.to_dep_node(DepKind::Hir)
+        };
         debug!("calculate_def_hash: dep_node={:?} hash={:?}", dep_node, item_hash);
         self.hashes.insert(dep_node, item_hash);
 
@@ -123,6 +130,14 @@ impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> {
             tcx.sess.perf_stats.incr_comp_bytes_hashed.get() +
             bytes_hashed;
         tcx.sess.perf_stats.incr_comp_bytes_hashed.set(bytes_hashed);
+
+        if hash_bodies {
+            let in_scope_traits_map = tcx.in_scope_traits_map(def_index);
+            let mut hasher = IchHasher::new();
+            in_scope_traits_map.hash_stable(&mut self.hcx, &mut hasher);
+            let dep_node = def_path_hash.to_dep_node(DepKind::InScopeTraits);
+            self.hashes.insert(dep_node, hasher.finish());
+        }
     }
 
     fn compute_crate_hash(&mut self) {
@@ -145,6 +160,7 @@ impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> {
                                 // This `match` determines what kinds of nodes
                                 // go into the SVH:
                                 match item_dep_node.kind {
+                                    DepKind::InScopeTraits |
                                     DepKind::Hir |
                                     DepKind::HirBody => {
                                         // We want to incoporate these into the
@@ -195,11 +211,10 @@ impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> {
             body_ids: _,
         } = *krate;
 
-        let def_path_hash = self.hcx.tcx().hir.definitions().def_path_hash(CRATE_DEF_INDEX);
-        self.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::Hir),
+        self.compute_and_store_ich_for_item_like(CRATE_DEF_INDEX,
                                                  false,
                                                  (module, (span, attrs)));
-        self.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::HirBody),
+        self.compute_and_store_ich_for_item_like(CRATE_DEF_INDEX,
                                                  true,
                                                  (module, (span, attrs)));
     }
@@ -251,34 +266,31 @@ impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> {
 
 impl<'a, 'tcx: 'a> ItemLikeVisitor<'tcx> for ComputeItemHashesVisitor<'a, 'tcx> {
     fn visit_item(&mut self, item: &'tcx hir::Item) {
-        let def_id = self.hcx.tcx().hir.local_def_id(item.id);
-        let def_path_hash = self.hcx.tcx().def_path_hash(def_id);
-        self.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::Hir),
+        let def_index = self.hcx.tcx().hir.local_def_id(item.id).index;
+        self.compute_and_store_ich_for_item_like(def_index,
                                                  false,
                                                  item);
-        self.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::HirBody),
+        self.compute_and_store_ich_for_item_like(def_index,
                                                  true,
                                                  item);
     }
 
     fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) {
-        let def_id = self.hcx.tcx().hir.local_def_id(item.id);
-        let def_path_hash = self.hcx.tcx().def_path_hash(def_id);
-        self.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::Hir),
+        let def_index = self.hcx.tcx().hir.local_def_id(item.id).index;
+        self.compute_and_store_ich_for_item_like(def_index,
                                                  false,
                                                  item);
-        self.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::HirBody),
+        self.compute_and_store_ich_for_item_like(def_index,
                                                  true,
                                                  item);
     }
 
     fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) {
-        let def_id = self.hcx.tcx().hir.local_def_id(item.id);
-        let def_path_hash = self.hcx.tcx().def_path_hash(def_id);
-        self.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::Hir),
+        let def_index = self.hcx.tcx().hir.local_def_id(item.id).index;
+        self.compute_and_store_ich_for_item_like(def_index,
                                                  false,
                                                  item);
-        self.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::HirBody),
+        self.compute_and_store_ich_for_item_like(def_index,
                                                  true,
                                                  item);
     }
@@ -301,12 +313,11 @@ pub fn compute_incremental_hashes_map<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
         krate.visit_all_item_likes(&mut visitor);
 
         for macro_def in krate.exported_macros.iter() {
-            let def_id = tcx.hir.local_def_id(macro_def.id);
-            let def_path_hash = tcx.def_path_hash(def_id);
-            visitor.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::Hir),
+            let def_index = tcx.hir.local_def_id(macro_def.id).index;
+            visitor.compute_and_store_ich_for_item_like(def_index,
                                                         false,
                                                         macro_def);
-            visitor.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::HirBody),
+            visitor.compute_and_store_ich_for_item_like(def_index,
                                                         true,
                                                         macro_def);
         }
diff --git a/src/librustc_incremental/persist/hash.rs b/src/librustc_incremental/persist/hash.rs
index 44d6788c77365..8355f31913938 100644
--- a/src/librustc_incremental/persist/hash.rs
+++ b/src/librustc_incremental/persist/hash.rs
@@ -49,6 +49,7 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> {
         match dep_node.kind {
             DepKind::Krate |
             DepKind::Hir |
+            DepKind::InScopeTraits |
             DepKind::HirBody =>
                 true,
             DepKind::MetaData => {
@@ -66,6 +67,7 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> {
             }
 
             // HIR nodes (which always come from our crate) are an input:
+            DepKind::InScopeTraits |
             DepKind::Hir |
             DepKind::HirBody => {
                 Some(self.incremental_hashes_map[dep_node])
diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs
index ba638289fdf03..9865ea8c2856a 100644
--- a/src/librustc_incremental/persist/load.rs
+++ b/src/librustc_incremental/persist/load.rs
@@ -104,6 +104,7 @@ fn does_still_exist(tcx: TyCtxt, dep_node: &DepNode) -> bool {
     match dep_node.kind {
         DepKind::Hir |
         DepKind::HirBody |
+        DepKind::InScopeTraits |
         DepKind::MetaData => {
             dep_node.extract_def_id(tcx).is_some()
         }
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index dc6c260ec7174..39bdf88925e44 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -301,7 +301,10 @@ impl<'a> CrateLoader<'a> {
             .decode(&cmeta)
             .filter(|lib| relevant_lib(self.sess, lib) &&
                           lib.kind == cstore::NativeLibraryKind::NativeUnknown)
-            .flat_map(|lib| lib.foreign_items.into_iter())
+            .flat_map(|lib| {
+                assert!(lib.foreign_items.iter().all(|def_id| def_id.krate == cnum));
+                lib.foreign_items.into_iter().map(|def_id| def_id.index)
+            })
             .collect();
 
         cmeta.dllimport_foreign_items = dllimports;
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index 3a116160bcab2..e4de27ee15e52 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -264,7 +264,7 @@ pub fn provide_local<'tcx>(providers: &mut Providers<'tcx>) {
             tcx.native_libraries(id.krate)
                 .iter()
                 .filter(|lib| native_libs::relevant_lib(&tcx.sess, lib))
-                .find(|l| l.foreign_items.contains(&id.index))
+                .find(|l| l.foreign_items.contains(&id))
                 .map(|l| l.kind)
         },
         native_libraries: |tcx, cnum| {
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 1c4f1c6348689..4696759817fcb 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -659,10 +659,11 @@ impl<'a, 'tcx> CrateMetadata {
     }
 
     /// Iterates over the language items in the given crate.
-    pub fn get_lang_items(&self) -> Vec<(DefIndex, usize)> {
+    pub fn get_lang_items(&self) -> Vec<(DefId, usize)> {
         self.root
             .lang_items
             .decode(self)
+            .map(|(def_index, index)| (self.local_def_id(def_index), index))
             .collect()
     }
 
diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs
index 669681d2aadde..cc332acb5b08e 100644
--- a/src/librustc_metadata/native_libs.rs
+++ b/src/librustc_metadata/native_libs.rs
@@ -96,7 +96,7 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for Collector<'a, 'tcx> {
                 list[0].meta_item().unwrap().clone()
             });
             let foreign_items = fm.items.iter()
-                .map(|it| self.tcx.hir.local_def_id(it.id).index)
+                .map(|it| self.tcx.hir.local_def_id(it.id))
                 .collect();
             let lib = NativeLibrary {
                 name: n,
diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs
index 6ed928ca09deb..dc18cdd8f0dd6 100644
--- a/src/librustc_mir/transform/erase_regions.rs
+++ b/src/librustc_mir/transform/erase_regions.rs
@@ -15,8 +15,7 @@
 //! "types-as-contracts"-validation, namely, AcquireValid, ReleaseValid, and EndRegion.
 
 use rustc::ty::subst::Substs;
-use rustc::ty::{self, Ty, TyCtxt, ClosureSubsts};
-use rustc::middle::const_val::ConstVal;
+use rustc::ty::{self, Ty, TyCtxt};
 use rustc::mir::*;
 use rustc::mir::visit::{MutVisitor, Lookup};
 use rustc::mir::transform::{MirPass, MirSource};
@@ -80,45 +79,6 @@ impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> {
         self.super_statement(block, statement, location);
         self.in_validation_statement = false;
     }
-
-    fn visit_const_val(&mut self,
-                       const_val: &mut ConstVal<'tcx>,
-                       _: Location) {
-        erase_const_val(self.tcx, const_val);
-        self.super_const_val(const_val);
-
-        fn erase_const_val<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                     const_val: &mut ConstVal<'tcx>) {
-            match *const_val {
-                ConstVal::Float(_)    |
-                ConstVal::Integral(_) |
-                ConstVal::Str(_)      |
-                ConstVal::ByteStr(_)  |
-                ConstVal::Bool(_)     |
-                ConstVal::Char(_)     |
-                ConstVal::Variant(_)  => {
-                    // nothing to do
-                }
-                ConstVal::Function(_, ref mut substs) => {
-                    *substs = tcx.erase_regions(&{*substs});
-                }
-                ConstVal::Struct(ref mut field_map) => {
-                    for (_, field_val) in field_map {
-                        erase_const_val(tcx, field_val);
-                    }
-                }
-                ConstVal::Tuple(ref mut fields) |
-                ConstVal::Array(ref mut fields) => {
-                    for field_val in fields {
-                        erase_const_val(tcx, field_val);
-                    }
-                }
-                ConstVal::Repeat(ref mut expr, _) => {
-                    erase_const_val(tcx, &mut **expr);
-                }
-            }
-        }
-    }
 }
 
 pub struct EraseRegions;
diff --git a/src/test/incremental/ich_method_call_trait_scope.rs b/src/test/incremental/ich_method_call_trait_scope.rs
index 0a36e3c693edb..7f4e2b0f17652 100644
--- a/src/test/incremental/ich_method_call_trait_scope.rs
+++ b/src/test/incremental/ich_method_call_trait_scope.rs
@@ -12,6 +12,7 @@
 // scope.
 
 // revisions: rpass1 rpass2
+// compile-flags: -Z query-dep-graph
 
 #![feature(rustc_attrs)]
 
@@ -47,13 +48,15 @@ mod mod3 {
     use Trait2;
 
     #[rustc_clean(label="Hir", cfg="rpass2")]
-    #[rustc_dirty(label="HirBody", cfg="rpass2")]
+    #[rustc_clean(label="HirBody", cfg="rpass2")]
+    #[rustc_dirty(label="TypeckTables", cfg="rpass2")]
     fn bar() {
         ().method();
     }
 
     #[rustc_clean(label="Hir", cfg="rpass2")]
     #[rustc_clean(label="HirBody", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
     fn baz() {
         22; // no method call, traits in scope don't matter
     }

From b9816c5fab6bfde01f83d83a0b53e78bb00d3900 Mon Sep 17 00:00:00 2001
From: Michael Woerister <michaelwoerister@posteo>
Date: Wed, 13 Sep 2017 14:59:10 +0200
Subject: [PATCH 16/24] incr.comp.: Already hash HIR bodies during metadata
 export so they don't have to be hashed in downstream crates.

---
 src/librustc/ich/hcx.rs              | 34 +++++++++++++++++++
 src/librustc/ich/impls_cstore.rs     | 28 ++++++++++++++++
 src/librustc/ich/impls_hir.rs        | 50 ++++++++++------------------
 src/librustc/middle/cstore.rs        | 22 ++++++++++++
 src/librustc/ty/maps.rs              | 11 +++---
 src/librustc_const_eval/eval.rs      |  5 ++-
 src/librustc_const_eval/pattern.rs   |  2 +-
 src/librustc_metadata/astencode.rs   | 25 ++++++++++++--
 src/librustc_metadata/cstore_impl.rs |  2 +-
 src/librustc_metadata/decoder.rs     | 35 ++++++++++++++-----
 src/librustdoc/clean/inline.rs       |  4 +--
 11 files changed, 163 insertions(+), 55 deletions(-)

diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs
index daf1ff8ad2b95..bd3a35836762b 100644
--- a/src/librustc/ich/hcx.rs
+++ b/src/librustc/ich/hcx.rs
@@ -202,6 +202,40 @@ impl<'a, 'gcx, 'lcx> StableHashingContextProvider for ty::TyCtxt<'a, 'gcx, 'lcx>
     }
 }
 
+impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::HirId {
+    #[inline]
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        match hcx.node_id_hashing_mode {
+            NodeIdHashingMode::Ignore => {
+                // Don't do anything.
+            }
+            NodeIdHashingMode::HashDefPath => {
+                let hir::HirId {
+                    owner,
+                    local_id,
+                } = *self;
+
+                hcx.tcx.hir.definitions().def_path_hash(owner).hash_stable(hcx, hasher);
+                local_id.hash_stable(hcx, hasher);
+            }
+        }
+    }
+}
+
+impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>> for hir::HirId {
+    type KeyType = (DefPathHash, hir::ItemLocalId);
+
+    #[inline]
+    fn to_stable_hash_key(&self,
+                          hcx: &StableHashingContext<'a, 'gcx, 'tcx>)
+                          -> (DefPathHash, hir::ItemLocalId) {
+        let def_path_hash = hcx.tcx().hir.definitions().def_path_hash(self.owner);
+        (def_path_hash, self.local_id)
+    }
+}
+
 impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ast::NodeId {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
diff --git a/src/librustc/ich/impls_cstore.rs b/src/librustc/ich/impls_cstore.rs
index 057a83ebbe352..18a02ff5c5882 100644
--- a/src/librustc/ich/impls_cstore.rs
+++ b/src/librustc/ich/impls_cstore.rs
@@ -11,6 +11,8 @@
 //! This module contains `HashStable` implementations for various data types
 //! from rustc::middle::cstore in no particular order.
 
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
+
 use middle;
 
 impl_stable_hash_for!(enum middle::cstore::DepKind {
@@ -51,3 +53,29 @@ impl_stable_hash_for!(struct middle::cstore::CrateSource {
     rlib,
     rmeta
 });
+
+impl<HCX> HashStable<HCX> for middle::cstore::ExternBodyNestedBodies {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut HCX,
+                                          hasher: &mut StableHasher<W>) {
+        let middle::cstore::ExternBodyNestedBodies {
+            nested_bodies: _,
+            fingerprint,
+        } = *self;
+
+        fingerprint.hash_stable(hcx, hasher);
+    }
+}
+
+impl<'a, HCX> HashStable<HCX> for middle::cstore::ExternConstBody<'a> {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut HCX,
+                                          hasher: &mut StableHasher<W>) {
+        let middle::cstore::ExternConstBody {
+            body: _,
+            fingerprint,
+        } = *self;
+
+        fingerprint.hash_stable(hcx, hasher);
+    }
+}
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index 9da147472ce4e..3c89e10a0d2d9 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -38,33 +38,6 @@ impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>> for D
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::HirId {
-    #[inline]
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
-                                          hasher: &mut StableHasher<W>) {
-        let hir::HirId {
-            owner,
-            local_id,
-        } = *self;
-
-        hcx.tcx().hir.definitions().def_path_hash(owner).hash_stable(hcx, hasher);
-        local_id.hash_stable(hcx, hasher);
-    }
-}
-
-impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>> for hir::HirId {
-    type KeyType = (DefPathHash, hir::ItemLocalId);
-
-    #[inline]
-    fn to_stable_hash_key(&self,
-                          hcx: &StableHashingContext<'a, 'gcx, 'tcx>)
-                          -> (DefPathHash, hir::ItemLocalId) {
-        let def_path_hash = hcx.tcx().hir.definitions().def_path_hash(self.owner);
-        (def_path_hash, self.local_id)
-    }
-}
-
 impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for CrateNum {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
@@ -415,6 +388,7 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::P
             ref span
         } = *self;
 
+
         node.hash_stable(hcx, hasher);
         span.hash_stable(hcx, hasher);
     }
@@ -1003,11 +977,23 @@ impl_stable_hash_for!(struct hir::Arg {
     hir_id
 });
 
-impl_stable_hash_for!(struct hir::Body {
-    arguments,
-    value,
-    is_generator
-});
+impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::Body {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        let hir::Body {
+            ref arguments,
+            ref value,
+            is_generator,
+        } = *self;
+
+        hcx.with_node_id_hashing_mode(NodeIdHashingMode::Ignore, |hcx| {
+            arguments.hash_stable(hcx, hasher);
+            value.hash_stable(hcx, hasher);
+            is_generator.hash_stable(hcx, hasher);
+        });
+    }
+}
 
 impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::BodyId {
     fn hash_stable<W: StableHasherResult>(&self,
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index 7c60c6d6430e1..de647913f0f3b 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -22,6 +22,7 @@
 //! are *mostly* used as a part of that interface, but these should
 //! probably get a better home if someone can find one.
 
+use hir;
 use hir::def;
 use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
 use hir::map as hir_map;
@@ -34,6 +35,7 @@ use session::search_paths::PathKind;
 use util::nodemap::NodeSet;
 
 use std::any::Any;
+use std::collections::BTreeMap;
 use std::path::{Path, PathBuf};
 use std::rc::Rc;
 use owning_ref::ErasedBoxRef;
@@ -218,6 +220,26 @@ pub trait MetadataLoader {
                           -> Result<ErasedBoxRef<[u8]>, String>;
 }
 
+#[derive(Clone)]
+pub struct ExternConstBody<'tcx> {
+    pub body: &'tcx hir::Body,
+
+    // It would require a lot of infrastructure to enable stable-hashing Bodies
+    // from other crates, so we hash on export and just store the fingerprint
+    // with them.
+    pub fingerprint: ich::Fingerprint,
+}
+
+#[derive(Clone)]
+pub struct ExternBodyNestedBodies {
+    pub nested_bodies: Rc<BTreeMap<hir::BodyId, hir::Body>>,
+
+    // It would require a lot of infrastructure to enable stable-hashing Bodies
+    // from other crates, so we hash on export and just store the fingerprint
+    // with them.
+    pub fingerprint: ich::Fingerprint,
+}
+
 /// A store of Rust crates, through with their metadata
 /// can be accessed.
 ///
diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs
index fc803d1c849b5..5207aaa0c5b2f 100644
--- a/src/librustc/ty/maps.rs
+++ b/src/librustc/ty/maps.rs
@@ -16,8 +16,9 @@ use hir::{self, TraitCandidate, ItemLocalId};
 use hir::svh::Svh;
 use lint;
 use middle::const_val;
-use middle::cstore::{ExternCrate, LinkagePreference, NativeLibrary};
-use middle::cstore::{NativeLibraryKind, DepKind, CrateSource};
+use middle::cstore::{ExternCrate, LinkagePreference, NativeLibrary,
+                     ExternBodyNestedBodies};
+use middle::cstore::{NativeLibraryKind, DepKind, CrateSource, ExternConstBody};
 use middle::privacy::AccessLevels;
 use middle::reachable::ReachableSet;
 use middle::region;
@@ -50,7 +51,6 @@ use std::fmt::Debug;
 use std::hash::Hash;
 use std::marker::PhantomData;
 use std::mem;
-use std::collections::BTreeMap;
 use std::ops::Deref;
 use std::rc::Rc;
 use std::sync::Arc;
@@ -1321,8 +1321,7 @@ define_maps! { <'tcx>
     [] fn impl_parent: ImplParent(DefId) -> Option<DefId>,
     [] fn trait_of_item: TraitOfItem(DefId) -> Option<DefId>,
     [] fn is_exported_symbol: IsExportedSymbol(DefId) -> bool,
-    [] fn item_body_nested_bodies: ItemBodyNestedBodies(DefId)
-        -> Rc<BTreeMap<hir::BodyId, hir::Body>>,
+    [] fn item_body_nested_bodies: ItemBodyNestedBodies(DefId) -> ExternBodyNestedBodies,
     [] fn const_is_rvalue_promotable_to_static: ConstIsRvaluePromotableToStatic(DefId) -> bool,
     [] fn is_mir_available: IsMirAvailable(DefId) -> bool,
 
@@ -1402,7 +1401,7 @@ define_maps! { <'tcx>
     [] fn get_lang_items: get_lang_items_node(CrateNum) -> Rc<LanguageItems>,
     [] fn defined_lang_items: DefinedLangItems(CrateNum) -> Rc<Vec<(DefId, usize)>>,
     [] fn missing_lang_items: MissingLangItems(CrateNum) -> Rc<Vec<LangItem>>,
-    [] fn extern_const_body: ExternConstBody(DefId) -> &'tcx hir::Body,
+    [] fn extern_const_body: ExternConstBody(DefId) -> ExternConstBody<'tcx>,
     [] fn visible_parent_map: visible_parent_map_node(CrateNum)
         -> Rc<DefIdMap<DefId>>,
     [] fn missing_extern_crate_item: MissingExternCrateItem(CrateNum) -> bool,
diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs
index 61eb5dfd18b9c..7520c6ac652ba 100644
--- a/src/librustc_const_eval/eval.rs
+++ b/src/librustc_const_eval/eval.rs
@@ -34,7 +34,6 @@ use syntax_pos::Span;
 use std::cmp::Ordering;
 
 use rustc_const_math::*;
-
 macro_rules! signal {
     ($e:expr, $exn:expr) => {
         return Err(ConstEvalErr { span: $e.span, kind: $exn })
@@ -366,7 +365,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
             }
           } else {
             if tcx.is_const_fn(def_id) {
-                tcx.extern_const_body(def_id)
+                tcx.extern_const_body(def_id).body
             } else {
                 signal!(e, TypeckError)
             }
@@ -790,7 +789,7 @@ fn const_eval<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         tcx.mir_const_qualif(def_id);
         tcx.hir.body(tcx.hir.body_owned_by(id))
     } else {
-        tcx.extern_const_body(def_id)
+        tcx.extern_const_body(def_id).body
     };
     ConstContext::new(tcx, key.param_env.and(substs), tables).eval(&body.value)
 }
diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs
index a87fa0c2746a3..7586ad5a75f81 100644
--- a/src/librustc_const_eval/pattern.rs
+++ b/src/librustc_const_eval/pattern.rs
@@ -607,7 +607,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
                         let body = if let Some(id) = self.tcx.hir.as_local_node_id(def_id) {
                             self.tcx.hir.body(self.tcx.hir.body_owned_by(id))
                         } else {
-                            self.tcx.extern_const_body(def_id)
+                            self.tcx.extern_const_body(def_id).body
                         };
                         let pat = self.lower_const_expr(&body.value, pat_id, span);
                         self.tables = old_tables;
diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs
index ade2612855e02..3bc281e5486a8 100644
--- a/src/librustc_metadata/astencode.rs
+++ b/src/librustc_metadata/astencode.rs
@@ -16,26 +16,46 @@ use schema::*;
 use rustc::hir;
 use rustc::ty::{self, TyCtxt};
 
+use rustc::ich::{StableHashingContext, Fingerprint};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct Ast<'tcx> {
     pub body: Lazy<hir::Body>,
     pub tables: Lazy<ty::TypeckTables<'tcx>>,
     pub nested_bodies: LazySeq<hir::Body>,
     pub rvalue_promotable_to_static: bool,
+    pub stable_bodies_hash: Fingerprint,
 }
 
 impl_stable_hash_for!(struct Ast<'tcx> {
     body,
     tables,
     nested_bodies,
-    rvalue_promotable_to_static
+    rvalue_promotable_to_static,
+    stable_bodies_hash
 });
 
 impl<'a, 'b, 'tcx> IsolatedEncoder<'a, 'b, 'tcx> {
     pub fn encode_body(&mut self, body_id: hir::BodyId) -> Lazy<Ast<'tcx>> {
         let body = self.tcx.hir.body(body_id);
-        let lazy_body = self.lazy(body);
 
+        // In order to avoid having to hash hir::Bodies from extern crates, we
+        // hash them here, during export, and store the hash with metadata.
+        let stable_bodies_hash = {
+            let mut hcx = StableHashingContext::new(self.tcx);
+            let mut hasher = StableHasher::new();
+
+            hcx.while_hashing_hir_bodies(true, |hcx| {
+                hcx.while_hashing_spans(false, |hcx| {
+                    body.hash_stable(hcx, &mut hasher);
+                });
+            });
+
+            hasher.finish()
+        };
+
+        let lazy_body = self.lazy(body);
         let tables = self.tcx.body_tables(body_id);
         let lazy_tables = self.lazy(tables);
 
@@ -54,6 +74,7 @@ impl<'a, 'b, 'tcx> IsolatedEncoder<'a, 'b, 'tcx> {
             tables: lazy_tables,
             nested_bodies: lazy_nested_bodies,
             rvalue_promotable_to_static,
+            stable_bodies_hash,
         })
     }
 }
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index e4de27ee15e52..78c44c7e45cdf 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -159,7 +159,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
     is_exported_symbol => {
         cdata.exported_symbols.contains(&def_id.index)
     }
-    item_body_nested_bodies => { Rc::new(cdata.item_body_nested_bodies(def_id.index)) }
+    item_body_nested_bodies => { cdata.item_body_nested_bodies(def_id.index) }
     const_is_rvalue_promotable_to_static => {
         cdata.const_is_rvalue_promotable_to_static(def_id.index)
     }
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 4696759817fcb..65cf15e5a0ec7 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -17,9 +17,11 @@ use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash};
 use rustc::hir;
 
 use rustc::middle::const_val::ByteArray;
-use rustc::middle::cstore::LinkagePreference;
+use rustc::middle::cstore::{LinkagePreference, ExternConstBody,
+                            ExternBodyNestedBodies};
 use rustc::hir::def::{self, Def, CtorKind};
 use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc::ich::Fingerprint;
 use rustc::middle::lang_items;
 use rustc::session::Session;
 use rustc::ty::{self, Ty, TyCtxt};
@@ -775,12 +777,16 @@ impl<'a, 'tcx> CrateMetadata {
     pub fn extern_const_body(&self,
                              tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              id: DefIndex)
-                             -> &'tcx hir::Body {
+                             -> ExternConstBody<'tcx> {
         assert!(!self.is_proc_macro(id));
         let ast = self.entry(id).ast.unwrap();
         let def_id = self.local_def_id(id);
-        let body = ast.decode((self, tcx)).body.decode((self, tcx));
-        tcx.hir.intern_inlined_body(def_id, body)
+        let ast = ast.decode((self, tcx));
+        let body = ast.body.decode((self, tcx));
+        ExternConstBody {
+            body: tcx.hir.intern_inlined_body(def_id, body),
+            fingerprint: ast.stable_bodies_hash,
+        }
     }
 
     pub fn item_body_tables(&self,
@@ -791,10 +797,23 @@ impl<'a, 'tcx> CrateMetadata {
         tcx.alloc_tables(ast.tables.decode((self, tcx)))
     }
 
-    pub fn item_body_nested_bodies(&self, id: DefIndex) -> BTreeMap<hir::BodyId, hir::Body> {
-        self.entry(id).ast.into_iter().flat_map(|ast| {
-            ast.decode(self).nested_bodies.decode(self).map(|body| (body.id(), body))
-        }).collect()
+    pub fn item_body_nested_bodies(&self, id: DefIndex) -> ExternBodyNestedBodies {
+        if let Some(ref ast) = self.entry(id).ast {
+            let ast = ast.decode(self);
+            let nested_bodies: BTreeMap<_, _> = ast.nested_bodies
+                                                   .decode(self)
+                                                   .map(|body| (body.id(), body))
+                                                   .collect();
+            ExternBodyNestedBodies {
+                nested_bodies: Rc::new(nested_bodies),
+                fingerprint: ast.stable_bodies_hash,
+            }
+        } else {
+            ExternBodyNestedBodies {
+                nested_bodies: Rc::new(BTreeMap::new()),
+                fingerprint: Fingerprint::zero(),
+            }
+        }
     }
 
     pub fn const_is_rvalue_promotable_to_static(&self, id: DefIndex) -> bool {
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 7f5d11ba5de28..3a4dcc3217388 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -474,9 +474,9 @@ impl hir::print::PpAnn for InlinedConst {
 }
 
 pub fn print_inlined_const(cx: &DocContext, did: DefId) -> String {
-    let body = cx.tcx.extern_const_body(did);
+    let body = cx.tcx.extern_const_body(did).body;
     let inlined = InlinedConst {
-        nested_bodies: cx.tcx.item_body_nested_bodies(did)
+        nested_bodies: cx.tcx.item_body_nested_bodies(did).nested_bodies
     };
     hir::print::to_string(&inlined, |s| s.print_expr(&body.value))
 }

From 67c84e05e72931587e5f81a297dee95bc149bcd8 Mon Sep 17 00:00:00 2001
From: Michael Woerister <michaelwoerister@posteo>
Date: Wed, 13 Sep 2017 18:20:27 +0200
Subject: [PATCH 17/24] incr.comp.: Use StableHash impls instead of functions
 for hashing most maps.

---
 src/librustc/ich/hcx.rs                       | 108 +-----------------
 src/librustc/ich/impls_ty.rs                  |  83 +++++---------
 src/librustc/ich/mod.rs                       |   4 +-
 src/librustc/lint/levels.rs                   |  31 ++---
 src/librustc/middle/region.rs                 |  25 ++--
 .../traits/specialize/specialization_graph.rs |  21 +---
 src/librustc/ty/context.rs                    |  43 ++++---
 src/librustc_data_structures/stable_hasher.rs |  50 ++++++--
 8 files changed, 118 insertions(+), 247 deletions(-)

diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs
index bd3a35836762b..0932c5ce8fb80 100644
--- a/src/librustc/ich/hcx.rs
+++ b/src/librustc/ich/hcx.rs
@@ -14,11 +14,10 @@ use hir::map::DefPathHash;
 use ich::{self, CachingCodemapView};
 use session::config::DebugInfoLevel::NoDebugInfo;
 use ty::{self, TyCtxt, fast_reject};
-use util::nodemap::{NodeMap, NodeSet, ItemLocalMap};
 
 use std::cmp::Ord;
 use std::hash as std_hash;
-use std::collections::{HashMap, HashSet, BTreeMap};
+use std::collections::HashMap;
 
 use syntax::ast;
 use syntax::attr;
@@ -337,111 +336,6 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for Span {
     }
 }
 
-pub fn hash_stable_hashmap<'a, 'gcx, 'tcx, K, V, R, SK, F, W>(
-    hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
-    hasher: &mut StableHasher<W>,
-    map: &HashMap<K, V, R>,
-    extract_stable_key: F)
-    where K: Eq + std_hash::Hash,
-          V: HashStable<StableHashingContext<'a, 'gcx, 'tcx>>,
-          R: std_hash::BuildHasher,
-          SK: HashStable<StableHashingContext<'a, 'gcx, 'tcx>> + Ord + Clone,
-          F: Fn(&mut StableHashingContext<'a, 'gcx, 'tcx>, &K) -> SK,
-          W: StableHasherResult,
-{
-    let mut keys: Vec<_> = map.keys()
-                              .map(|k| (extract_stable_key(hcx, k), k))
-                              .collect();
-    keys.sort_unstable_by(|&(ref sk1, _), &(ref sk2, _)| sk1.cmp(sk2));
-    keys.len().hash_stable(hcx, hasher);
-    for (stable_key, key) in keys {
-        stable_key.hash_stable(hcx, hasher);
-        map[key].hash_stable(hcx, hasher);
-    }
-}
-
-pub fn hash_stable_hashset<'a, 'tcx, 'gcx, K, R, SK, F, W>(
-    hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
-    hasher: &mut StableHasher<W>,
-    set: &HashSet<K, R>,
-    extract_stable_key: F)
-    where K: Eq + std_hash::Hash,
-          R: std_hash::BuildHasher,
-          SK: HashStable<StableHashingContext<'a, 'gcx, 'tcx>> + Ord + Clone,
-          F: Fn(&mut StableHashingContext<'a, 'gcx, 'tcx>, &K) -> SK,
-          W: StableHasherResult,
-{
-    let mut keys: Vec<_> = set.iter()
-                              .map(|k| extract_stable_key(hcx, k))
-                              .collect();
-    keys.sort_unstable();
-    keys.hash_stable(hcx, hasher);
-}
-
-pub fn hash_stable_nodemap<'a, 'tcx, 'gcx, V, W>(
-    hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
-    hasher: &mut StableHasher<W>,
-    map: &NodeMap<V>)
-    where V: HashStable<StableHashingContext<'a, 'gcx, 'tcx>>,
-          W: StableHasherResult,
-{
-    let definitions = hcx.tcx.hir.definitions();
-    hash_stable_hashmap(hcx, hasher, map, |_, node_id| {
-        let hir_id = definitions.node_to_hir_id(*node_id);
-        let owner_def_path_hash = definitions.def_path_hash(hir_id.owner);
-        (owner_def_path_hash, hir_id.local_id)
-    });
-}
-
-pub fn hash_stable_nodeset<'a, 'tcx, 'gcx, W>(
-    hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
-    hasher: &mut StableHasher<W>,
-    map: &NodeSet)
-    where W: StableHasherResult,
-{
-    let definitions = hcx.tcx.hir.definitions();
-    hash_stable_hashset(hcx, hasher, map, |_, node_id| {
-        let hir_id = definitions.node_to_hir_id(*node_id);
-        let owner_def_path_hash = definitions.def_path_hash(hir_id.owner);
-        (owner_def_path_hash, hir_id.local_id)
-    });
-}
-
-pub fn hash_stable_itemlocalmap<'a, 'tcx, 'gcx, V, W>(
-    hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
-    hasher: &mut StableHasher<W>,
-    map: &ItemLocalMap<V>)
-    where V: HashStable<StableHashingContext<'a, 'gcx, 'tcx>>,
-          W: StableHasherResult,
-{
-    hash_stable_hashmap(hcx, hasher, map, |_, local_id| {
-        *local_id
-    });
-}
-
-
-pub fn hash_stable_btreemap<'a, 'tcx, 'gcx, K, V, SK, F, W>(
-    hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
-    hasher: &mut StableHasher<W>,
-    map: &BTreeMap<K, V>,
-    extract_stable_key: F)
-    where K: Eq + Ord,
-          V: HashStable<StableHashingContext<'a, 'gcx, 'tcx>>,
-          SK: HashStable<StableHashingContext<'a, 'gcx, 'tcx>> + Ord + Clone,
-          F: Fn(&mut StableHashingContext<'a, 'gcx, 'tcx>, &K) -> SK,
-          W: StableHasherResult,
-{
-    let mut keys: Vec<_> = map.keys()
-                              .map(|k| (extract_stable_key(hcx, k), k))
-                              .collect();
-    keys.sort_unstable_by(|&(ref sk1, _), &(ref sk2, _)| sk1.cmp(sk2));
-    keys.len().hash_stable(hcx, hasher);
-    for (stable_key, key) in keys {
-        stable_key.hash_stable(hcx, hasher);
-        map[key].hash_stable(hcx, hasher);
-    }
-}
-
 pub fn hash_stable_trait_impls<'a, 'tcx, 'gcx, W, R>(
     hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
     hasher: &mut StableHasher<W>,
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index 53a071fe48030..371a9c966440a 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -11,9 +11,9 @@
 //! This module contains `HashStable` implementations for various data types
 //! from rustc::ty in no particular order.
 
-use ich::{self, StableHashingContext, NodeIdHashingMode};
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
-                                           StableHasherResult};
+use ich::{StableHashingContext, NodeIdHashingMode};
+use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey,
+                                           StableHasher, StableHasherResult};
 use std::hash as std_hash;
 use std::mem;
 use middle::region;
@@ -124,9 +124,10 @@ for ty::adjustment::Adjust<'gcx> {
 
 impl_stable_hash_for!(struct ty::adjustment::Adjustment<'tcx> { kind, target });
 impl_stable_hash_for!(struct ty::adjustment::OverloadedDeref<'tcx> { region, mutbl });
-impl_stable_hash_for!(struct ty::UpvarId { var_id, closure_expr_id });
 impl_stable_hash_for!(struct ty::UpvarBorrow<'tcx> { kind, region });
 
+impl_stable_hash_for!(struct ty::UpvarId { var_id, closure_expr_id });
+
 impl_stable_hash_for!(enum ty::BorrowKind {
     ImmBorrow,
     UniqueImmBorrow,
@@ -513,28 +514,20 @@ impl_stable_hash_for!(enum ty::cast::CastKind {
     FnPtrAddrCast
 });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
-for region::Scope
-{
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
-                                          hasher: &mut StableHasher<W>) {
-        mem::discriminant(self).hash_stable(hcx, hasher);
-        hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
-            match *self {
-                region::Scope::Node(node_id) |
-                region::Scope::Destruction(node_id) => {
-                    node_id.hash_stable(hcx, hasher);
-                }
-                region::Scope::CallSite(body_id) |
-                region::Scope::Arguments(body_id) => {
-                    body_id.hash_stable(hcx, hasher);
-                }
-                region::Scope::Remainder(block_remainder) => {
-                    block_remainder.hash_stable(hcx, hasher);
-                }
-            }
-        })
+impl_stable_hash_for!(enum ::middle::region::Scope {
+    Node(local_id),
+    Destruction(local_id),
+    CallSite(local_id),
+    Arguments(local_id),
+    Remainder(block_remainder)
+});
+
+impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>> for region::Scope {
+    type KeyType = region::Scope;
+
+    #[inline]
+    fn to_stable_hash_key(&self, _: &StableHashingContext<'a, 'gcx, 'tcx>) -> region::Scope {
+        *self
     }
 }
 
@@ -770,10 +763,7 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ty::Cr
         } = *self;
 
         dependencies.hash_stable(hcx, hasher);
-
-        ich::hash_stable_hashmap(hcx, hasher, variances, |hcx, def_id| {
-            hcx.def_path_hash(*def_id)
-        });
+        variances.hash_stable(hcx, hasher);
     }
 }
 
@@ -836,25 +826,14 @@ for ::middle::privacy::AccessLevels {
                 ref map
             } = *self;
 
-            ich::hash_stable_nodemap(hcx, hasher, map);
+            map.hash_stable(hcx, hasher);
         });
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
-for ty::CrateInherentImpls {
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
-                                          hasher: &mut StableHasher<W>) {
-        let ty::CrateInherentImpls {
-            ref inherent_impls,
-        } = *self;
-
-        ich::hash_stable_hashmap(hcx, hasher, inherent_impls, |hcx, def_id| {
-            hcx.def_path_hash(*def_id)
-        });
-    }
-}
+impl_stable_hash_for!(struct ty::CrateInherentImpls {
+    inherent_impls
+});
 
 impl_stable_hash_for!(enum ::session::CompileIncomplete {
     Stopped,
@@ -863,14 +842,6 @@ impl_stable_hash_for!(enum ::session::CompileIncomplete {
 
 impl_stable_hash_for!(struct ::util::common::ErrorReported {});
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
-for ::middle::reachable::ReachableSet {
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
-                                          hasher: &mut StableHasher<W>) {
-        let ::middle::reachable::ReachableSet(ref reachable_set) = *self;
-
-        ich::hash_stable_nodeset(hcx, hasher, reachable_set);
-    }
-}
-
+impl_stable_hash_for!(tuple_struct ::middle::reachable::ReachableSet {
+    reachable_set
+});
diff --git a/src/librustc/ich/mod.rs b/src/librustc/ich/mod.rs
index 5558534b71d2e..cd0749a686511 100644
--- a/src/librustc/ich/mod.rs
+++ b/src/librustc/ich/mod.rs
@@ -12,9 +12,7 @@
 
 pub use self::fingerprint::Fingerprint;
 pub use self::caching_codemap_view::CachingCodemapView;
-pub use self::hcx::{StableHashingContext, NodeIdHashingMode, hash_stable_hashmap,
-                    hash_stable_hashset, hash_stable_nodemap, hash_stable_nodeset,
-                    hash_stable_btreemap, hash_stable_itemlocalmap,
+pub use self::hcx::{StableHashingContext, NodeIdHashingMode,
                     hash_stable_trait_impls};
 mod fingerprint;
 mod caching_codemap_view;
diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs
index e953afd799dbf..eb2b136e417d3 100644
--- a/src/librustc/lint/levels.rs
+++ b/src/librustc/lint/levels.rs
@@ -12,12 +12,12 @@ use std::cmp;
 
 use errors::DiagnosticBuilder;
 use hir::HirId;
-use ich::{self, StableHashingContext};
+use ich::StableHashingContext;
 use lint::builtin;
 use lint::context::CheckLintNameResult;
 use lint::{self, Lint, LintId, Level, LintSource};
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
-                                           StableHasherResult};
+use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey,
+                                           StableHasher, StableHasherResult};
 use session::Session;
 use syntax::ast;
 use syntax::attr;
@@ -396,10 +396,7 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for LintLe
             ref id_to_set,
         } = *self;
 
-        let definitions = hcx.tcx().hir.definitions();
-        ich::hash_stable_hashmap(hcx, hasher, id_to_set, |_, hir_id| {
-            (definitions.def_path_hash(hir_id.owner), hir_id.local_id)
-        });
+        id_to_set.hash_stable(hcx, hasher);
 
         let LintLevelSets {
             ref list,
@@ -418,14 +415,10 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for LintLe
 
                 match *lint_set {
                     LintSet::CommandLine { ref specs } => {
-                        ich::hash_stable_hashmap(hcx, hasher, specs, |_, lint_id| {
-                            lint_id.lint_name_raw()
-                        });
+                        specs.hash_stable(hcx, hasher);
                     }
                     LintSet::Node { ref specs, parent } => {
-                        ich::hash_stable_hashmap(hcx, hasher, specs, |_, lint_id| {
-                            lint_id.lint_name_raw()
-                        });
+                        specs.hash_stable(hcx, hasher);
                         parent.hash_stable(hcx, hasher);
                     }
                 }
@@ -434,12 +427,20 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for LintLe
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for LintId {
+impl<HCX> HashStable<HCX> for LintId {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut HCX,
                                           hasher: &mut StableHasher<W>) {
         self.lint_name_raw().hash_stable(hcx, hasher);
     }
 }
 
+impl<HCX> ToStableHashKey<HCX> for LintId {
+    type KeyType = &'static str;
+
+    #[inline]
+    fn to_stable_hash_key(&self, _: &HCX) -> &'static str {
+        self.lint_name_raw()
+    }
+}
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index 562536ced3ce9..5c6feddb1fdf2 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -14,7 +14,7 @@
 //! Most of the documentation on regions can be found in
 //! `middle/infer/region_inference/README.md`
 
-use ich::{self, StableHashingContext, NodeIdHashingMode};
+use ich::{StableHashingContext, NodeIdHashingMode};
 use util::nodemap::{FxHashMap, FxHashSet};
 use ty;
 
@@ -1259,22 +1259,11 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ScopeT
             root_parent.hash_stable(hcx, hasher);
         });
 
-        ich::hash_stable_hashmap(hcx, hasher, parent_map, |hcx, scope| {
-            let mut hasher = StableHasher::new();
-            scope.hash_stable(hcx, &mut hasher);
-            let stable: u64 = hasher.finish();
-            stable
-        });
-
-        ich::hash_stable_itemlocalmap(hcx, hasher, var_map);
-        ich::hash_stable_itemlocalmap(hcx, hasher, destruction_scopes);
-        ich::hash_stable_itemlocalmap(hcx, hasher, rvalue_scopes);
-        ich::hash_stable_itemlocalmap(hcx, hasher, closure_tree);
-        ich::hash_stable_hashmap(hcx, hasher, yield_in_scope, |hcx, scope| {
-            let mut hasher = StableHasher::new();
-            scope.hash_stable(hcx, &mut hasher);
-            let stable: u64 = hasher.finish();
-            stable
-        });
+        parent_map.hash_stable(hcx, hasher);
+        var_map.hash_stable(hcx, hasher);
+        destruction_scopes.hash_stable(hcx, hasher);
+        rvalue_scopes.hash_stable(hcx, hasher);
+        closure_tree.hash_stable(hcx, hasher);
+        yield_in_scope.hash_stable(hcx, hasher);
     }
 }
diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs
index ecaf14659ae6b..6895e0e8a3456 100644
--- a/src/librustc/traits/specialize/specialization_graph.rs
+++ b/src/librustc/traits/specialize/specialization_graph.rs
@@ -382,20 +382,7 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for Childr
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for Graph {
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
-                                          hasher: &mut StableHasher<W>) {
-        let Graph {
-            ref parent,
-            ref children,
-        } = *self;
-
-        ich::hash_stable_hashmap(hcx, hasher, parent, |hcx, def_id| {
-            hcx.def_path_hash(*def_id)
-        });
-        ich::hash_stable_hashmap(hcx, hasher, children, |hcx, def_id| {
-            hcx.def_path_hash(*def_id)
-        });
-    }
-}
+impl_stable_hash_for!(struct self::Graph {
+    parent,
+    children
+});
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 7edc55e8a9fe4..0ea466a1bbcc3 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -21,7 +21,7 @@ use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
 use hir::map as hir_map;
 use hir::map::DefPathHash;
 use lint::{self, Lint};
-use ich::{self, StableHashingContext, NodeIdHashingMode};
+use ich::{StableHashingContext, NodeIdHashingMode};
 use middle::const_val::ConstVal;
 use middle::cstore::{CrateStore, LinkMeta, EncodedMetadataHashes};
 use middle::cstore::EncodedMetadata;
@@ -49,8 +49,8 @@ use ty::BindingMode;
 use util::nodemap::{NodeMap, NodeSet, DefIdSet, ItemLocalMap};
 use util::nodemap::{FxHashMap, FxHashSet};
 use rustc_data_structures::accumulate_vec::AccumulateVec;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
-                                           StableHasherResult};
+use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap,
+                                           StableHasher, StableHasherResult};
 
 use arena::{TypedArena, DroplessArena};
 use rustc_const_math::{ConstInt, ConstUsize};
@@ -714,12 +714,12 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for Typeck
         } = *self;
 
         hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
-            ich::hash_stable_itemlocalmap(hcx, hasher, type_dependent_defs);
-            ich::hash_stable_itemlocalmap(hcx, hasher, node_types);
-            ich::hash_stable_itemlocalmap(hcx, hasher, node_substs);
-            ich::hash_stable_itemlocalmap(hcx, hasher, adjustments);
-            ich::hash_stable_itemlocalmap(hcx, hasher, pat_binding_modes);
-            ich::hash_stable_hashmap(hcx, hasher, upvar_capture_map, |hcx, up_var_id| {
+            type_dependent_defs.hash_stable(hcx, hasher);
+            node_types.hash_stable(hcx, hasher);
+            node_substs.hash_stable(hcx, hasher);
+            adjustments.hash_stable(hcx, hasher);
+            pat_binding_modes.hash_stable(hcx, hasher);
+            hash_stable_hashmap(hcx, hasher, upvar_capture_map, |up_var_id, hcx| {
                 let ty::UpvarId {
                     var_id,
                     closure_expr_id
@@ -736,22 +736,19 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for Typeck
                     krate: local_id_root.krate,
                     index: closure_expr_id,
                 };
-                ((hcx.def_path_hash(var_owner_def_id), var_id.local_id),
-                 hcx.def_path_hash(closure_def_id))
-            });
-
-            ich::hash_stable_itemlocalmap(hcx, hasher, closure_tys);
-            ich::hash_stable_itemlocalmap(hcx, hasher, closure_kinds);
-            ich::hash_stable_itemlocalmap(hcx, hasher, liberated_fn_sigs);
-            ich::hash_stable_itemlocalmap(hcx, hasher, fru_field_types);
-            ich::hash_stable_itemlocalmap(hcx, hasher, cast_kinds);
-            ich::hash_stable_itemlocalmap(hcx, hasher, generator_sigs);
-            ich::hash_stable_itemlocalmap(hcx, hasher, generator_interiors);
-
-            ich::hash_stable_hashset(hcx, hasher, used_trait_imports, |hcx, def_id| {
-                hcx.def_path_hash(*def_id)
+                (hcx.tcx().def_path_hash(var_owner_def_id),
+                 var_id.local_id,
+                 hcx.tcx().def_path_hash(closure_def_id))
             });
 
+            closure_tys.hash_stable(hcx, hasher);
+            closure_kinds.hash_stable(hcx, hasher);
+            liberated_fn_sigs.hash_stable(hcx, hasher);
+            fru_field_types.hash_stable(hcx, hasher);
+            cast_kinds.hash_stable(hcx, hasher);
+            generator_sigs.hash_stable(hcx, hasher);
+            generator_interiors.hash_stable(hcx, hasher);
+            used_trait_imports.hash_stable(hcx, hasher);
             tainted_by_errors.hash_stable(hcx, hasher);
             free_region_map.hash_stable(hcx, hasher);
         })
diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs
index 1b2d09bef934c..e18c1969a91cc 100644
--- a/src/librustc_data_structures/stable_hasher.rs
+++ b/src/librustc_data_structures/stable_hasher.rs
@@ -289,7 +289,8 @@ impl<T1: HashStable<CTX>, CTX> HashStable<CTX> for (T1,) {
     fn hash_stable<W: StableHasherResult>(&self,
                                           ctx: &mut CTX,
                                           hasher: &mut StableHasher<W>) {
-        self.0.hash_stable(ctx, hasher);
+        let (ref _0,) = *self;
+        _0.hash_stable(ctx, hasher);
     }
 }
 
@@ -297,8 +298,24 @@ impl<T1: HashStable<CTX>, T2: HashStable<CTX>, CTX> HashStable<CTX> for (T1, T2)
     fn hash_stable<W: StableHasherResult>(&self,
                                           ctx: &mut CTX,
                                           hasher: &mut StableHasher<W>) {
-        self.0.hash_stable(ctx, hasher);
-        self.1.hash_stable(ctx, hasher);
+        let (ref _0, ref _1) = *self;
+        _0.hash_stable(ctx, hasher);
+        _1.hash_stable(ctx, hasher);
+    }
+}
+
+impl<T1, T2, T3, CTX> HashStable<CTX> for (T1, T2, T3)
+     where T1: HashStable<CTX>,
+           T2: HashStable<CTX>,
+           T3: HashStable<CTX>,
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          ctx: &mut CTX,
+                                          hasher: &mut StableHasher<W>) {
+        let (ref _0, ref _1, ref _2) = *self;
+        _0.hash_stable(ctx, hasher);
+        _1.hash_stable(ctx, hasher);
+        _2.hash_stable(ctx, hasher);
     }
 }
 
@@ -462,14 +479,11 @@ impl<K, V, R, HCX> HashStable<HCX> for ::std::collections::HashMap<K, V, R>
           V: HashStable<HCX>,
           R: BuildHasher,
 {
+    #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut HCX,
                                           hasher: &mut StableHasher<W>) {
-        let mut entries: Vec<_> = self.iter()
-                                      .map(|(k, v)| (k.to_stable_hash_key(hcx), v))
-                                      .collect();
-        entries.sort_unstable_by(|&(ref sk1, _), &(ref sk2, _)| sk1.cmp(sk2));
-        entries.hash_stable(hcx, hasher);
+        hash_stable_hashmap(hcx, hasher, self, ToStableHashKey::to_stable_hash_key);
     }
 }
 
@@ -516,3 +530,23 @@ impl<K, HCX> HashStable<HCX> for ::std::collections::BTreeSet<K>
         keys.hash_stable(hcx, hasher);
     }
 }
+
+pub fn hash_stable_hashmap<HCX, K, V, R, SK, F, W>(
+    hcx: &mut HCX,
+    hasher: &mut StableHasher<W>,
+    map: &::std::collections::HashMap<K, V, R>,
+    to_stable_hash_key: F)
+    where K: Eq + Hash,
+          V: HashStable<HCX>,
+          R: BuildHasher,
+          SK: HashStable<HCX> + Ord + Clone,
+          F: Fn(&K, &HCX) -> SK,
+          W: StableHasherResult,
+{
+    let mut entries: Vec<_> = map.iter()
+                                  .map(|(k, v)| (to_stable_hash_key(k, hcx), v))
+                                  .collect();
+    entries.sort_unstable_by(|&(ref sk1, _), &(ref sk2, _)| sk1.cmp(sk2));
+    entries.hash_stable(hcx, hasher);
+}
+

From dd501735ac8eb38756f8a4f4da91b0b7a4fbca1b Mon Sep 17 00:00:00 2001
From: Michael Woerister <michaelwoerister@posteo>
Date: Thu, 14 Sep 2017 12:08:03 +0200
Subject: [PATCH 18/24] incr.comp.: Initialize the CachingCodemapView in
 StableHashingContext lazily.

---
 src/librustc/ich/caching_codemap_view.rs | 10 ++++------
 src/librustc/ich/hcx.rs                  | 20 +++++++++++++++++---
 2 files changed, 21 insertions(+), 9 deletions(-)

diff --git a/src/librustc/ich/caching_codemap_view.rs b/src/librustc/ich/caching_codemap_view.rs
index 49e18f100cf26..71e442b3bb213 100644
--- a/src/librustc/ich/caching_codemap_view.rs
+++ b/src/librustc/ich/caching_codemap_view.rs
@@ -11,7 +11,6 @@
 use std::rc::Rc;
 use syntax::codemap::CodeMap;
 use syntax_pos::{BytePos, FileMap};
-use ty::TyCtxt;
 
 #[derive(Clone)]
 struct CacheEntry {
@@ -23,15 +22,14 @@ struct CacheEntry {
     file_index: usize,
 }
 
-pub struct CachingCodemapView<'tcx> {
-    codemap: &'tcx CodeMap,
+pub struct CachingCodemapView<'cm> {
+    codemap: &'cm CodeMap,
     line_cache: [CacheEntry; 3],
     time_stamp: usize,
 }
 
-impl<'gcx> CachingCodemapView<'gcx> {
-    pub fn new<'a, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> CachingCodemapView<'gcx> {
-        let codemap = tcx.sess.codemap();
+impl<'cm> CachingCodemapView<'cm> {
+    pub fn new(codemap: &'cm CodeMap) -> CachingCodemapView<'cm> {
         let files = codemap.files();
         let first_file = files[0].clone();
         let entry = CacheEntry {
diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs
index 0932c5ce8fb80..3f9590a45c68c 100644
--- a/src/librustc/ich/hcx.rs
+++ b/src/librustc/ich/hcx.rs
@@ -21,6 +21,7 @@ use std::collections::HashMap;
 
 use syntax::ast;
 use syntax::attr;
+use syntax::codemap::CodeMap;
 use syntax::ext::hygiene::SyntaxContext;
 use syntax::symbol::Symbol;
 use syntax_pos::Span;
@@ -36,13 +37,17 @@ use rustc_data_structures::accumulate_vec::AccumulateVec;
 /// things (e.g. each DefId/DefPath is only hashed once).
 pub struct StableHashingContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
-    codemap: CachingCodemapView<'gcx>,
     hash_spans: bool,
     hash_bodies: bool,
     overflow_checks_enabled: bool,
     node_id_hashing_mode: NodeIdHashingMode,
     // A sorted array of symbol keys for fast lookup.
     ignored_attr_names: Vec<Symbol>,
+
+    // Very often, we are hashing something that does not need the
+    // CachingCodemapView, so we initialize it lazily.
+    raw_codemap: &'gcx CodeMap,
+    caching_codemap: Option<CachingCodemapView<'gcx>>,
 }
 
 #[derive(PartialEq, Eq, Clone, Copy)]
@@ -66,7 +71,8 @@ impl<'a, 'gcx, 'tcx> StableHashingContext<'a, 'gcx, 'tcx> {
 
         StableHashingContext {
             tcx,
-            codemap: CachingCodemapView::new(tcx),
+            caching_codemap: None,
+            raw_codemap: tcx.sess.codemap(),
             hash_spans: hash_spans_initial,
             hash_bodies: true,
             overflow_checks_enabled: check_overflow_initial,
@@ -132,7 +138,15 @@ impl<'a, 'gcx, 'tcx> StableHashingContext<'a, 'gcx, 'tcx> {
 
     #[inline]
     pub fn codemap(&mut self) -> &mut CachingCodemapView<'gcx> {
-        &mut self.codemap
+        match self.caching_codemap {
+            Some(ref mut cm) => {
+                cm
+            }
+            ref mut none => {
+                *none = Some(CachingCodemapView::new(self.raw_codemap));
+                none.as_mut().unwrap()
+            }
+        }
     }
 
     #[inline]

From e567afbc584e32df6492d1ea29a65b583ca24e57 Mon Sep 17 00:00:00 2001
From: Michael Woerister <michaelwoerister@posteo>
Date: Thu, 14 Sep 2017 12:29:16 +0200
Subject: [PATCH 19/24] incr.comp.: Initialize IGNORED_ATTRS in
 StableHashingContext lazily.

---
 src/librustc/ich/hcx.rs          | 26 ++++++++++++++++----------
 src/librustc/ich/impls_syntax.rs |  5 +++++
 2 files changed, 21 insertions(+), 10 deletions(-)

diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs
index 3f9590a45c68c..616b966cb5058 100644
--- a/src/librustc/ich/hcx.rs
+++ b/src/librustc/ich/hcx.rs
@@ -17,6 +17,7 @@ use ty::{self, TyCtxt, fast_reject};
 
 use std::cmp::Ord;
 use std::hash as std_hash;
+use std::cell::RefCell;
 use std::collections::HashMap;
 
 use syntax::ast;
@@ -30,6 +31,10 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHashingContextProvi
                                            StableHasher, StableHasherResult,
                                            ToStableHashKey};
 use rustc_data_structures::accumulate_vec::AccumulateVec;
+use rustc_data_structures::fx::FxHashSet;
+
+thread_local!(static IGNORED_ATTR_NAMES: RefCell<FxHashSet<Symbol>> =
+    RefCell::new(FxHashSet()));
 
 /// This is the context state available during incr. comp. hashing. It contains
 /// enough information to transform DefIds and HirIds into stable DefPaths (i.e.
@@ -41,8 +46,6 @@ pub struct StableHashingContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     hash_bodies: bool,
     overflow_checks_enabled: bool,
     node_id_hashing_mode: NodeIdHashingMode,
-    // A sorted array of symbol keys for fast lookup.
-    ignored_attr_names: Vec<Symbol>,
 
     // Very often, we are hashing something that does not need the
     // CachingCodemapView, so we initialize it lazily.
@@ -62,12 +65,14 @@ impl<'a, 'gcx, 'tcx> StableHashingContext<'a, 'gcx, 'tcx> {
         let hash_spans_initial = tcx.sess.opts.debuginfo != NoDebugInfo;
         let check_overflow_initial = tcx.sess.overflow_checks();
 
-        let mut ignored_attr_names: Vec<_> = ich::IGNORED_ATTRIBUTES
-            .iter()
-            .map(|&s| Symbol::intern(s))
-            .collect();
-
-        ignored_attr_names.sort();
+        debug_assert!(ich::IGNORED_ATTRIBUTES.len() > 0);
+        IGNORED_ATTR_NAMES.with(|names| {
+            let mut names = names.borrow_mut();
+            if names.is_empty() {
+                names.extend(ich::IGNORED_ATTRIBUTES.iter()
+                                                    .map(|&s| Symbol::intern(s)));
+            }
+        });
 
         StableHashingContext {
             tcx,
@@ -77,7 +82,6 @@ impl<'a, 'gcx, 'tcx> StableHashingContext<'a, 'gcx, 'tcx> {
             hash_bodies: true,
             overflow_checks_enabled: check_overflow_initial,
             node_id_hashing_mode: NodeIdHashingMode::HashDefPath,
-            ignored_attr_names,
         }
     }
 
@@ -151,7 +155,9 @@ impl<'a, 'gcx, 'tcx> StableHashingContext<'a, 'gcx, 'tcx> {
 
     #[inline]
     pub fn is_ignored_attr(&self, name: Symbol) -> bool {
-        self.ignored_attr_names.binary_search(&name).is_ok()
+        IGNORED_ATTR_NAMES.with(|names| {
+            names.borrow().contains(&name)
+        })
     }
 
     pub fn hash_hir_item_like<F: FnOnce(&mut Self)>(&mut self,
diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs
index a75527c14bd69..4e3caca2b6131 100644
--- a/src/librustc/ich/impls_syntax.rs
+++ b/src/librustc/ich/impls_syntax.rs
@@ -169,6 +169,11 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for [ast::
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
                                           hasher: &mut StableHasher<W>) {
+        if self.len() == 0 {
+            self.len().hash_stable(hcx, hasher);
+            return
+        }
+
         // Some attributes are always ignored during hashing.
         let filtered: AccumulateVec<[&ast::Attribute; 8]> = self
             .iter()

From ba6f93ca76d7d71399a13d5c9722c3239497f8ef Mon Sep 17 00:00:00 2001
From: Michael Woerister <michaelwoerister@posteo>
Date: Thu, 14 Sep 2017 14:01:40 +0200
Subject: [PATCH 20/24] incr.comp.: Make the StableHashingContext mostly
 independent of the tcx.

---
 src/librustc/ich/hcx.rs                       | 49 ++++++++++++++++---
 src/librustc/ich/impls_hir.rs                 | 16 ++----
 src/librustc/ich/impls_syntax.rs              |  4 +-
 src/librustc/ty/context.rs                    |  4 +-
 src/librustc_incremental/calculate_svh/mod.rs | 27 +++++-----
 5 files changed, 61 insertions(+), 39 deletions(-)

diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs
index 616b966cb5058..136190f7573c1 100644
--- a/src/librustc/ich/hcx.rs
+++ b/src/librustc/ich/hcx.rs
@@ -9,11 +9,12 @@
 // except according to those terms.
 
 use hir;
-use hir::def_id::DefId;
+use hir::def_id::{DefId, DefIndex};
 use hir::map::DefPathHash;
 use ich::{self, CachingCodemapView};
 use session::config::DebugInfoLevel::NoDebugInfo;
 use ty::{self, TyCtxt, fast_reject};
+use session::Session;
 
 use std::cmp::Ord;
 use std::hash as std_hash;
@@ -42,6 +43,7 @@ thread_local!(static IGNORED_ATTR_NAMES: RefCell<FxHashSet<Symbol>> =
 /// things (e.g. each DefId/DefPath is only hashed once).
 pub struct StableHashingContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
+    body_resolver: BodyResolver<'gcx>,
     hash_spans: bool,
     hash_bodies: bool,
     overflow_checks_enabled: bool,
@@ -59,6 +61,20 @@ pub enum NodeIdHashingMode {
     HashDefPath,
 }
 
+/// The BodyResolver allows to map a BodyId to the corresponding hir::Body.
+/// We could also just store a plain reference to the hir::Crate but we want
+/// to avoid that the crate is used to get untracked access to all of the HIR.
+#[derive(Clone, Copy)]
+struct BodyResolver<'hir>(&'hir hir::Crate);
+
+impl<'hir> BodyResolver<'hir> {
+    // Return a reference to the hir::Body with the given BodyId.
+    // DOES NOT DO ANY TRACKING, use carefully.
+    fn body(self, id: hir::BodyId) -> &'hir hir::Body {
+        self.0.body(id)
+    }
+}
+
 impl<'a, 'gcx, 'tcx> StableHashingContext<'a, 'gcx, 'tcx> {
 
     pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Self {
@@ -74,8 +90,11 @@ impl<'a, 'gcx, 'tcx> StableHashingContext<'a, 'gcx, 'tcx> {
             }
         });
 
+        let body_resolver = BodyResolver(tcx.dep_graph.with_ignore(|| tcx.hir.krate()));
+
         StableHashingContext {
             tcx,
+            body_resolver,
             caching_codemap: None,
             raw_codemap: tcx.sess.codemap(),
             hash_spans: hash_spans_initial,
@@ -85,6 +104,11 @@ impl<'a, 'gcx, 'tcx> StableHashingContext<'a, 'gcx, 'tcx> {
         }
     }
 
+    #[inline]
+    pub fn sess(&self) -> &'gcx Session {
+        self.tcx.sess
+    }
+
     pub fn force_span_hashing(mut self) -> Self {
         self.hash_spans = true;
         self
@@ -121,13 +145,13 @@ impl<'a, 'gcx, 'tcx> StableHashingContext<'a, 'gcx, 'tcx> {
     }
 
     #[inline]
-    pub fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
-        self.tcx
+    pub fn def_path_hash(&self, def_id: DefId) -> DefPathHash {
+        self.tcx.def_path_hash(def_id)
     }
 
     #[inline]
-    pub fn def_path_hash(&mut self, def_id: DefId) -> DefPathHash {
-        self.tcx.def_path_hash(def_id)
+    pub fn local_def_path_hash(&self, def_index: DefIndex) -> DefPathHash {
+        self.tcx.hir.definitions().def_path_hash(def_index)
     }
 
     #[inline]
@@ -221,6 +245,16 @@ impl<'a, 'gcx, 'lcx> StableHashingContextProvider for ty::TyCtxt<'a, 'gcx, 'lcx>
     }
 }
 
+impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::BodyId {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        if hcx.hash_bodies() {
+            hcx.body_resolver.body(*self).hash_stable(hcx, hasher);
+        }
+    }
+}
+
 impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::HirId {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
@@ -250,7 +284,7 @@ impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>> for h
     fn to_stable_hash_key(&self,
                           hcx: &StableHashingContext<'a, 'gcx, 'tcx>)
                           -> (DefPathHash, hir::ItemLocalId) {
-        let def_path_hash = hcx.tcx().hir.definitions().def_path_hash(self.owner);
+        let def_path_hash = hcx.local_def_path_hash(self.owner);
         (def_path_hash, self.local_id)
     }
 }
@@ -378,10 +412,9 @@ pub fn hash_stable_trait_impls<'a, 'tcx, 'gcx, W, R>(
     }
 
     {
-        let tcx = hcx.tcx();
         let mut keys: AccumulateVec<[_; 8]> =
             non_blanket_impls.keys()
-                             .map(|k| (k, k.map_def(|d| tcx.def_path_hash(d))))
+                             .map(|k| (k, k.map_def(|d| hcx.def_path_hash(d))))
                              .collect();
         keys.sort_unstable_by(|&(_, ref k1), &(_, ref k2)| k1.cmp(k2));
         keys.len().hash_stable(hcx, hasher);
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index 3c89e10a0d2d9..aa4826528ec6d 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -34,7 +34,7 @@ impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>> for D
 
     #[inline]
     fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a, 'gcx, 'tcx>) -> DefPathHash {
-        hcx.tcx().def_path_hash(*self)
+        hcx.def_path_hash(*self)
     }
 }
 
@@ -995,16 +995,6 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::B
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::BodyId {
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
-                                          hasher: &mut StableHasher<W>) {
-        if hcx.hash_bodies() {
-            hcx.tcx().hir.body(*self).hash_stable(hcx, hasher);
-        }
-    }
-}
-
 impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>> for hir::BodyId {
     type KeyType = (DefPathHash, hir::ItemLocalId);
 
@@ -1119,7 +1109,7 @@ for hir::def_id::DefIndex {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
                                           hasher: &mut StableHasher<W>) {
-        hcx.tcx().hir.definitions().def_path_hash(*self).hash_stable(hcx, hasher);
+        hcx.local_def_path_hash(*self).hash_stable(hcx, hasher);
     }
 }
 
@@ -1129,7 +1119,7 @@ for hir::def_id::DefIndex {
 
     #[inline]
     fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a, 'gcx, 'tcx>) -> DefPathHash {
-         hcx.tcx().hir.definitions().def_path_hash(*self)
+         hcx.local_def_path_hash(*self)
     }
 }
 
diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs
index 4e3caca2b6131..6bcbce4b69304 100644
--- a/src/librustc/ich/impls_syntax.rs
+++ b/src/librustc/ich/impls_syntax.rs
@@ -324,11 +324,11 @@ fn hash_token<'a, 'gcx, 'tcx, W: StableHasherResult>(token: &token::Token,
             //            in a stable way, in addition to the HIR.
             //            Since this is hardly used anywhere, just emit a
             //            warning for now.
-            if hcx.tcx().sess.opts.debugging_opts.incremental.is_some() {
+            if hcx.sess().opts.debugging_opts.incremental.is_some() {
                 let msg = format!("Quasi-quoting might make incremental \
                                    compilation very inefficient: {:?}",
                                   non_terminal);
-                hcx.tcx().sess.span_warn(error_reporting_span, &msg[..]);
+                hcx.sess().span_warn(error_reporting_span, &msg[..]);
             }
 
             std_hash::Hash::hash(non_terminal, hasher);
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 0ea466a1bbcc3..61cd5db9a1948 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -736,9 +736,9 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for Typeck
                     krate: local_id_root.krate,
                     index: closure_expr_id,
                 };
-                (hcx.tcx().def_path_hash(var_owner_def_id),
+                (hcx.def_path_hash(var_owner_def_id),
                  var_id.local_id,
-                 hcx.tcx().def_path_hash(closure_def_id))
+                 hcx.def_path_hash(closure_def_id))
             });
 
             closure_tys.hash_stable(hcx, hasher);
diff --git a/src/librustc_incremental/calculate_svh/mod.rs b/src/librustc_incremental/calculate_svh/mod.rs
index d8e201d3acdcf..60e1f238f44a4 100644
--- a/src/librustc_incremental/calculate_svh/mod.rs
+++ b/src/librustc_incremental/calculate_svh/mod.rs
@@ -90,6 +90,7 @@ impl<'a> ::std::ops::Index<&'a DepNode> for IncrementalHashesMap {
 }
 
 struct ComputeItemHashesVisitor<'a, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     hcx: StableHashingContext<'a, 'tcx, 'tcx>,
     hashes: IncrementalHashesMap,
 }
@@ -101,14 +102,14 @@ impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> {
                                               item_like: T)
         where T: HashStable<StableHashingContext<'a, 'tcx, 'tcx>>
     {
-        if !hash_bodies && !self.hcx.tcx().sess.opts.build_dep_graph() {
+        if !hash_bodies && !self.tcx.sess.opts.build_dep_graph() {
             // If we just need the hashes in order to compute the SVH, we don't
             // need have two hashes per item. Just the one containing also the
             // item's body is sufficient.
             return
         }
 
-        let def_path_hash = self.hcx.tcx().hir.definitions().def_path_hash(def_index);
+        let def_path_hash = self.hcx.local_def_path_hash(def_index);
 
         let mut hasher = IchHasher::new();
         self.hcx.while_hashing_hir_bodies(hash_bodies, |hcx| {
@@ -125,14 +126,12 @@ impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> {
         debug!("calculate_def_hash: dep_node={:?} hash={:?}", dep_node, item_hash);
         self.hashes.insert(dep_node, item_hash);
 
-        let tcx = self.hcx.tcx();
         let bytes_hashed =
-            tcx.sess.perf_stats.incr_comp_bytes_hashed.get() +
-            bytes_hashed;
-        tcx.sess.perf_stats.incr_comp_bytes_hashed.set(bytes_hashed);
+            self.tcx.sess.perf_stats.incr_comp_bytes_hashed.get() + bytes_hashed;
+        self.tcx.sess.perf_stats.incr_comp_bytes_hashed.set(bytes_hashed);
 
         if hash_bodies {
-            let in_scope_traits_map = tcx.in_scope_traits_map(def_index);
+            let in_scope_traits_map = self.tcx.in_scope_traits_map(def_index);
             let mut hasher = IchHasher::new();
             in_scope_traits_map.hash_stable(&mut self.hcx, &mut hasher);
             let dep_node = def_path_hash.to_dep_node(DepKind::InScopeTraits);
@@ -141,12 +140,11 @@ impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> {
     }
 
     fn compute_crate_hash(&mut self) {
-        let tcx = self.hcx.tcx();
-        let krate = tcx.hir.krate();
+        let krate = self.tcx.hir.krate();
 
         let mut crate_state = IchHasher::new();
 
-        let crate_disambiguator = tcx.sess.local_crate_disambiguator();
+        let crate_disambiguator = self.tcx.sess.local_crate_disambiguator();
         "crate_disambiguator".hash(&mut crate_state);
         crate_disambiguator.as_str().len().hash(&mut crate_state);
         crate_disambiguator.as_str().hash(&mut crate_state);
@@ -221,7 +219,7 @@ impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> {
 
     fn compute_and_store_ich_for_trait_impls(&mut self, krate: &'tcx hir::Crate)
     {
-        let tcx = self.hcx.tcx();
+        let tcx = self.tcx;
 
         let mut impls: Vec<(DefPathHash, Fingerprint)> = krate
             .trait_impls
@@ -266,7 +264,7 @@ impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> {
 
 impl<'a, 'tcx: 'a> ItemLikeVisitor<'tcx> for ComputeItemHashesVisitor<'a, 'tcx> {
     fn visit_item(&mut self, item: &'tcx hir::Item) {
-        let def_index = self.hcx.tcx().hir.local_def_id(item.id).index;
+        let def_index = self.tcx.hir.local_def_id(item.id).index;
         self.compute_and_store_ich_for_item_like(def_index,
                                                  false,
                                                  item);
@@ -276,7 +274,7 @@ impl<'a, 'tcx: 'a> ItemLikeVisitor<'tcx> for ComputeItemHashesVisitor<'a, 'tcx>
     }
 
     fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) {
-        let def_index = self.hcx.tcx().hir.local_def_id(item.id).index;
+        let def_index = self.tcx.hir.local_def_id(item.id).index;
         self.compute_and_store_ich_for_item_like(def_index,
                                                  false,
                                                  item);
@@ -286,7 +284,7 @@ impl<'a, 'tcx: 'a> ItemLikeVisitor<'tcx> for ComputeItemHashesVisitor<'a, 'tcx>
     }
 
     fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) {
-        let def_index = self.hcx.tcx().hir.local_def_id(item.id).index;
+        let def_index = self.tcx.hir.local_def_id(item.id).index;
         self.compute_and_store_ich_for_item_like(def_index,
                                                  false,
                                                  item);
@@ -304,6 +302,7 @@ pub fn compute_incremental_hashes_map<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
     let krate = tcx.hir.krate();
 
     let mut visitor = ComputeItemHashesVisitor {
+        tcx,
         hcx: StableHashingContext::new(tcx),
         hashes: IncrementalHashesMap::new(),
     };

From d5b1fee6fd658bf464902d46f9a6c9c2f8ab87d7 Mon Sep 17 00:00:00 2001
From: Michael Woerister <michaelwoerister@posteo>
Date: Thu, 14 Sep 2017 15:10:24 +0200
Subject: [PATCH 21/24] incr.comp.: Remove tcx from StableHashingContext.

---
 src/librustc/dep_graph/dep_node.rs            |   4 +-
 src/librustc/hir/map/mod.rs                   |   8 +-
 src/librustc/ich/hcx.rs                       |  88 +++++++------
 src/librustc/ich/impls_hir.rs                 | 120 +++++++++---------
 src/librustc/ich/impls_mir.rs                 |  80 ++++++------
 src/librustc/ich/impls_syntax.rs              |  48 +++----
 src/librustc/ich/impls_ty.rs                  | 104 +++++++--------
 src/librustc/lint/levels.rs                   |   4 +-
 src/librustc/macros.rs                        |  16 +--
 src/librustc/middle/region.rs                 |   4 +-
 src/librustc/mir/cache.rs                     |   4 +-
 .../traits/specialize/specialization_graph.rs |   4 +-
 src/librustc/ty/context.rs                    |  13 +-
 src/librustc/ty/fast_reject.rs                |   6 +-
 src/librustc/ty/layout.rs                     |   8 +-
 src/librustc/ty/mod.rs                        |   8 +-
 src/librustc/ty/trait_def.rs                  |   4 +-
 src/librustc/ty/util.rs                       |   4 +-
 src/librustc_driver/driver.rs                 |   2 +-
 src/librustc_driver/test.rs                   |   2 +-
 src/librustc_incremental/calculate_svh/mod.rs |   6 +-
 src/librustc_metadata/astencode.rs            |   4 +-
 src/librustc_metadata/isolated_encoder.rs     |  16 +--
 src/librustc_metadata/schema.rs               |   8 +-
 src/librustc_trans/context.rs                 |   4 +-
 src/librustc_typeck/variance/constraints.rs   |   4 +-
 src/librustdoc/core.rs                        |   2 +-
 src/librustdoc/test.rs                        |   2 +-
 28 files changed, 300 insertions(+), 277 deletions(-)

diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 1dcc9272d4e02..7c21bba49f81b 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -603,12 +603,12 @@ trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug {
 }
 
 impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a, T> DepNodeParams<'a, 'gcx, 'tcx> for T
-    where T: HashStable<StableHashingContext<'a, 'gcx, 'tcx>> + fmt::Debug
+    where T: HashStable<StableHashingContext<'gcx>> + fmt::Debug
 {
     default const CAN_RECONSTRUCT_QUERY_KEY: bool = false;
 
     default fn to_fingerprint(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Fingerprint {
-        let mut hcx = StableHashingContext::new(tcx);
+        let mut hcx = tcx.create_stable_hashing_context();
         let mut hasher = StableHasher::new();
 
         self.hash_stable(&mut hcx, &mut hasher);
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index d043d8346e6a8..b2d6886e7f228 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -247,7 +247,7 @@ pub struct Map<'hir> {
     /// plain old integers.
     map: Vec<MapEntry<'hir>>,
 
-    definitions: Definitions,
+    definitions: &'hir Definitions,
 
     /// Bodies inlined from other crates are cached here.
     inlined_bodies: RefCell<DefIdMap<&'hir Body>>,
@@ -304,8 +304,8 @@ impl<'hir> Map<'hir> {
     }
 
     #[inline]
-    pub fn definitions(&self) -> &Definitions {
-        &self.definitions
+    pub fn definitions(&self) -> &'hir Definitions {
+        self.definitions
     }
 
     pub fn def_key(&self, def_id: DefId) -> DefKey {
@@ -1013,7 +1013,7 @@ impl Named for TraitItem { fn name(&self) -> Name { self.name } }
 impl Named for ImplItem { fn name(&self) -> Name { self.name } }
 
 pub fn map_crate<'hir>(forest: &'hir mut Forest,
-                       definitions: Definitions)
+                       definitions: &'hir Definitions)
                        -> Map<'hir> {
     let map = {
         let mut collector = NodeCollector::root(&forest.krate,
diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs
index 136190f7573c1..0a2566f069249 100644
--- a/src/librustc/ich/hcx.rs
+++ b/src/librustc/ich/hcx.rs
@@ -11,7 +11,9 @@
 use hir;
 use hir::def_id::{DefId, DefIndex};
 use hir::map::DefPathHash;
+use hir::map::definitions::Definitions;
 use ich::{self, CachingCodemapView};
+use middle::cstore::CrateStore;
 use session::config::DebugInfoLevel::NoDebugInfo;
 use ty::{self, TyCtxt, fast_reject};
 use session::Session;
@@ -41,8 +43,10 @@ thread_local!(static IGNORED_ATTR_NAMES: RefCell<FxHashSet<Symbol>> =
 /// enough information to transform DefIds and HirIds into stable DefPaths (i.e.
 /// a reference to the TyCtxt) and it holds a few caches for speeding up various
 /// things (e.g. each DefId/DefPath is only hashed once).
-pub struct StableHashingContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'gcx, 'tcx>,
+pub struct StableHashingContext<'gcx> {
+    sess: &'gcx Session,
+    definitions: &'gcx Definitions,
+    cstore: &'gcx CrateStore,
     body_resolver: BodyResolver<'gcx>,
     hash_spans: bool,
     hash_bodies: bool,
@@ -65,21 +69,27 @@ pub enum NodeIdHashingMode {
 /// We could also just store a plain reference to the hir::Crate but we want
 /// to avoid that the crate is used to get untracked access to all of the HIR.
 #[derive(Clone, Copy)]
-struct BodyResolver<'hir>(&'hir hir::Crate);
+struct BodyResolver<'gcx>(&'gcx hir::Crate);
 
-impl<'hir> BodyResolver<'hir> {
+impl<'gcx> BodyResolver<'gcx> {
     // Return a reference to the hir::Body with the given BodyId.
     // DOES NOT DO ANY TRACKING, use carefully.
-    fn body(self, id: hir::BodyId) -> &'hir hir::Body {
+    fn body(self, id: hir::BodyId) -> &'gcx hir::Body {
         self.0.body(id)
     }
 }
 
-impl<'a, 'gcx, 'tcx> StableHashingContext<'a, 'gcx, 'tcx> {
-
-    pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Self {
-        let hash_spans_initial = tcx.sess.opts.debuginfo != NoDebugInfo;
-        let check_overflow_initial = tcx.sess.overflow_checks();
+impl<'gcx> StableHashingContext<'gcx> {
+    // The `krate` here is only used for mapping BodyIds to Bodies.
+    // Don't use it for anything else or you'll run the risk of
+    // leaking data out of the tracking system.
+    pub fn new(sess: &'gcx Session,
+               krate: &'gcx hir::Crate,
+               definitions: &'gcx Definitions,
+               cstore: &'gcx CrateStore)
+               -> Self {
+        let hash_spans_initial = sess.opts.debuginfo != NoDebugInfo;
+        let check_overflow_initial = sess.overflow_checks();
 
         debug_assert!(ich::IGNORED_ATTRIBUTES.len() > 0);
         IGNORED_ATTR_NAMES.with(|names| {
@@ -90,13 +100,13 @@ impl<'a, 'gcx, 'tcx> StableHashingContext<'a, 'gcx, 'tcx> {
             }
         });
 
-        let body_resolver = BodyResolver(tcx.dep_graph.with_ignore(|| tcx.hir.krate()));
-
         StableHashingContext {
-            tcx,
-            body_resolver,
+            sess,
+            body_resolver: BodyResolver(krate),
+            definitions,
+            cstore,
             caching_codemap: None,
-            raw_codemap: tcx.sess.codemap(),
+            raw_codemap: sess.codemap(),
             hash_spans: hash_spans_initial,
             hash_bodies: true,
             overflow_checks_enabled: check_overflow_initial,
@@ -106,7 +116,7 @@ impl<'a, 'gcx, 'tcx> StableHashingContext<'a, 'gcx, 'tcx> {
 
     #[inline]
     pub fn sess(&self) -> &'gcx Session {
-        self.tcx.sess
+        self.sess
     }
 
     pub fn force_span_hashing(mut self) -> Self {
@@ -146,12 +156,16 @@ impl<'a, 'gcx, 'tcx> StableHashingContext<'a, 'gcx, 'tcx> {
 
     #[inline]
     pub fn def_path_hash(&self, def_id: DefId) -> DefPathHash {
-        self.tcx.def_path_hash(def_id)
+        if def_id.is_local() {
+            self.definitions.def_path_hash(def_id.index)
+        } else {
+            self.cstore.def_path_hash(def_id)
+        }
     }
 
     #[inline]
     pub fn local_def_path_hash(&self, def_index: DefIndex) -> DefPathHash {
-        self.tcx.hir.definitions().def_path_hash(def_index)
+        self.definitions.def_path_hash(def_index)
     }
 
     #[inline]
@@ -239,15 +253,15 @@ impl<'a, 'gcx, 'tcx> StableHashingContext<'a, 'gcx, 'tcx> {
 }
 
 impl<'a, 'gcx, 'lcx> StableHashingContextProvider for ty::TyCtxt<'a, 'gcx, 'lcx> {
-    type ContextType = StableHashingContext<'a, 'gcx, 'lcx>;
+    type ContextType = StableHashingContext<'gcx>;
     fn create_stable_hashing_context(&self) -> Self::ContextType {
-        StableHashingContext::new(*self)
+        (*self).create_stable_hashing_context()
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::BodyId {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::BodyId {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         if hcx.hash_bodies() {
             hcx.body_resolver.body(*self).hash_stable(hcx, hasher);
@@ -255,10 +269,10 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::B
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::HirId {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::HirId {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         match hcx.node_id_hashing_mode {
             NodeIdHashingMode::Ignore => {
@@ -270,52 +284,52 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::H
                     local_id,
                 } = *self;
 
-                hcx.tcx.hir.definitions().def_path_hash(owner).hash_stable(hcx, hasher);
+                hcx.local_def_path_hash(owner).hash_stable(hcx, hasher);
                 local_id.hash_stable(hcx, hasher);
             }
         }
     }
 }
 
-impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>> for hir::HirId {
+impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for hir::HirId {
     type KeyType = (DefPathHash, hir::ItemLocalId);
 
     #[inline]
     fn to_stable_hash_key(&self,
-                          hcx: &StableHashingContext<'a, 'gcx, 'tcx>)
+                          hcx: &StableHashingContext<'gcx>)
                           -> (DefPathHash, hir::ItemLocalId) {
         let def_path_hash = hcx.local_def_path_hash(self.owner);
         (def_path_hash, self.local_id)
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ast::NodeId {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for ast::NodeId {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         match hcx.node_id_hashing_mode {
             NodeIdHashingMode::Ignore => {
                 // Don't do anything.
             }
             NodeIdHashingMode::HashDefPath => {
-                hcx.tcx.hir.node_to_hir_id(*self).hash_stable(hcx, hasher);
+                hcx.definitions.node_to_hir_id(*self).hash_stable(hcx, hasher);
             }
         }
     }
 }
 
-impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>> for ast::NodeId {
+impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for ast::NodeId {
     type KeyType = (DefPathHash, hir::ItemLocalId);
 
     #[inline]
     fn to_stable_hash_key(&self,
-                          hcx: &StableHashingContext<'a, 'gcx, 'tcx>)
+                          hcx: &StableHashingContext<'gcx>)
                           -> (DefPathHash, hir::ItemLocalId) {
-        hcx.tcx.hir.node_to_hir_id(*self).to_stable_hash_key(hcx)
+        hcx.definitions.node_to_hir_id(*self).to_stable_hash_key(hcx)
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for Span {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for Span {
 
     // Hash a span in a stable way. We can't directly hash the span's BytePos
     // fields (that would be similar to hashing pointers, since those are just
@@ -327,7 +341,7 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for Span {
     // Also, hashing filenames is expensive so we avoid doing it twice when the
     // span starts and ends in the same file, which is almost always the case.
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         use syntax_pos::Pos;
 
@@ -390,8 +404,8 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for Span {
     }
 }
 
-pub fn hash_stable_trait_impls<'a, 'tcx, 'gcx, W, R>(
-    hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+pub fn hash_stable_trait_impls<'gcx, W, R>(
+    hcx: &mut StableHashingContext<'gcx>,
     hasher: &mut StableHasher<W>,
     blanket_impls: &Vec<DefId>,
     non_blanket_impls: &HashMap<fast_reject::SimplifiedType, Vec<DefId>, R>)
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index aa4826528ec6d..9582b03ce1c8a 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -20,28 +20,28 @@ use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey,
 use std::mem;
 use syntax::ast;
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for DefId {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for DefId {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         hcx.def_path_hash(*self).hash_stable(hcx, hasher);
     }
 }
 
-impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>> for DefId {
+impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for DefId {
     type KeyType = DefPathHash;
 
     #[inline]
-    fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a, 'gcx, 'tcx>) -> DefPathHash {
+    fn to_stable_hash_key(&self, hcx: &StableHashingContext<'gcx>) -> DefPathHash {
         hcx.def_path_hash(*self)
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for CrateNum {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for CrateNum {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         hcx.def_path_hash(DefId {
             krate: *self,
@@ -50,11 +50,11 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for CrateN
     }
 }
 
-impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>> for CrateNum {
+impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for CrateNum {
     type KeyType = DefPathHash;
 
     #[inline]
-    fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a, 'gcx, 'tcx>) -> DefPathHash {
+    fn to_stable_hash_key(&self, hcx: &StableHashingContext<'gcx>) -> DefPathHash {
         let def_id = DefId { krate: *self, index: CRATE_DEF_INDEX };
         def_id.to_stable_hash_key(hcx)
     }
@@ -62,13 +62,13 @@ impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>> for C
 
 impl_stable_hash_for!(tuple_struct hir::ItemLocalId { index });
 
-impl<'a, 'gcx, 'lcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'lcx>>
+impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>>
 for hir::ItemLocalId {
     type KeyType = hir::ItemLocalId;
 
     #[inline]
     fn to_stable_hash_key(&self,
-                          _: &StableHashingContext<'a, 'gcx, 'lcx>)
+                          _: &StableHashingContext<'gcx>)
                           -> hir::ItemLocalId {
         *self
     }
@@ -81,9 +81,9 @@ for hir::ItemLocalId {
 // want to pick up on a reference changing its target, so we hash the NodeIds
 // in "DefPath Mode".
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::ItemId {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::ItemId {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         let hir::ItemId {
             id
@@ -95,9 +95,9 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::I
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::TraitItemId {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::TraitItemId {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         let hir::TraitItemId {
             node_id
@@ -109,9 +109,9 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::T
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::ImplItemId {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::ImplItemId {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         let hir::ImplItemId {
             node_id
@@ -231,9 +231,9 @@ impl_stable_hash_for!(struct hir::TypeBinding {
     span
 });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::Ty {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Ty {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         hcx.while_hashing_hir_bodies(true, |hcx| {
             let hir::Ty {
@@ -292,9 +292,9 @@ impl_stable_hash_for!(enum hir::FunctionRetTy {
     Return(t)
 });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::TraitRef {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::TraitRef {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         let hir::TraitRef {
             ref path,
@@ -329,9 +329,9 @@ impl_stable_hash_for!(struct hir::MacroDef {
 });
 
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::Block {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Block {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         let hir::Block {
             ref stmts,
@@ -377,9 +377,9 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::B
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::Pat {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Pat {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         let hir::Pat {
             id: _,
@@ -504,9 +504,9 @@ impl_stable_hash_for!(enum hir::UnsafeSource {
     UserProvided
 });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::Expr {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Expr {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         hcx.while_hashing_hir_bodies(true, |hcx| {
             let hir::Expr {
@@ -622,9 +622,9 @@ impl_stable_hash_for!(enum hir::LoopSource {
     ForLoop
 });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::MatchSource {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::MatchSource {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         use hir::MatchSource;
 
@@ -673,9 +673,9 @@ impl_stable_hash_for!(enum hir::ScopeTarget {
     Loop(loop_id_result)
 });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ast::Ident {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for ast::Ident {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         let ast::Ident {
             ref name,
@@ -686,9 +686,9 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ast::I
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::TraitItem {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::TraitItem {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         let hir::TraitItem {
             id,
@@ -720,9 +720,9 @@ impl_stable_hash_for!(enum hir::TraitItemKind {
     Type(bounds, rhs)
 });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::ImplItem {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::ImplItem {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         let hir::ImplItem {
             id,
@@ -753,9 +753,9 @@ impl_stable_hash_for!(enum hir::ImplItemKind {
     Type(t)
 });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::Visibility {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Visibility {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
@@ -774,9 +774,9 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::V
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::Defaultness {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Defaultness {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
@@ -795,9 +795,9 @@ impl_stable_hash_for!(enum hir::ImplPolarity {
     Negative
 });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::Mod {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Mod {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         let hir::Mod {
             inner,
@@ -850,9 +850,9 @@ impl_stable_hash_for!(enum hir::VariantData {
     Unit(id)
 });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::Item {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Item {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         let hash_spans = match self.node {
             hir::ItemStatic(..)      |
@@ -933,10 +933,10 @@ impl_stable_hash_for!(struct hir::ImplItemRef {
     defaultness
 });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+impl<'gcx> HashStable<StableHashingContext<'gcx>>
 for hir::AssociatedItemKind {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
@@ -977,9 +977,9 @@ impl_stable_hash_for!(struct hir::Arg {
     hir_id
 });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::Body {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Body {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         let hir::Body {
             ref arguments,
@@ -995,12 +995,12 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::B
     }
 }
 
-impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>> for hir::BodyId {
+impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for hir::BodyId {
     type KeyType = (DefPathHash, hir::ItemLocalId);
 
     #[inline]
     fn to_stable_hash_key(&self,
-                          hcx: &StableHashingContext<'a, 'gcx, 'tcx>)
+                          hcx: &StableHashingContext<'gcx>)
                           -> (DefPathHash, hir::ItemLocalId) {
         let hir::BodyId { node_id } = *self;
         node_id.to_stable_hash_key(hcx)
@@ -1013,9 +1013,9 @@ impl_stable_hash_for!(struct hir::InlineAsmOutput {
     is_indirect
 });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::GlobalAsm {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::GlobalAsm {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         let hir::GlobalAsm {
             asm,
@@ -1026,9 +1026,9 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::G
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::InlineAsm {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::InlineAsm {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         let hir::InlineAsm {
             asm,
@@ -1103,22 +1103,22 @@ impl_stable_hash_for!(enum hir::Constness {
     NotConst
 });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+impl<'gcx> HashStable<StableHashingContext<'gcx>>
 for hir::def_id::DefIndex {
 
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         hcx.local_def_path_hash(*self).hash_stable(hcx, hasher);
     }
 }
 
-impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>>
+impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>>
 for hir::def_id::DefIndex {
     type KeyType = DefPathHash;
 
     #[inline]
-    fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a, 'gcx, 'tcx>) -> DefPathHash {
+    fn to_stable_hash_key(&self, hcx: &StableHashingContext<'gcx>) -> DefPathHash {
          hcx.local_def_path_hash(*self)
     }
 }
@@ -1129,10 +1129,10 @@ impl_stable_hash_for!(struct hir::def::Export {
     span
 });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+impl<'gcx> HashStable<StableHashingContext<'gcx>>
 for ::middle::lang_items::LangItem {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          _: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          _: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         ::std::hash::Hash::hash(self, hasher);
     }
@@ -1143,10 +1143,10 @@ impl_stable_hash_for!(struct ::middle::lang_items::LanguageItems {
     missing
 });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+impl<'gcx> HashStable<StableHashingContext<'gcx>>
 for hir::TraitCandidate {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
             let hir::TraitCandidate {
diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs
index dce1639b375b7..9b6613e4cae96 100644
--- a/src/librustc/ich/impls_mir.rs
+++ b/src/librustc/ich/impls_mir.rs
@@ -33,11 +33,11 @@ impl_stable_hash_for!(struct mir::LocalDecl<'tcx> {
 impl_stable_hash_for!(struct mir::UpvarDecl { debug_name, by_ref });
 impl_stable_hash_for!(struct mir::BasicBlockData<'tcx> { statements, terminator, is_cleanup });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+impl<'gcx> HashStable<StableHashingContext<'gcx>>
 for mir::Terminator<'gcx> {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         let mir::Terminator {
             ref kind,
@@ -76,61 +76,61 @@ for mir::Terminator<'gcx> {
 }
 
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for mir::Local {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Local {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         use rustc_data_structures::indexed_vec::Idx;
         self.index().hash_stable(hcx, hasher);
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for mir::BasicBlock {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::BasicBlock {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         use rustc_data_structures::indexed_vec::Idx;
         self.index().hash_stable(hcx, hasher);
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for mir::Field {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Field {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         use rustc_data_structures::indexed_vec::Idx;
         self.index().hash_stable(hcx, hasher);
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+impl<'gcx> HashStable<StableHashingContext<'gcx>>
 for mir::VisibilityScope {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         use rustc_data_structures::indexed_vec::Idx;
         self.index().hash_stable(hcx, hasher);
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for mir::Promoted {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Promoted {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         use rustc_data_structures::indexed_vec::Idx;
         self.index().hash_stable(hcx, hasher);
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+impl<'gcx> HashStable<StableHashingContext<'gcx>>
 for mir::TerminatorKind<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
 
@@ -196,10 +196,10 @@ for mir::TerminatorKind<'gcx> {
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+impl<'gcx> HashStable<StableHashingContext<'gcx>>
 for mir::AssertMessage<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
 
@@ -219,10 +219,10 @@ for mir::AssertMessage<'gcx> {
 
 impl_stable_hash_for!(struct mir::Statement<'tcx> { source_info, kind });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+impl<'gcx> HashStable<StableHashingContext<'gcx>>
 for mir::StatementKind<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
 
@@ -256,12 +256,12 @@ for mir::StatementKind<'gcx> {
     }
 }
 
-impl<'a, 'gcx, 'tcx, T> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+impl<'gcx, T> HashStable<StableHashingContext<'gcx>>
     for mir::ValidationOperand<'gcx, T>
-    where T: HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+    where T: HashStable<StableHashingContext<'gcx>>
 {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>)
     {
         self.lval.hash_stable(hcx, hasher);
@@ -273,9 +273,9 @@ impl<'a, 'gcx, 'tcx, T> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
 
 impl_stable_hash_for!(enum mir::ValidationOp { Acquire, Release, Suspend(region_scope) });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for mir::Lvalue<'gcx> {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Lvalue<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
@@ -292,14 +292,14 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for mir::L
     }
 }
 
-impl<'a, 'gcx, 'tcx, B, V, T> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+impl<'gcx, B, V, T> HashStable<StableHashingContext<'gcx>>
 for mir::Projection<'gcx, B, V, T>
-    where B: HashStable<StableHashingContext<'a, 'gcx, 'tcx>>,
-          V: HashStable<StableHashingContext<'a, 'gcx, 'tcx>>,
-          T: HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+    where B: HashStable<StableHashingContext<'gcx>>,
+          V: HashStable<StableHashingContext<'gcx>>,
+          T: HashStable<StableHashingContext<'gcx>>
 {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         let mir::Projection {
             ref base,
@@ -311,13 +311,13 @@ for mir::Projection<'gcx, B, V, T>
     }
 }
 
-impl<'a, 'gcx, 'tcx, V, T> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+impl<'gcx, V, T> HashStable<StableHashingContext<'gcx>>
 for mir::ProjectionElem<'gcx, V, T>
-    where V: HashStable<StableHashingContext<'a, 'gcx, 'tcx>>,
-          T: HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+    where V: HashStable<StableHashingContext<'gcx>>,
+          T: HashStable<StableHashingContext<'gcx>>
 {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
@@ -348,9 +348,9 @@ for mir::ProjectionElem<'gcx, V, T>
 
 impl_stable_hash_for!(struct mir::VisibilityScopeData { span, parent_scope });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for mir::Operand<'gcx> {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Operand<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
 
@@ -365,9 +365,9 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for mir::O
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for mir::Rvalue<'gcx> {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Rvalue<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
 
@@ -425,10 +425,10 @@ impl_stable_hash_for!(enum mir::CastKind {
     Unsize
 });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+impl<'gcx> HashStable<StableHashingContext<'gcx>>
 for mir::AggregateKind<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
@@ -487,9 +487,9 @@ impl_stable_hash_for!(enum mir::NullOp {
 
 impl_stable_hash_for!(struct mir::Constant<'tcx> { span, ty, literal });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for mir::Literal<'gcx> {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Literal<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs
index 6bcbce4b69304..6821ac8529800 100644
--- a/src/librustc/ich/impls_syntax.rs
+++ b/src/librustc/ich/impls_syntax.rs
@@ -28,42 +28,42 @@ use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey,
                                            StableHasher, StableHasherResult};
 use rustc_data_structures::accumulate_vec::AccumulateVec;
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for InternedString {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for InternedString {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         let s: &str = &**self;
         s.hash_stable(hcx, hasher);
     }
 }
 
-impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>> for InternedString {
+impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for InternedString {
     type KeyType = InternedString;
 
     #[inline]
     fn to_stable_hash_key(&self,
-                          _: &StableHashingContext<'a, 'gcx, 'tcx>)
+                          _: &StableHashingContext<'gcx>)
                           -> InternedString {
         self.clone()
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ast::Name {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for ast::Name {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         self.as_str().hash_stable(hcx, hasher);
     }
 }
 
-impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>> for ast::Name {
+impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for ast::Name {
     type KeyType = InternedString;
 
     #[inline]
     fn to_stable_hash_key(&self,
-                          _: &StableHashingContext<'a, 'gcx, 'tcx>)
+                          _: &StableHashingContext<'gcx>)
                           -> InternedString {
         self.as_str()
     }
@@ -110,10 +110,10 @@ impl_stable_hash_for!(struct ::syntax::attr::Stability {
     rustc_const_unstable
 });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+impl<'gcx> HashStable<StableHashingContext<'gcx>>
 for ::syntax::attr::StabilityLevel {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
@@ -165,9 +165,9 @@ impl_stable_hash_for!(struct ::syntax::ast::Lifetime { id, span, ident });
 impl_stable_hash_for!(enum ::syntax::ast::StrStyle { Cooked, Raw(pounds) });
 impl_stable_hash_for!(enum ::syntax::ast::AttrStyle { Outer, Inner });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for [ast::Attribute] {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for [ast::Attribute] {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         if self.len() == 0 {
             self.len().hash_stable(hcx, hasher);
@@ -190,9 +190,9 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for [ast::
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ast::Attribute {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for ast::Attribute {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         // Make sure that these have been filtered out.
         debug_assert!(self.name().map(|name| !hcx.is_ignored_attr(name)).unwrap_or(true));
@@ -219,10 +219,10 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ast::A
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+impl<'gcx> HashStable<StableHashingContext<'gcx>>
 for tokenstream::TokenTree {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
@@ -241,10 +241,10 @@ for tokenstream::TokenTree {
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+impl<'gcx> HashStable<StableHashingContext<'gcx>>
 for tokenstream::TokenStream {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         for sub_tt in self.trees() {
             sub_tt.hash_stable(hcx, hasher);
@@ -252,10 +252,10 @@ for tokenstream::TokenStream {
     }
 }
 
-fn hash_token<'a, 'gcx, 'tcx, W: StableHasherResult>(token: &token::Token,
-                                               hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
-                                               hasher: &mut StableHasher<W>,
-                                               error_reporting_span: Span) {
+fn hash_token<'gcx, W: StableHasherResult>(token: &token::Token,
+                                           hcx: &mut StableHashingContext<'gcx>,
+                                           hasher: &mut StableHasher<W>,
+                                           error_reporting_span: Span) {
     mem::discriminant(token).hash_stable(hcx, hasher);
     match *token {
         token::Token::Eq |
@@ -358,9 +358,9 @@ impl_stable_hash_for!(enum ::syntax::ast::MetaItemKind {
     NameValue(lit)
 });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for FileMap {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for FileMap {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         let FileMap {
             ref name,
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index 371a9c966440a..e3ecaae953a6b 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -20,30 +20,30 @@ use middle::region;
 use traits;
 use ty;
 
-impl<'a, 'gcx, 'tcx, T> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+impl<'gcx, T> HashStable<StableHashingContext<'gcx>>
 for &'gcx ty::Slice<T>
-    where T: HashStable<StableHashingContext<'a, 'gcx, 'tcx>> {
+    where T: HashStable<StableHashingContext<'gcx>> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         (&self[..]).hash_stable(hcx, hasher);
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+impl<'gcx> HashStable<StableHashingContext<'gcx>>
 for ty::subst::Kind<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         self.as_type().hash_stable(hcx, hasher);
         self.as_region().hash_stable(hcx, hasher);
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+impl<'gcx> HashStable<StableHashingContext<'gcx>>
 for ty::RegionKind {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
@@ -81,10 +81,10 @@ for ty::RegionKind {
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+impl<'gcx> HashStable<StableHashingContext<'gcx>>
 for ty::adjustment::AutoBorrow<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
@@ -99,10 +99,10 @@ for ty::adjustment::AutoBorrow<'gcx> {
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+impl<'gcx> HashStable<StableHashingContext<'gcx>>
 for ty::adjustment::Adjust<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
@@ -134,10 +134,10 @@ impl_stable_hash_for!(enum ty::BorrowKind {
     MutBorrow
 });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+impl<'gcx> HashStable<StableHashingContext<'gcx>>
 for ty::UpvarCapture<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
@@ -161,11 +161,11 @@ impl_stable_hash_for!(struct ty::FnSig<'tcx> {
     abi
 });
 
-impl<'a, 'gcx, 'tcx, T> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ty::Binder<T>
-    where T: HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+impl<'gcx, T> HashStable<StableHashingContext<'gcx>> for ty::Binder<T>
+    where T: HashStable<StableHashingContext<'gcx>>
 {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         let ty::Binder(ref inner) = *self;
         inner.hash_stable(hcx, hasher);
@@ -185,13 +185,13 @@ impl_stable_hash_for!(struct ty::TraitPredicate<'tcx> { trait_ref });
 impl_stable_hash_for!(tuple_struct ty::EquatePredicate<'tcx> { t1, t2 });
 impl_stable_hash_for!(struct ty::SubtypePredicate<'tcx> { a_is_expected, a, b });
 
-impl<'a, 'gcx, 'tcx, A, B> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+impl<'gcx, A, B> HashStable<StableHashingContext<'gcx>>
 for ty::OutlivesPredicate<A, B>
-    where A: HashStable<StableHashingContext<'a, 'gcx, 'tcx>>,
-          B: HashStable<StableHashingContext<'a, 'gcx, 'tcx>>,
+    where A: HashStable<StableHashingContext<'gcx>>,
+          B: HashStable<StableHashingContext<'gcx>>,
 {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         let ty::OutlivesPredicate(ref a, ref b) = *self;
         a.hash_stable(hcx, hasher);
@@ -203,9 +203,9 @@ impl_stable_hash_for!(struct ty::ProjectionPredicate<'tcx> { projection_ty, ty }
 impl_stable_hash_for!(struct ty::ProjectionTy<'tcx> { substs, item_def_id });
 
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ty::Predicate<'gcx> {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::Predicate<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
@@ -245,9 +245,9 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ty::Pr
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ty::AdtFlags {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::AdtFlags {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          _: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          _: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         std_hash::Hash::hash(self, hasher);
     }
@@ -272,10 +272,10 @@ impl_stable_hash_for!(struct ty::FieldDef {
     vis
 });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+impl<'gcx> HashStable<StableHashingContext<'gcx>>
 for ::middle::const_val::ConstVal<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         use middle::const_val::ConstVal::*;
         use middle::const_val::ConstAggregate::*;
@@ -347,10 +347,10 @@ impl_stable_hash_for!(struct ::middle::const_val::ConstEvalErr<'tcx> {
     kind
 });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+impl<'gcx> HashStable<StableHashingContext<'gcx>>
 for ::middle::const_val::ErrKind<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         use middle::const_val::ErrKind::*;
 
@@ -410,9 +410,9 @@ impl_stable_hash_for!(enum ty::adjustment::CustomCoerceUnsized {
     Struct(index)
 });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ty::Generics {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::Generics {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         let ty::Generics {
             parent,
@@ -438,10 +438,10 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ty::Ge
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+impl<'gcx> HashStable<StableHashingContext<'gcx>>
 for ty::RegionParameterDef {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         let ty::RegionParameterDef {
             name,
@@ -466,12 +466,12 @@ impl_stable_hash_for!(struct ty::TypeParameterDef {
     pure_wrt_drop
 });
 
-impl<'a, 'gcx, 'tcx, T> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+impl<'gcx, T> HashStable<StableHashingContext<'gcx>>
 for ::middle::resolve_lifetime::Set1<T>
-    where T: HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+    where T: HashStable<StableHashingContext<'gcx>>
 {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         use middle::resolve_lifetime::Set1;
 
@@ -522,11 +522,11 @@ impl_stable_hash_for!(enum ::middle::region::Scope {
     Remainder(block_remainder)
 });
 
-impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>> for region::Scope {
+impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for region::Scope {
     type KeyType = region::Scope;
 
     #[inline]
-    fn to_stable_hash_key(&self, _: &StableHashingContext<'a, 'gcx, 'tcx>) -> region::Scope {
+    fn to_stable_hash_key(&self, _: &StableHashingContext<'gcx>) -> region::Scope {
         *self
     }
 }
@@ -552,11 +552,11 @@ impl_stable_hash_for!(enum ty::BoundRegion {
     BrEnv
 });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+impl<'gcx> HashStable<StableHashingContext<'gcx>>
 for ty::TypeVariants<'gcx>
 {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         use ty::TypeVariants::*;
 
@@ -648,11 +648,11 @@ impl_stable_hash_for!(struct ty::TypeAndMut<'tcx> {
     mutbl
 });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+impl<'gcx> HashStable<StableHashingContext<'gcx>>
 for ty::ExistentialPredicate<'gcx>
 {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
@@ -685,9 +685,9 @@ impl_stable_hash_for!(struct ty::Instance<'tcx> {
     substs
 });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ty::InstanceDef<'gcx> {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::InstanceDef<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
 
@@ -721,9 +721,9 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ty::In
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ty::TraitDef {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::TraitDef {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         let ty::TraitDef {
             // We already have the def_path_hash below, no need to hash it twice
@@ -751,9 +751,9 @@ impl_stable_hash_for!(struct ty::DtorckConstraint<'tcx> {
 });
 
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ty::CrateVariancesMap {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::CrateVariancesMap {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         let ty::CrateVariancesMap {
             ref dependencies,
@@ -789,12 +789,12 @@ impl_stable_hash_for!(enum ty::AssociatedItemContainer {
 });
 
 
-impl<'a, 'gcx, 'tcx, T> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+impl<'gcx, T> HashStable<StableHashingContext<'gcx>>
 for ty::steal::Steal<T>
-    where T: HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+    where T: HashStable<StableHashingContext<'gcx>>
 {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         self.borrow().hash_stable(hcx, hasher);
     }
@@ -816,10 +816,10 @@ impl_stable_hash_for!(enum ::middle::privacy::AccessLevel {
     Public
 });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+impl<'gcx> HashStable<StableHashingContext<'gcx>>
 for ::middle::privacy::AccessLevels {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
             let ::middle::privacy::AccessLevels {
diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs
index eb2b136e417d3..21dfd3267df51 100644
--- a/src/librustc/lint/levels.rs
+++ b/src/librustc/lint/levels.rs
@@ -386,10 +386,10 @@ impl LintLevelMap {
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for LintLevelMap {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for LintLevelMap {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         let LintLevelMap {
             ref sets,
diff --git a/src/librustc/macros.rs b/src/librustc/macros.rs
index f3d66b49de5a8..f0285d6a93782 100644
--- a/src/librustc/macros.rs
+++ b/src/librustc/macros.rs
@@ -73,10 +73,10 @@ macro_rules! __impl_stable_hash_field {
 #[macro_export]
 macro_rules! impl_stable_hash_for {
     (enum $enum_name:path { $( $variant:ident $( ( $($arg:ident),* ) )* ),* }) => {
-        impl<'a, 'tcx, 'lcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a, 'tcx, 'lcx>> for $enum_name {
+        impl<'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'tcx>> for $enum_name {
             #[inline]
             fn hash_stable<W: ::rustc_data_structures::stable_hasher::StableHasherResult>(&self,
-                                                  __ctx: &mut $crate::ich::StableHashingContext<'a, 'tcx, 'lcx>,
+                                                  __ctx: &mut $crate::ich::StableHashingContext<'tcx>,
                                                   __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher<W>) {
                 use $enum_name::*;
                 ::std::mem::discriminant(self).hash_stable(__ctx, __hasher);
@@ -92,10 +92,10 @@ macro_rules! impl_stable_hash_for {
         }
     };
     (struct $struct_name:path { $($field:ident),* }) => {
-        impl<'a, 'tcx, 'lcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a, 'tcx, 'lcx>> for $struct_name {
+        impl<'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'tcx>> for $struct_name {
             #[inline]
             fn hash_stable<W: ::rustc_data_structures::stable_hasher::StableHasherResult>(&self,
-                                                  __ctx: &mut $crate::ich::StableHashingContext<'a, 'tcx, 'lcx>,
+                                                  __ctx: &mut $crate::ich::StableHashingContext<'tcx>,
                                                   __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher<W>) {
                 let $struct_name {
                     $(ref $field),*
@@ -106,10 +106,10 @@ macro_rules! impl_stable_hash_for {
         }
     };
     (tuple_struct $struct_name:path { $($field:ident),* }) => {
-        impl<'a, 'tcx, 'lcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a, 'tcx, 'lcx>> for $struct_name {
+        impl<'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'tcx>> for $struct_name {
             #[inline]
             fn hash_stable<W: ::rustc_data_structures::stable_hasher::StableHasherResult>(&self,
-                                                  __ctx: &mut $crate::ich::StableHashingContext<'a, 'tcx, 'lcx>,
+                                                  __ctx: &mut $crate::ich::StableHashingContext<'tcx>,
                                                   __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher<W>) {
                 let $struct_name (
                     $(ref $field),*
@@ -125,11 +125,11 @@ macro_rules! impl_stable_hash_for {
 macro_rules! impl_stable_hash_for_spanned {
     ($T:path) => (
 
-        impl<'a, 'tcx, 'lcx> HashStable<StableHashingContext<'a, 'tcx, 'lcx>> for ::syntax::codemap::Spanned<$T>
+        impl<'tcx> HashStable<StableHashingContext<'tcx>> for ::syntax::codemap::Spanned<$T>
         {
             #[inline]
             fn hash_stable<W: StableHasherResult>(&self,
-                                                  hcx: &mut StableHashingContext<'a, 'tcx, 'lcx>,
+                                                  hcx: &mut StableHashingContext<'tcx>,
                                                   hasher: &mut StableHasher<W>) {
                 self.node.hash_stable(hcx, hasher);
                 self.span.hash_stable(hcx, hasher);
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index 5c6feddb1fdf2..5b286c6593b7a 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -1239,9 +1239,9 @@ pub fn provide(providers: &mut Providers) {
     };
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ScopeTree {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for ScopeTree {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         let ScopeTree {
             root_body,
diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs
index 73c702fedb816..efc2f647cfdf5 100644
--- a/src/librustc/mir/cache.rs
+++ b/src/librustc/mir/cache.rs
@@ -35,9 +35,9 @@ impl serialize::Decodable for Cache {
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for Cache {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for Cache {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          _: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          _: &mut StableHashingContext<'gcx>,
                                           _: &mut StableHasher<W>) {
         // do nothing
     }
diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs
index 6895e0e8a3456..0651d1904bf06 100644
--- a/src/librustc/traits/specialize/specialization_graph.rs
+++ b/src/librustc/traits/specialize/specialization_graph.rs
@@ -369,9 +369,9 @@ pub fn ancestors(tcx: TyCtxt,
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for Children {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for Children {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         let Children {
             ref nonblanket_impls,
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 61cd5db9a1948..8005714433f5e 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -687,9 +687,9 @@ impl<'tcx> TypeckTables<'tcx> {
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for TypeckTables<'gcx> {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for TypeckTables<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         let ty::TypeckTables {
             local_id_root,
@@ -1225,6 +1225,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     pub fn crate_data_as_rc_any(self, cnum: CrateNum) -> Rc<Any> {
         self.cstore.crate_data_as_rc_any(cnum)
     }
+
+    pub fn create_stable_hashing_context(self) -> StableHashingContext<'gcx> {
+        let krate = self.dep_graph.with_ignore(|| self.gcx.hir.krate());
+
+        StableHashingContext::new(self.sess,
+                                  krate,
+                                  self.hir.definitions(),
+                                  self.cstore)
+    }
 }
 
 impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs
index 86ae4bb92df07..490bfe78a9a1f 100644
--- a/src/librustc/ty/fast_reject.rs
+++ b/src/librustc/ty/fast_reject.rs
@@ -144,12 +144,12 @@ impl<D: Copy + Debug + Ord + Eq + Hash> SimplifiedTypeGen<D> {
     }
 }
 
-impl<'a, 'gcx, 'tcx, D> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for SimplifiedTypeGen<D>
+impl<'gcx, D> HashStable<StableHashingContext<'gcx>> for SimplifiedTypeGen<D>
     where D: Copy + Debug + Ord + Eq + Hash +
-             HashStable<StableHashingContext<'a, 'gcx, 'tcx>>,
+             HashStable<StableHashingContext<'gcx>>,
 {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index 1ae1e7007ac5e..1709f9ed2df1c 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -2306,10 +2306,10 @@ impl<'a, 'tcx> TyLayout<'tcx> {
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for Layout
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for Layout
 {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         use ty::layout::Layout::*;
         mem::discriminant(self).hash_stable(hcx, hasher);
@@ -2399,10 +2399,10 @@ impl_stable_hash_for!(struct ::ty::layout::Size {
     raw
 });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for LayoutError<'gcx>
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for LayoutError<'gcx>
 {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         use ty::layout::LayoutError::*;
         mem::discriminant(self).hash_stable(hcx, hasher);
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index da00f12edacb0..32d8a5114a79d 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -500,9 +500,9 @@ impl<'tcx> TyS<'tcx> {
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ty::TyS<'gcx> {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::TyS<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         let ty::TyS {
             ref sty,
@@ -1334,9 +1334,9 @@ impl<'tcx> serialize::UseSpecializedEncodable for &'tcx AdtDef {
 impl<'tcx> serialize::UseSpecializedDecodable for &'tcx AdtDef {}
 
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for AdtDef {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for AdtDef {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         let ty::AdtDef {
             did,
diff --git a/src/librustc/ty/trait_def.rs b/src/librustc/ty/trait_def.rs
index 9ae6c3516a5cf..e0b05c2ba39ac 100644
--- a/src/librustc/ty/trait_def.rs
+++ b/src/librustc/ty/trait_def.rs
@@ -186,9 +186,9 @@ pub(super) fn trait_impls_of_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     })
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for TraitImpls {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for TraitImpls {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         let TraitImpls {
             ref blanket_impls,
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 16ae3cdbf1796..27819f551b9b3 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -12,7 +12,7 @@
 
 use hir::def_id::{DefId, LOCAL_CRATE};
 use hir::map::DefPathData;
-use ich::{StableHashingContext, NodeIdHashingMode};
+use ich::NodeIdHashingMode;
 use middle::const_val::ConstVal;
 use traits::{self, Reveal};
 use ty::{self, Ty, TyCtxt, TypeFoldable};
@@ -214,7 +214,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
     /// context it's calculated within. This is used by the `type_id` intrinsic.
     pub fn type_id_hash(self, ty: Ty<'tcx>) -> u64 {
         let mut hasher = StableHasher::new();
-        let mut hcx = StableHashingContext::new(self);
+        let mut hcx = self.create_stable_hashing_context();
 
         // We want the type_id be independent of the types free regions, so we
         // erase them. The erase_regions() call will also anonymize bound
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 32a160bcffcef..d50d3deb67347 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -175,7 +175,7 @@ pub fn compile_input(sess: &Session,
         // Construct the HIR map
         let hir_map = time(sess.time_passes(),
                            "indexing hir",
-                           || hir_map::map_crate(&mut hir_forest, defs));
+                           || hir_map::map_crate(&mut hir_forest, &defs));
 
         {
             let _ignore = hir_map.dep_graph.in_ignore();
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index 34f4e0e7b0c95..daabf481e461f 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -133,7 +133,7 @@ fn test_env<F>(source_string: &str,
 
     let arena = DroplessArena::new();
     let arenas = ty::GlobalArenas::new();
-    let hir_map = hir_map::map_crate(&mut hir_forest, defs);
+    let hir_map = hir_map::map_crate(&mut hir_forest, &defs);
 
     // run just enough stuff to build a tcx:
     let named_region_map = resolve_lifetime::krate(&sess, &*cstore, &hir_map);
diff --git a/src/librustc_incremental/calculate_svh/mod.rs b/src/librustc_incremental/calculate_svh/mod.rs
index 60e1f238f44a4..0329aa8d6741b 100644
--- a/src/librustc_incremental/calculate_svh/mod.rs
+++ b/src/librustc_incremental/calculate_svh/mod.rs
@@ -91,7 +91,7 @@ impl<'a> ::std::ops::Index<&'a DepNode> for IncrementalHashesMap {
 
 struct ComputeItemHashesVisitor<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    hcx: StableHashingContext<'a, 'tcx, 'tcx>,
+    hcx: StableHashingContext<'tcx>,
     hashes: IncrementalHashesMap,
 }
 
@@ -100,7 +100,7 @@ impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> {
                                               def_index: DefIndex,
                                               hash_bodies: bool,
                                               item_like: T)
-        where T: HashStable<StableHashingContext<'a, 'tcx, 'tcx>>
+        where T: HashStable<StableHashingContext<'tcx>>
     {
         if !hash_bodies && !self.tcx.sess.opts.build_dep_graph() {
             // If we just need the hashes in order to compute the SVH, we don't
@@ -303,7 +303,7 @@ pub fn compute_incremental_hashes_map<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
 
     let mut visitor = ComputeItemHashesVisitor {
         tcx,
-        hcx: StableHashingContext::new(tcx),
+        hcx: tcx.create_stable_hashing_context(),
         hashes: IncrementalHashesMap::new(),
     };
 
diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs
index 3bc281e5486a8..d9ab2562efff2 100644
--- a/src/librustc_metadata/astencode.rs
+++ b/src/librustc_metadata/astencode.rs
@@ -16,7 +16,7 @@ use schema::*;
 use rustc::hir;
 use rustc::ty::{self, TyCtxt};
 
-use rustc::ich::{StableHashingContext, Fingerprint};
+use rustc::ich::Fingerprint;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 
 #[derive(RustcEncodable, RustcDecodable)]
@@ -43,7 +43,7 @@ impl<'a, 'b, 'tcx> IsolatedEncoder<'a, 'b, 'tcx> {
         // In order to avoid having to hash hir::Bodies from extern crates, we
         // hash them here, during export, and store the hash with metadata.
         let stable_bodies_hash = {
-            let mut hcx = StableHashingContext::new(self.tcx);
+            let mut hcx = self.tcx.create_stable_hashing_context();
             let mut hasher = StableHasher::new();
 
             hcx.while_hashing_hir_bodies(true, |hcx| {
diff --git a/src/librustc_metadata/isolated_encoder.rs b/src/librustc_metadata/isolated_encoder.rs
index b9ad9086c039a..7dc50fe29df07 100644
--- a/src/librustc_metadata/isolated_encoder.rs
+++ b/src/librustc_metadata/isolated_encoder.rs
@@ -23,7 +23,7 @@ use rustc_serialize::Encodable;
 pub struct IsolatedEncoder<'a, 'b: 'a, 'tcx: 'b> {
     pub tcx: TyCtxt<'b, 'tcx, 'tcx>,
     ecx: &'a mut EncodeContext<'b, 'tcx>,
-    hcx: Option<(StableHashingContext<'b, 'tcx, 'tcx>, StableHasher<Fingerprint>)>,
+    hcx: Option<(StableHashingContext<'tcx>, StableHasher<Fingerprint>)>,
 }
 
 impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
@@ -40,9 +40,9 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
                 // Except when -Zquery-dep-graph is specified because we don't
                 // want to mess up our tests.
                 let hcx = if tcx.sess.opts.debugging_opts.query_dep_graph {
-                    StableHashingContext::new(tcx)
+                    tcx.create_stable_hashing_context()
                 } else {
-                    StableHashingContext::new(tcx).force_span_hashing()
+                    tcx.create_stable_hashing_context().force_span_hashing()
                 };
 
                 Some((hcx, StableHasher::new()))
@@ -61,7 +61,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
     }
 
     pub fn lazy<T>(&mut self, value: &T) -> Lazy<T>
-        where T: Encodable + HashStable<StableHashingContext<'b, 'tcx, 'tcx>>
+        where T: Encodable + HashStable<StableHashingContext<'tcx>>
     {
         if let Some((ref mut hcx, ref mut hasher)) = self.hcx {
             value.hash_stable(hcx, hasher);
@@ -72,7 +72,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
 
     pub fn lazy_seq<I, T>(&mut self, iter: I) -> LazySeq<T>
         where I: IntoIterator<Item = T>,
-              T: Encodable + HashStable<StableHashingContext<'b, 'tcx, 'tcx>>
+              T: Encodable + HashStable<StableHashingContext<'tcx>>
     {
         if let Some((ref mut hcx, ref mut hasher)) = self.hcx {
             let iter = iter.into_iter();
@@ -111,7 +111,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
 
     pub fn lazy_seq_ref<'x, I, T>(&mut self, iter: I) -> LazySeq<T>
         where I: IntoIterator<Item = &'x T>,
-              T: 'x + Encodable + HashStable<StableHashingContext<'b, 'tcx, 'tcx>>
+              T: 'x + Encodable + HashStable<StableHashingContext<'tcx>>
     {
         if let Some((ref mut hcx, ref mut hasher)) = self.hcx {
             let iter = iter.into_iter();
@@ -149,7 +149,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
     }
 
     pub fn lazy_seq_from_slice<T>(&mut self, slice: &[T]) -> LazySeq<T>
-        where T: Encodable + HashStable<StableHashingContext<'b, 'tcx, 'tcx>>
+        where T: Encodable + HashStable<StableHashingContext<'tcx>>
     {
         if let Some((ref mut hcx, ref mut hasher)) = self.hcx {
             slice.hash_stable(hcx, hasher);
@@ -159,7 +159,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
     }
 
     pub fn lazy_seq_ref_from_slice<T>(&mut self, slice: &[&T]) -> LazySeq<T>
-        where T: Encodable + HashStable<StableHashingContext<'b, 'tcx, 'tcx>>
+        where T: Encodable + HashStable<StableHashingContext<'tcx>>
     {
         if let Some((ref mut hcx, ref mut hasher)) = self.hcx {
             slice.hash_stable(hcx, hasher);
diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs
index ee196d74bb814..dad0d26d2715d 100644
--- a/src/librustc_metadata/schema.rs
+++ b/src/librustc_metadata/schema.rs
@@ -229,9 +229,9 @@ pub struct TraitImpls {
     pub impls: LazySeq<DefIndex>,
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for TraitImpls {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for TraitImpls {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         let TraitImpls {
             trait_id: (krate, def_index),
@@ -312,9 +312,9 @@ pub enum EntryKind<'tcx> {
     AssociatedConst(AssociatedContainer, u8),
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for EntryKind<'tcx> {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for EntryKind<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs
index 40fc07cfd4f62..7e75eb9c78bab 100644
--- a/src/librustc_trans/context.rs
+++ b/src/librustc_trans/context.rs
@@ -141,10 +141,10 @@ impl<'a, 'tcx> DepGraphSafe for SharedCrateContext<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> StableHashingContextProvider for SharedCrateContext<'a, 'tcx> {
-    type ContextType = StableHashingContext<'a, 'tcx, 'tcx>;
+    type ContextType = StableHashingContext<'tcx>;
 
     fn create_stable_hashing_context(&self) -> Self::ContextType {
-        StableHashingContext::new(self.tcx)
+        self.tcx.create_stable_hashing_context()
     }
 }
 
diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs
index 4918dd78b3793..29da763f334c7 100644
--- a/src/librustc_typeck/variance/constraints.rs
+++ b/src/librustc_typeck/variance/constraints.rs
@@ -141,10 +141,10 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> StableHashingContextProvider for ConstraintContext<'a, 'tcx> {
-    type ContextType = StableHashingContext<'a, 'tcx, 'tcx>;
+    type ContextType = StableHashingContext<'tcx>;
 
     fn create_stable_hashing_context(&self) -> Self::ContextType {
-         StableHashingContext::new(self.terms_cx.tcx)
+         self.terms_cx.tcx.create_stable_hashing_context()
     }
 }
 
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 277e2909ba9ed..1663e5ad14286 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -175,7 +175,7 @@ pub fn run_core(search_paths: SearchPaths,
 
     let arena = DroplessArena::new();
     let arenas = GlobalArenas::new();
-    let hir_map = hir_map::map_crate(&mut hir_forest, defs);
+    let hir_map = hir_map::map_crate(&mut hir_forest, &defs);
     let output_filenames = driver::build_output_filenames(&input,
                                                           &None,
                                                           &None,
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 95c0f5f5d6364..36efc37a8095c 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -124,7 +124,7 @@ pub fn run(input: &str,
                                        render_type);
 
     {
-        let map = hir::map::map_crate(&mut hir_forest, defs);
+        let map = hir::map::map_crate(&mut hir_forest, &defs);
         let krate = map.krate();
         let mut hir_collector = HirCollector {
             sess: &sess,

From 74d6b850fd731597fe2f03408a0397a972c13641 Mon Sep 17 00:00:00 2001
From: Michael Woerister <michaelwoerister@posteo>
Date: Mon, 18 Sep 2017 12:14:52 +0200
Subject: [PATCH 22/24] incr.comp.: Fix rebase fallout.

---
 src/librustc/ich/hcx.rs                       |  4 +-
 .../error_reporting/different_lifetimes.rs    | 12 +--
 src/librustc/middle/exported_symbols.rs       |  5 ++
 src/librustc/middle/trans.rs                  | 79 +++++++++++++++++++
 src/librustc/session/config.rs                | 33 ++++++++
 src/librustc_data_structures/stable_hasher.rs |  8 ++
 src/librustc_trans/base.rs                    | 25 ++----
 src/librustc_trans/context.rs                 |  3 +-
 8 files changed, 138 insertions(+), 31 deletions(-)

diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs
index 0a2566f069249..64fc63002da1f 100644
--- a/src/librustc/ich/hcx.rs
+++ b/src/librustc/ich/hcx.rs
@@ -15,7 +15,7 @@ use hir::map::definitions::Definitions;
 use ich::{self, CachingCodemapView};
 use middle::cstore::CrateStore;
 use session::config::DebugInfoLevel::NoDebugInfo;
-use ty::{self, TyCtxt, fast_reject};
+use ty::{TyCtxt, fast_reject};
 use session::Session;
 
 use std::cmp::Ord;
@@ -252,7 +252,7 @@ impl<'gcx> StableHashingContext<'gcx> {
     }
 }
 
-impl<'a, 'gcx, 'lcx> StableHashingContextProvider for ty::TyCtxt<'a, 'gcx, 'lcx> {
+impl<'a, 'gcx, 'lcx> StableHashingContextProvider for TyCtxt<'a, 'gcx, 'lcx> {
     type ContextType = StableHashingContext<'gcx>;
     fn create_stable_hashing_context(&self) -> Self::ContextType {
         (*self).create_stable_hashing_context()
diff --git a/src/librustc/infer/error_reporting/different_lifetimes.rs b/src/librustc/infer/error_reporting/different_lifetimes.rs
index ef28b5b42b0dd..6c57130a9955f 100644
--- a/src/librustc/infer/error_reporting/different_lifetimes.rs
+++ b/src/librustc/infer/error_reporting/different_lifetimes.rs
@@ -332,10 +332,8 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for TyPathVisitor<'a, 'gcx, 'tcx> {
 
             (Some(rl::Region::EarlyBound(_, id)), ty::BrNamed(def_id, _)) => {
                 debug!("EarlyBound self.infcx.tcx.hir.local_def_id(id)={:?} \
-                                        def_id={:?}",
-                       self.infcx.tcx.hir.local_def_id(id),
-                       def_id);
-                if self.infcx.tcx.hir.local_def_id(id) == def_id {
+                                        def_id={:?}", id, def_id);
+                if id == def_id {
                     self.found_it = true;
                     return; // we can stop visiting now
                 }
@@ -344,11 +342,9 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for TyPathVisitor<'a, 'gcx, 'tcx> {
             (Some(rl::Region::LateBound(debruijn_index, id)), ty::BrNamed(def_id, _)) => {
                 debug!("FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}",
                        debruijn_index.depth);
-                debug!("self.infcx.tcx.hir.local_def_id(id)={:?}",
-                       self.infcx.tcx.hir.local_def_id(id));
+                debug!("id={:?}", id);
                 debug!("def_id={:?}", def_id);
-                if debruijn_index.depth == self.depth &&
-                   self.infcx.tcx.hir.local_def_id(id) == def_id {
+                if debruijn_index.depth == self.depth && id == def_id {
                     self.found_it = true;
                     return; // we can stop visiting now
                 }
diff --git a/src/librustc/middle/exported_symbols.rs b/src/librustc/middle/exported_symbols.rs
index 230878f854595..d650dbe88b5c8 100644
--- a/src/librustc/middle/exported_symbols.rs
+++ b/src/librustc/middle/exported_symbols.rs
@@ -19,6 +19,11 @@ pub enum SymbolExportLevel {
     Rust,
 }
 
+impl_stable_hash_for!(enum self::SymbolExportLevel {
+    C,
+    Rust
+});
+
 impl SymbolExportLevel {
     pub fn is_below_threshold(self, threshold: SymbolExportLevel) -> bool {
         if threshold == SymbolExportLevel::Rust {
diff --git a/src/librustc/middle/trans.rs b/src/librustc/middle/trans.rs
index 9a50125754846..7744c9c3d1238 100644
--- a/src/librustc/middle/trans.rs
+++ b/src/librustc/middle/trans.rs
@@ -12,6 +12,9 @@ use syntax::ast::NodeId;
 use syntax::symbol::InternedString;
 use ty::Instance;
 use util::nodemap::FxHashMap;
+use rustc_data_structures::stable_hasher::{HashStable, StableHasherResult,
+                                           StableHasher};
+use ich::{Fingerprint, StableHashingContext, NodeIdHashingMode};
 
 #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
 pub enum TransItem<'tcx> {
@@ -20,6 +23,26 @@ pub enum TransItem<'tcx> {
     GlobalAsm(NodeId),
 }
 
+impl<'tcx> HashStable<StableHashingContext<'tcx>> for TransItem<'tcx> {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                           hcx: &mut StableHashingContext<'tcx>,
+                                           hasher: &mut StableHasher<W>) {
+        ::std::mem::discriminant(self).hash_stable(hcx, hasher);
+
+        match *self {
+            TransItem::Fn(ref instance) => {
+                instance.hash_stable(hcx, hasher);
+            }
+            TransItem::Static(node_id)    |
+            TransItem::GlobalAsm(node_id) => {
+                hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
+                    node_id.hash_stable(hcx, hasher);
+                })
+            }
+        }
+    }
+}
+
 pub struct CodegenUnit<'tcx> {
     /// A name for this CGU. Incremental compilation requires that
     /// name be unique amongst **all** crates.  Therefore, it should
@@ -44,6 +67,20 @@ pub enum Linkage {
     Common,
 }
 
+impl_stable_hash_for!(enum self::Linkage {
+    External,
+    AvailableExternally,
+    LinkOnceAny,
+    LinkOnceODR,
+    WeakAny,
+    WeakODR,
+    Appending,
+    Internal,
+    Private,
+    ExternalWeak,
+    Common
+});
+
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 pub enum Visibility {
     Default,
@@ -51,6 +88,12 @@ pub enum Visibility {
     Protected,
 }
 
+impl_stable_hash_for!(enum self::Visibility {
+    Default,
+    Hidden,
+    Protected
+});
+
 impl<'tcx> CodegenUnit<'tcx> {
     pub fn new(name: InternedString) -> CodegenUnit<'tcx> {
         CodegenUnit {
@@ -78,6 +121,29 @@ impl<'tcx> CodegenUnit<'tcx> {
     }
 }
 
+impl<'tcx> HashStable<StableHashingContext<'tcx>> for CodegenUnit<'tcx> {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                           hcx: &mut StableHashingContext<'tcx>,
+                                           hasher: &mut StableHasher<W>) {
+        let CodegenUnit {
+            ref items,
+            name,
+        } = *self;
+
+        name.hash_stable(hcx, hasher);
+
+        let mut items: Vec<(Fingerprint, _)> = items.iter().map(|(trans_item, &attrs)| {
+            let mut hasher = StableHasher::new();
+            trans_item.hash_stable(hcx, &mut hasher);
+            let trans_item_fingerprint = hasher.finish();
+            (trans_item_fingerprint, attrs)
+        }).collect();
+
+        items.sort_unstable_by_key(|i| i.0);
+        items.hash_stable(hcx, hasher);
+    }
+}
+
 #[derive(Clone, Default)]
 pub struct Stats {
     pub n_glues_created: usize,
@@ -92,6 +158,18 @@ pub struct Stats {
     pub fn_stats: Vec<(String, usize)>,
 }
 
+impl_stable_hash_for!(struct self::Stats {
+    n_glues_created,
+    n_null_glues,
+    n_real_glues,
+    n_fns,
+    n_inlines,
+    n_closures,
+    n_llvm_insns,
+    llvm_insns,
+    fn_stats
+});
+
 impl Stats {
     pub fn extend(&mut self, stats: Stats) {
         self.n_glues_created += stats.n_glues_created;
@@ -108,3 +186,4 @@ impl Stats {
         self.fn_stats.extend(stats.fn_stats);
     }
 }
+
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index df2de17f1e471..f079d7d43389a 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -19,8 +19,10 @@ pub use self::DebugInfoLevel::*;
 use session::{early_error, early_warn, Session};
 use session::search_paths::SearchPaths;
 
+use ich::StableHashingContext;
 use rustc_back::{LinkerFlavor, PanicStrategy, RelroLevel};
 use rustc_back::target::Target;
+use rustc_data_structures::stable_hasher::ToStableHashKey;
 use lint;
 use middle::cstore;
 
@@ -90,6 +92,25 @@ pub enum OutputType {
     DepInfo,
 }
 
+impl_stable_hash_for!(enum self::OutputType {
+    Bitcode,
+    Assembly,
+    LlvmAssembly,
+    Mir,
+    Metadata,
+    Object,
+    Exe,
+    DepInfo
+});
+
+impl<'tcx> ToStableHashKey<StableHashingContext<'tcx>> for OutputType {
+    type KeyType = OutputType;
+    #[inline]
+    fn to_stable_hash_key(&self, _: &StableHashingContext<'tcx>) -> Self::KeyType {
+        *self
+    }
+}
+
 impl OutputType {
     fn is_compatible_with_codegen_units_and_single_output_file(&self) -> bool {
         match *self {
@@ -149,6 +170,10 @@ impl Default for ErrorOutputType {
 #[derive(Clone, Hash)]
 pub struct OutputTypes(BTreeMap<OutputType, Option<PathBuf>>);
 
+impl_stable_hash_for!(tuple_struct self::OutputTypes {
+    map
+});
+
 impl OutputTypes {
     pub fn new(entries: &[(OutputType, Option<PathBuf>)]) -> OutputTypes {
         OutputTypes(BTreeMap::from_iter(entries.iter()
@@ -373,6 +398,14 @@ pub struct OutputFilenames {
     pub outputs: OutputTypes,
 }
 
+impl_stable_hash_for!(struct self::OutputFilenames {
+    out_directory,
+    out_filestem,
+    single_output_file,
+    extra,
+    outputs
+});
+
 /// Codegen unit names generated by the numbered naming scheme will contain this
 /// marker right before the index of the codegen unit.
 pub const NUMBERED_CODEGEN_UNIT_MARKER: &'static str = ".cgu-";
diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs
index e18c1969a91cc..f6b23af2f7374 100644
--- a/src/librustc_data_structures/stable_hasher.rs
+++ b/src/librustc_data_structures/stable_hasher.rs
@@ -386,6 +386,14 @@ impl<CTX> HashStable<CTX> for String {
     }
 }
 
+impl<HCX> ToStableHashKey<HCX> for String {
+    type KeyType = String;
+    #[inline]
+    fn to_stable_hash_key(&self, _: &HCX) -> Self::KeyType {
+        self.clone()
+    }
+}
+
 impl<CTX> HashStable<CTX> for bool {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index 1e1b9929f0e37..ba15f3522ac1f 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -41,7 +41,6 @@ use rustc::middle::trans::{Linkage, Visibility, Stats};
 use rustc::middle::cstore::{EncodedMetadata, EncodedMetadataHashes};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::maps::Providers;
-use rustc::dep_graph::AssertDepGraphSafe;
 use rustc::middle::cstore::{self, LinkMeta, LinkagePreference};
 use rustc::hir::map as hir_map;
 use rustc::util::common::{time, print_time_passes_entry};
@@ -894,7 +893,7 @@ fn iter_globals(llmod: llvm::ModuleRef) -> ValueIter {
 /// This list is later used by linkers to determine the set of symbols needed to
 /// be exposed from a dynamic library and it's also encoded into the metadata.
 pub fn find_exported_symbols(tcx: TyCtxt) -> NodeSet {
-    tcx.reachable_set(LOCAL_CRATE).iter().cloned().filter(|&id| {
+    tcx.reachable_set(LOCAL_CRATE).0.iter().cloned().filter(|&id| {
         // Next, we want to ignore some FFI functions that are not exposed from
         // this crate. Reachable FFI functions can be lumped into two
         // categories:
@@ -1370,8 +1369,8 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let dep_node = cgu.work_product_dep_node();
     let ((stats, module), _) =
         tcx.dep_graph.with_task(dep_node,
-                                AssertDepGraphSafe(tcx),
-                                AssertDepGraphSafe(cgu),
+                                tcx,
+                                cgu,
                                 module_translation);
     let time_to_translate = start_time.elapsed();
 
@@ -1392,14 +1391,10 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     return stats;
 
     fn module_translation<'a, 'tcx>(
-        tcx: AssertDepGraphSafe<TyCtxt<'a, 'tcx, 'tcx>>,
-        args: AssertDepGraphSafe<Arc<CodegenUnit<'tcx>>>)
+        tcx: TyCtxt<'a, 'tcx, 'tcx>,
+        cgu: Arc<CodegenUnit<'tcx>>)
         -> (Stats, ModuleTranslation)
     {
-        // FIXME(#40304): We ought to be using the id as a key and some queries, I think.
-        let AssertDepGraphSafe(tcx) = tcx;
-        let AssertDepGraphSafe(cgu) = args;
-
         let cgu_name = cgu.name().to_string();
         let cgu_id = cgu.work_product_id();
         let symbol_name_hash = cgu.compute_symbol_name_hash(tcx);
@@ -1564,6 +1559,7 @@ pub fn visibility_to_llvm(linkage: Visibility) -> llvm::Visibility {
         Visibility::Default => llvm::Visibility::Default,
         Visibility::Hidden => llvm::Visibility::Hidden,
         Visibility::Protected => llvm::Visibility::Protected,
+    }
 }
 
 // FIXME(mw): Anything that is produced via DepGraph::with_task() must implement
@@ -1577,17 +1573,8 @@ pub fn visibility_to_llvm(linkage: Visibility) -> llvm::Visibility {
 mod temp_stable_hash_impls {
     use rustc_data_structures::stable_hasher::{StableHasherResult, StableHasher,
                                                HashStable};
-    use context::Stats;
     use ModuleTranslation;
 
-    impl<HCX> HashStable<HCX> for Stats {
-        fn hash_stable<W: StableHasherResult>(&self,
-                                              _: &mut HCX,
-                                              _: &mut StableHasher<W>) {
-            // do nothing
-        }
-    }
-
     impl<HCX> HashStable<HCX> for ModuleTranslation {
         fn hash_stable<W: StableHasherResult>(&self,
                                               _: &mut HCX,
diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs
index 7e75eb9c78bab..b394911c9234d 100644
--- a/src/librustc_trans/context.rs
+++ b/src/librustc_trans/context.rs
@@ -27,9 +27,8 @@ use type_::Type;
 use rustc_data_structures::base_n;
 use rustc::middle::trans::Stats;
 use rustc_data_structures::stable_hasher::StableHashingContextProvider;
-use rustc::session::config::{self, NoDebugInfo, OutputFilenames};
-use rustc::session::Session;
 use rustc::session::config::{self, NoDebugInfo};
+use rustc::session::Session;
 use rustc::ty::layout::{LayoutCx, LayoutError, LayoutTyper, TyLayout};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::util::nodemap::FxHashMap;

From 4961a8e2bd8a6d2144ee90b4ec568a1c5b7a3241 Mon Sep 17 00:00:00 2001
From: Michael Woerister <michaelwoerister@posteo>
Date: Mon, 18 Sep 2017 13:14:38 +0200
Subject: [PATCH 23/24] incr.comp.: Fix ICE caused by trying to hash
 INVALID_CRATE_NUM.

---
 src/librustc/ty/maps.rs                  |  2 +-
 src/librustc_trans/back/symbol_export.rs | 33 +++++++++++-------------
 2 files changed, 16 insertions(+), 19 deletions(-)

diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs
index 5207aaa0c5b2f..c0045483ced47 100644
--- a/src/librustc/ty/maps.rs
+++ b/src/librustc/ty/maps.rs
@@ -1417,7 +1417,7 @@ define_maps! { <'tcx>
     [] fn all_crate_nums: all_crate_nums_node(CrateNum) -> Rc<Vec<CrateNum>>,
 
     [] fn exported_symbols: ExportedSymbols(CrateNum)
-        -> Arc<Vec<(String, DefId, SymbolExportLevel)>>,
+        -> Arc<Vec<(String, Option<DefId>, SymbolExportLevel)>>,
     [] fn collect_and_partition_translation_items:
         collect_and_partition_translation_items_node(CrateNum)
         -> (Arc<DefIdSet>, Arc<Vec<Arc<CodegenUnit<'tcx>>>>),
diff --git a/src/librustc_trans/back/symbol_export.rs b/src/librustc_trans/back/symbol_export.rs
index 844442edbc872..e1f97e2c923db 100644
--- a/src/librustc_trans/back/symbol_export.rs
+++ b/src/librustc_trans/back/symbol_export.rs
@@ -14,7 +14,7 @@ use std::sync::Arc;
 use base;
 use monomorphize::Instance;
 use rustc::hir::def_id::CrateNum;
-use rustc::hir::def_id::{DefId, LOCAL_CRATE, INVALID_CRATE, CRATE_DEF_INDEX};
+use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::middle::exported_symbols::SymbolExportLevel;
 use rustc::session::config;
 use rustc::ty::TyCtxt;
@@ -24,7 +24,7 @@ use rustc_allocator::ALLOCATOR_METHODS;
 
 pub type ExportedSymbols = FxHashMap<
     CrateNum,
-    Arc<Vec<(String, DefId, SymbolExportLevel)>>,
+    Arc<Vec<(String, Option<DefId>, SymbolExportLevel)>>,
 >;
 
 pub fn threshold(tcx: TyCtxt) -> SymbolExportLevel {
@@ -65,11 +65,13 @@ pub fn provide_local(providers: &mut Providers) {
         Rc::new(tcx.exported_symbols(cnum)
             .iter()
             .filter_map(|&(_, id, level)| {
-                if level.is_below_threshold(export_threshold) {
-                    Some(id)
-                } else {
-                    None
-                }
+                id.and_then(|id| {
+                    if level.is_below_threshold(export_threshold) {
+                        Some(id)
+                    } else {
+                        None
+                    }
+                })
             })
             .collect())
     };
@@ -95,25 +97,20 @@ pub fn provide_local(providers: &mut Providers) {
                 let name = tcx.symbol_name(Instance::mono(tcx, def_id));
                 let export_level = export_level(tcx, def_id);
                 debug!("EXPORTED SYMBOL (local): {} ({:?})", name, export_level);
-                (str::to_owned(&name), def_id, export_level)
+                (str::to_owned(&name), Some(def_id), export_level)
             })
             .collect();
 
-        const INVALID_DEF_ID: DefId = DefId {
-            krate: INVALID_CRATE,
-            index: CRATE_DEF_INDEX,
-        };
-
         if let Some(_) = *tcx.sess.entry_fn.borrow() {
             local_crate.push(("main".to_string(),
-                              INVALID_DEF_ID,
+                              None,
                               SymbolExportLevel::C));
         }
 
         if tcx.sess.allocator_kind.get().is_some() {
             for method in ALLOCATOR_METHODS {
                 local_crate.push((format!("__rust_{}", method.name),
-                                  INVALID_DEF_ID,
+                                  None,
                                   SymbolExportLevel::Rust));
             }
         }
@@ -123,12 +120,12 @@ pub fn provide_local(providers: &mut Providers) {
             let idx = def_id.index;
             let disambiguator = tcx.sess.local_crate_disambiguator();
             let registrar = tcx.sess.generate_derive_registrar_symbol(disambiguator, idx);
-            local_crate.push((registrar, def_id, SymbolExportLevel::C));
+            local_crate.push((registrar, Some(def_id), SymbolExportLevel::C));
         }
 
         if tcx.sess.crate_types.borrow().contains(&config::CrateTypeDylib) {
             local_crate.push((metadata_symbol_name(tcx),
-                              INVALID_DEF_ID,
+                              None,
                               SymbolExportLevel::Rust));
         }
         Arc::new(local_crate)
@@ -178,7 +175,7 @@ pub fn provide_extern(providers: &mut Providers) {
                     export_level(tcx, def_id)
                 };
                 debug!("EXPORTED SYMBOL (re-export): {} ({:?})", name, export_level);
-                (str::to_owned(&name), def_id, export_level)
+                (str::to_owned(&name), Some(def_id), export_level)
             })
             .collect();
 

From 90ce24ab699bc44ab2474fa6bf22fde5ead180e9 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Mon, 18 Sep 2017 12:51:48 +0200
Subject: [PATCH 24/24] Fix run button

---
 src/librustdoc/html/static/rustdoc.css | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index c15051376bf27..b1aac2da1c2f7 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -817,6 +817,7 @@ span.since {
 	position: absolute;
 	left: -1px;
 	margin-top: 7px;
+	z-index: 1;
 }
 
 .tooltip {
@@ -853,3 +854,7 @@ span.since {
 	border-style: solid;
 	border-color: transparent black transparent transparent;
 }
+
+pre.rust {
+	position: relative;
+}