Rollup merge of #64486 - matthewjasper:hygiene-debugging, r=petrochenkov

Print out more information for `-Zunpretty=expanded,hygiene`

I've found this helpful when trying to understand how hygiene works.

Closes #16420
diff --git a/Cargo.lock b/Cargo.lock
index 679a024..326f3b1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -232,9 +232,9 @@
 
 [[package]]
 name = "byteorder"
-version = "1.2.7"
+version = "1.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d"
+checksum = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
 
 [[package]]
 name = "bytes"
@@ -2065,7 +2065,7 @@
  "hex",
  "log",
  "num-traits",
- "rand 0.6.1",
+ "rand 0.7.0",
  "rustc-workspace-hack",
  "rustc_version",
  "shell-escape",
@@ -2180,9 +2180,9 @@
 
 [[package]]
 name = "openssl-src"
-version = "111.3.0+1.1.1c"
+version = "111.6.0+1.1.1d"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53ed5f31d294bdf5f7a4ba0a206c2754b0f60e9a63b7e3076babc5317873c797"
+checksum = "b9c2da1de8a7a3f860919c01540b03a6db16de042405a8a07a5e9d0b4b825d9c"
 dependencies = [
  "cc",
 ]
@@ -3017,7 +3017,7 @@
  "log",
  "measureme",
  "num_cpus",
- "parking_lot 0.7.1",
+ "parking_lot 0.9.0",
  "polonius-engine",
  "rustc-rayon",
  "rustc-rayon-core",
@@ -3253,7 +3253,6 @@
 name = "rustc-workspace-hack"
 version = "1.0.0"
 dependencies = [
- "byteorder",
  "crossbeam-utils 0.6.5",
  "serde",
  "serde_json",
@@ -3311,7 +3310,7 @@
  "log",
  "memmap",
  "num_cpus",
- "parking_lot 0.7.1",
+ "parking_lot 0.9.0",
  "rustc",
  "rustc_apfloat",
  "rustc_codegen_utils",
@@ -3354,7 +3353,7 @@
  "jobserver",
  "lazy_static 1.3.0",
  "log",
- "parking_lot 0.7.1",
+ "parking_lot 0.9.0",
  "rustc-hash",
  "rustc-rayon",
  "rustc-rayon-core",
@@ -4261,13 +4260,13 @@
 
 [[package]]
 name = "tempfile"
-version = "3.0.5"
+version = "3.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e91405c14320e5c79b3d148e1c86f40749a36e490642202a31689cb1a3452b2"
+checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
 dependencies = [
  "cfg-if",
  "libc",
- "rand 0.6.1",
+ "rand 0.7.0",
  "redox_syscall",
  "remove_dir_all",
  "winapi 0.3.6",
diff --git a/RELEASES.md b/RELEASES.md
index f26f6e6..d634feb 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,108 @@
+Version 1.38.0 (2019-09-26)
+==========================
+
+Language
+--------
+- [The `#[global_allocator]` attribute can now be used in submodules.][62735]
+- [The `#[deprecated]` attribute can now be used on macros.][62042]
+
+Compiler
+--------
+- [Added pipelined compilation support to `rustc`.][62766] This will
+  improve compilation times in some cases. For further information please refer
+  to the [_"Evaluating pipelined rustc compilation"_][pipeline-internals] thread.
+- [Added tier 3\* support for the `aarch64-uwp-windows-msvc`, `i686-uwp-windows-gnu`,
+  `i686-uwp-windows-msvc`, `x86_64-uwp-windows-gnu`, and
+  `x86_64-uwp-windows-msvc` targets.][60260]
+- [Added tier 3 support for the `armv7-unknown-linux-gnueabi` and
+  `armv7-unknown-linux-musleabi` targets.][63107]
+- [Added tier 3 support for the `hexagon-unknown-linux-musl` target.][62814]
+- [Added tier 3 support for the `riscv32i-unknown-none-elf` target.][62784]
+
+\* Refer to Rust's [platform support page][forge-platform-support] for more
+information on Rust's tiered platform support.
+
+Libraries
+---------
+- [`ascii::EscapeDefault` now implements `Clone` and `Display`.][63421]
+- [Derive macros for prelude traits (e.g. `Clone`, `Debug`, `Hash`) are now
+  available at the same path as the trait.][63056] (e.g. The `Clone` derive macro
+  is available at `std::clone::Clone`). This also makes all built-in macros
+  available in `std`/`core` root. e.g. `std::include_bytes!`.
+- [`str::Chars` now implements `Debug`.][63000]
+- [`slice::{concat, connect, join}` now accepts `&[T]` in addition to `&T`.][62528]
+- [`*const T` and `*mut T` now implement `marker::Unpin`.][62583]
+- [`Arc<[T]>` and `Rc<[T]>` now implement `FromIterator<T>`.][61953]
+- [Added euclidean remainder and division operations (`div_euclid`,
+  `rem_euclid`) to all numeric primitives.][61884] Additionally `checked`,
+  `overflowing`, and `wrapping` versions are available for all
+  integer primitives.
+- [`thread::AccessError` now implements `Clone`, `Copy`, `Eq`, `Error`, and
+  `PartialEq`.][61491]
+- [`iter::{StepBy, Peekable, Take}` now implement `DoubleEndedIterator`.][61457]
+
+Stabilized APIs
+---------------
+- [`<*const T>::cast`]
+- [`<*mut T>::cast`]
+- [`Duration::as_secs_f32`]
+- [`Duration::as_secs_f64`]
+- [`Duration::div_duration_f32`]
+- [`Duration::div_duration_f64`]
+- [`Duration::div_f32`]
+- [`Duration::div_f64`]
+- [`Duration::from_secs_f32`]
+- [`Duration::from_secs_f64`]
+- [`Duration::mul_f32`]
+- [`Duration::mul_f64`]
+- [`any::type_name`]
+
+Cargo
+-----
+- [Added pipelined compilation support to `cargo`.][cargo/7143]
+- [You can now pass the `--features` option multiple times to enable
+  multiple features.][cargo/7084]
+
+Misc
+----
+- [`rustc` will now warn about some incorrect uses of
+  `mem::{uninitialized, zeroed}` that are known to cause undefined behaviour.][63346]
+
+[60260]: https://github.com/rust-lang/rust/pull/60260/
+[61457]: https://github.com/rust-lang/rust/pull/61457/
+[61491]: https://github.com/rust-lang/rust/pull/61491/
+[61884]: https://github.com/rust-lang/rust/pull/61884/
+[61953]: https://github.com/rust-lang/rust/pull/61953/
+[62042]: https://github.com/rust-lang/rust/pull/62042/
+[62528]: https://github.com/rust-lang/rust/pull/62528/
+[62583]: https://github.com/rust-lang/rust/pull/62583/
+[62735]: https://github.com/rust-lang/rust/pull/62735/
+[62766]: https://github.com/rust-lang/rust/pull/62766/
+[62784]: https://github.com/rust-lang/rust/pull/62784/
+[62814]: https://github.com/rust-lang/rust/pull/62814/
+[63000]: https://github.com/rust-lang/rust/pull/63000/
+[63056]: https://github.com/rust-lang/rust/pull/63056/
+[63107]: https://github.com/rust-lang/rust/pull/63107/
+[63346]: https://github.com/rust-lang/rust/pull/63346/
+[63421]: https://github.com/rust-lang/rust/pull/63421/
+[cargo/7084]: https://github.com/rust-lang/cargo/pull/7084/
+[cargo/7143]: https://github.com/rust-lang/cargo/pull/7143/
+[`<*const T>::cast`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.cast
+[`<*mut T>::cast`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.cast
+[`Duration::as_secs_f32`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_secs_f32
+[`Duration::as_secs_f64`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_secs_f64
+[`Duration::div_duration_f32`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.div_duration_f32
+[`Duration::div_duration_f64`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.div_duration_f64
+[`Duration::div_f32`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.div_f32
+[`Duration::div_f64`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.div_f64
+[`Duration::from_secs_f32`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.from_secs_f32
+[`Duration::from_secs_f64`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.from_secs_f64
+[`Duration::mul_f32`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.mul_f32
+[`Duration::mul_f64`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.mul_f64
+[`any::type_name`]: https://doc.rust-lang.org/std/any/fn.type_name.html
+[forge-platform-support]: https://forge.rust-lang.org/platform-support.html
+[pipeline-internals]: https://internals.rust-lang.org/t/evaluating-pipelined-rustc-compilation/10199
+
 Version 1.37.0 (2019-08-15)
 ==========================
 
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 500d576..076bcd8 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -2000,6 +2000,8 @@
     }
 
     fn run(self, builder: &Builder<'_>) {
+        // This gets called by `promote-release`
+        // (https://github.com/rust-lang/rust-central-station/tree/master/promote-release).
         let mut cmd = builder.tool_cmd(Tool::BuildManifest);
         if builder.config.dry_run {
             return;
@@ -2010,10 +2012,14 @@
         let addr = builder.config.dist_upload_addr.as_ref().unwrap_or_else(|| {
             panic!("\n\nfailed to specify `dist.upload-addr` in `config.toml`\n\n")
         });
-        let file = builder.config.dist_gpg_password_file.as_ref().unwrap_or_else(|| {
-            panic!("\n\nfailed to specify `dist.gpg-password-file` in `config.toml`\n\n")
-        });
-        let pass = t!(fs::read_to_string(&file));
+        let pass = if env::var("BUILD_MANIFEST_DISABLE_SIGNING").is_err() {
+            let file = builder.config.dist_gpg_password_file.as_ref().unwrap_or_else(|| {
+                panic!("\n\nfailed to specify `dist.gpg-password-file` in `config.toml`\n\n")
+            });
+            t!(fs::read_to_string(&file))
+        } else {
+            String::new()
+        };
 
         let today = output(Command::new("date").arg("+%Y-%m-%d"));
 
diff --git a/src/ci/azure-pipelines/auto.yml b/src/ci/azure-pipelines/auto.yml
index 77c9cda..1656066 100644
--- a/src/ci/azure-pipelines/auto.yml
+++ b/src/ci/azure-pipelines/auto.yml
@@ -236,10 +236,16 @@
         MSYS_BITS: 32
         RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc
         SCRIPT: make ci-subset-1
+        # FIXME(#59637)
+        NO_DEBUG_ASSERTIONS: 1
+        NO_LLVM_ASSERTIONS: 1
       i686-msvc-2:
         MSYS_BITS: 32
         RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc
         SCRIPT: make ci-subset-2
+        # FIXME(#59637)
+        NO_DEBUG_ASSERTIONS: 1
+        NO_LLVM_ASSERTIONS: 1
       # MSVC aux tests
       x86_64-msvc-aux:
         MSYS_BITS: 64
@@ -250,6 +256,9 @@
         SCRIPT: python x.py test src/tools/cargotest src/tools/cargo
         RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc
         VCVARS_BAT: vcvars64.bat
+        # FIXME(#59637)
+        NO_DEBUG_ASSERTIONS: 1
+        NO_LLVM_ASSERTIONS: 1
       # MSVC tools tests
       x86_64-msvc-tools:
         MSYS_BITS: 64
diff --git a/src/ci/azure-pipelines/steps/run.yml b/src/ci/azure-pipelines/steps/run.yml
index ac6b344..da0a899 100644
--- a/src/ci/azure-pipelines/steps/run.yml
+++ b/src/ci/azure-pipelines/steps/run.yml
@@ -147,8 +147,15 @@
     git clone --depth=1 https://github.com/rust-lang-nursery/rust-toolstate.git
     cd rust-toolstate
     python2.7 "$BUILD_SOURCESDIRECTORY/src/tools/publish_toolstate.py" "$(git rev-parse HEAD)" "$(git log --format=%s -n1 HEAD)" "" ""
+    # Only check maintainers if this build is supposed to publish toolstate.
+    # Builds that are not supposed to publish don't have the access token.
+    if [ -n "${TOOLSTATE_PUBLISH+is_set}" ]; then
+      TOOLSTATE_VALIDATE_MAINTAINERS_REPO=rust-lang/rust python2.7 "${BUILD_SOURCESDIRECTORY}/src/tools/publish_toolstate.py"
+    fi
     cd ..
     rm -rf rust-toolstate
+  env:
+    TOOLSTATE_REPO_ACCESS_TOKEN: $(TOOLSTATE_REPO_ACCESS_TOKEN)
   condition: and(succeeded(), not(variables.SKIP_JOB), eq(variables['IMAGE'], 'mingw-check'))
   displayName: Verify the publish_toolstate script works
 
diff --git a/src/ci/docker/i686-gnu-nopt/Dockerfile b/src/ci/docker/i686-gnu-nopt/Dockerfile
index 2041ba5..517b59c 100644
--- a/src/ci/docker/i686-gnu-nopt/Dockerfile
+++ b/src/ci/docker/i686-gnu-nopt/Dockerfile
@@ -19,3 +19,6 @@
 
 ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu --disable-optimize-tests
 ENV SCRIPT python2.7 ../x.py test
+
+# FIXME(#59637) takes too long on CI right now
+ENV NO_LLVM_ASSERTIONS=1 NO_DEBUG_ASSERTIONS=1
diff --git a/src/ci/docker/i686-gnu/Dockerfile b/src/ci/docker/i686-gnu/Dockerfile
index 17441dd..03db3ba 100644
--- a/src/ci/docker/i686-gnu/Dockerfile
+++ b/src/ci/docker/i686-gnu/Dockerfile
@@ -25,3 +25,6 @@
   --exclude src/test/rustdoc-js \
   --exclude src/tools/error_index_generator \
   --exclude src/tools/linkchecker
+
+# FIXME(#59637) takes too long on CI right now
+ENV NO_LLVM_ASSERTIONS=1 NO_DEBUG_ASSERTIONS=1
diff --git a/src/liballoc/collections/btree/set.rs b/src/liballoc/collections/btree/set.rs
index d3af910..0cb91ba 100644
--- a/src/liballoc/collections/btree/set.rs
+++ b/src/liballoc/collections/btree/set.rs
@@ -3,7 +3,7 @@
 
 use core::borrow::Borrow;
 use core::cmp::Ordering::{self, Less, Greater, Equal};
-use core::cmp::max;
+use core::cmp::{max, min};
 use core::fmt::{self, Debug};
 use core::iter::{Peekable, FromIterator, FusedIterator};
 use core::ops::{BitOr, BitAnd, BitXor, Sub, RangeBounds};
@@ -187,8 +187,8 @@
 }
 enum IntersectionInner<'a, T: 'a> {
     Stitch {
-        small_iter: Iter<'a, T>, // for size_hint, should be the smaller of the sets
-        other_iter: Iter<'a, T>,
+        a: Iter<'a, T>,
+        b: Iter<'a, T>,
     },
     Search {
         small_iter: Iter<'a, T>,
@@ -201,12 +201,12 @@
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match &self.inner {
             IntersectionInner::Stitch {
-                small_iter,
-                other_iter,
+                a,
+                b,
             } => f
                 .debug_tuple("Intersection")
-                .field(&small_iter)
-                .field(&other_iter)
+                .field(&a)
+                .field(&b)
                 .finish(),
             IntersectionInner::Search {
                 small_iter,
@@ -397,8 +397,8 @@
             // Iterate both sets jointly, spotting matches along the way.
             Intersection {
                 inner: IntersectionInner::Stitch {
-                    small_iter: small.iter(),
-                    other_iter: other.iter(),
+                    a: small.iter(),
+                    b: other.iter(),
                 },
             }
         } else {
@@ -1221,11 +1221,11 @@
         Intersection {
             inner: match &self.inner {
                 IntersectionInner::Stitch {
-                    small_iter,
-                    other_iter,
+                    a,
+                    b,
                 } => IntersectionInner::Stitch {
-                    small_iter: small_iter.clone(),
-                    other_iter: other_iter.clone(),
+                    a: a.clone(),
+                    b: b.clone(),
                 },
                 IntersectionInner::Search {
                     small_iter,
@@ -1245,16 +1245,16 @@
     fn next(&mut self) -> Option<&'a T> {
         match &mut self.inner {
             IntersectionInner::Stitch {
-                small_iter,
-                other_iter,
+                a,
+                b,
             } => {
-                let mut small_next = small_iter.next()?;
-                let mut other_next = other_iter.next()?;
+                let mut a_next = a.next()?;
+                let mut b_next = b.next()?;
                 loop {
-                    match Ord::cmp(small_next, other_next) {
-                        Less => small_next = small_iter.next()?,
-                        Greater => other_next = other_iter.next()?,
-                        Equal => return Some(small_next),
+                    match Ord::cmp(a_next, b_next) {
+                        Less => a_next = a.next()?,
+                        Greater => b_next = b.next()?,
+                        Equal => return Some(a_next),
                     }
                 }
             }
@@ -1272,7 +1272,7 @@
 
     fn size_hint(&self) -> (usize, Option<usize>) {
         let min_len = match &self.inner {
-            IntersectionInner::Stitch { small_iter, .. } => small_iter.len(),
+            IntersectionInner::Stitch { a, b } => min(a.len(), b.len()),
             IntersectionInner::Search { small_iter, .. } => small_iter.len(),
         };
         (0, Some(min_len))
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index 370e5cf..9e6ed92 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -117,7 +117,7 @@
 #![feature(allocator_internals)]
 #![feature(on_unimplemented)]
 #![feature(rustc_const_unstable)]
-#![feature(const_vec_new)]
+#![cfg_attr(bootstrap, feature(const_vec_new))]
 #![feature(slice_partition_dedup)]
 #![feature(maybe_uninit_extra, maybe_uninit_slice)]
 #![feature(alloc_layout_extra)]
diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs
index cf025ee..ee75fc2 100644
--- a/src/liballoc/raw_vec.rs
+++ b/src/liballoc/raw_vec.rs
@@ -113,13 +113,38 @@
 }
 
 impl<T> RawVec<T, Global> {
+    /// HACK(Centril): This exists because `#[unstable]` `const fn`s needn't conform
+    /// to `min_const_fn` and so they cannot be called in `min_const_fn`s either.
+    ///
+    /// If you change `RawVec<T>::new` or dependencies, please take care to not
+    /// introduce anything that would truly violate `min_const_fn`.
+    ///
+    /// NOTE: We could avoid this hack and check conformance with some
+    /// `#[rustc_force_min_const_fn]` attribute which requires conformance
+    /// with `min_const_fn` but does not necessarily allow calling it in
+    /// `stable(...) const fn` / user code not enabling `foo` when
+    /// `#[rustc_const_unstable(feature = "foo", ..)]` is present.
+    pub const NEW: Self = Self::new();
+
     /// Creates the biggest possible `RawVec` (on the system heap)
     /// without allocating. If `T` has positive size, then this makes a
     /// `RawVec` with capacity `0`. If `T` is zero-sized, then it makes a
     /// `RawVec` with capacity `usize::MAX`. Useful for implementing
     /// delayed allocation.
     pub const fn new() -> Self {
-        Self::new_in(Global)
+        // FIXME(Centril): Reintegrate this with `fn new_in` when we can.
+
+        // `!0` is `usize::MAX`. This branch should be stripped at compile time.
+        // FIXME(mark-i-m): use this line when `if`s are allowed in `const`:
+        //let cap = if mem::size_of::<T>() == 0 { !0 } else { 0 };
+
+        // `Unique::empty()` doubles as "unallocated" and "zero-sized allocation".
+        RawVec {
+            ptr: Unique::empty(),
+            // FIXME(mark-i-m): use `cap` when ifs are allowed in const
+            cap: [0, !0][(mem::size_of::<T>() == 0) as usize],
+            a: Global,
+        }
     }
 
     /// Creates a `RawVec` (on the system heap) with exactly the
diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs
index b65f191..1166e7b 100644
--- a/src/liballoc/string.rs
+++ b/src/liballoc/string.rs
@@ -369,7 +369,7 @@
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_string_new")]
+    #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_string_new"))]
     pub const fn new() -> String {
         String { vec: Vec::new() }
     }
diff --git a/src/liballoc/tests/btree/set.rs b/src/liballoc/tests/btree/set.rs
index 62ccb53..35db18c 100644
--- a/src/liballoc/tests/btree/set.rs
+++ b/src/liballoc/tests/btree/set.rs
@@ -91,6 +91,17 @@
 }
 
 #[test]
+fn test_intersection_size_hint() {
+    let x: BTreeSet<i32> = [3, 4].iter().copied().collect();
+    let y: BTreeSet<i32> = [1, 2, 3].iter().copied().collect();
+    let mut iter = x.intersection(&y);
+    assert_eq!(iter.size_hint(), (0, Some(2)));
+    assert_eq!(iter.next(), Some(&3));
+    assert_eq!(iter.size_hint(), (0, Some(0)));
+    assert_eq!(iter.next(), None);
+}
+
+#[test]
 fn test_difference() {
     fn check_difference(a: &[i32], b: &[i32], expected: &[i32]) {
         check(a, b, expected, |x, y, f| x.difference(y).all(f))
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs
index c513658..405969a 100644
--- a/src/liballoc/vec.rs
+++ b/src/liballoc/vec.rs
@@ -314,10 +314,10 @@
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_vec_new")]
+    #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_vec_new"))]
     pub const fn new() -> Vec<T> {
         Vec {
-            buf: RawVec::new(),
+            buf: RawVec::NEW,
             len: 0,
         }
     }
diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs
index 402a7b2..06f2b7b 100644
--- a/src/libcore/convert.rs
+++ b/src/libcore/convert.rs
@@ -42,11 +42,11 @@
 
 use crate::fmt;
 
-/// An identity function.
+/// The identity function.
 ///
 /// Two things are important to note about this function:
 ///
-/// - It is not always equivalent to a closure like `|x| x` since the
+/// - It is not always equivalent to a closure like `|x| x`, since the
 ///   closure may coerce `x` into a different type.
 ///
 /// - It moves the input `x` passed to the function.
@@ -56,31 +56,32 @@
 ///
 /// # Examples
 ///
-/// Using `identity` to do nothing among other interesting functions:
+/// Using `identity` to do nothing in a sequence of other, interesting,
+/// functions:
 ///
 /// ```rust
 /// use std::convert::identity;
 ///
 /// fn manipulation(x: u32) -> u32 {
-///     // Let's assume that this function does something interesting.
+///     // Let's pretend that adding one is an interesting function.
 ///     x + 1
 /// }
 ///
 /// let _arr = &[identity, manipulation];
 /// ```
 ///
-/// Using `identity` to get a function that changes nothing in a conditional:
+/// Using `identity` as a "do nothing" base case in a conditional:
 ///
 /// ```rust
 /// use std::convert::identity;
 ///
 /// # let condition = true;
-///
+/// #
 /// # fn manipulation(x: u32) -> u32 { x + 1 }
-///
+/// #
 /// let do_stuff = if condition { manipulation } else { identity };
 ///
-/// // do more interesting stuff..
+/// // Do more interesting stuff...
 ///
 /// let _results = do_stuff(42);
 /// ```
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index d145f22..ecff40a 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -845,21 +845,26 @@
     ///
     /// ```
     /// let store = [0, 1, 2, 3];
-    /// let mut v_orig = store.iter().collect::<Vec<&i32>>();
+    /// let v_orig = store.iter().collect::<Vec<&i32>>();
+    ///
+    /// // clone the vector as we will reuse them later
+    /// let v_clone = v_orig.clone();
     ///
     /// // Using transmute: this is Undefined Behavior, and a bad idea.
     /// // However, it is no-copy.
     /// let v_transmuted = unsafe {
-    ///     std::mem::transmute::<Vec<&i32>, Vec<Option<&i32>>>(
-    ///         v_orig.clone())
+    ///     std::mem::transmute::<Vec<&i32>, Vec<Option<&i32>>>(v_clone)
     /// };
     ///
+    /// let v_clone = v_orig.clone();
+    ///
     /// // This is the suggested, safe way.
     /// // It does copy the entire vector, though, into a new array.
-    /// let v_collected = v_orig.clone()
-    ///                         .into_iter()
-    ///                         .map(|r| Some(r))
-    ///                         .collect::<Vec<Option<&i32>>>();
+    /// let v_collected = v_clone.into_iter()
+    ///                          .map(Some)
+    ///                          .collect::<Vec<Option<&i32>>>();
+    ///
+    /// let v_clone = v_orig.clone();
     ///
     /// // The no-copy, unsafe way, still using transmute, but not UB.
     /// // This is equivalent to the original, but safer, and reuses the
@@ -869,11 +874,12 @@
     /// // the original inner type (`&i32`) to the converted inner type
     /// // (`Option<&i32>`), so read the nomicon pages linked above.
     /// let v_from_raw = unsafe {
-    ///     Vec::from_raw_parts(v_orig.as_mut_ptr() as *mut Option<&i32>,
-    ///                         v_orig.len(),
-    ///                         v_orig.capacity())
+    ///     // Ensure the original vector is not dropped.
+    ///     let mut v_clone = std::mem::ManuallyDrop::new(v_clone);
+    ///     Vec::from_raw_parts(v_clone.as_mut_ptr() as *mut Option<&i32>,
+    ///                         v_clone.len(),
+    ///                         v_clone.capacity())
     /// };
-    /// std::mem::forget(v_orig);
     /// ```
     ///
     /// Implementing `split_at_mut`:
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index 79bd04b..5569d99 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -295,7 +295,7 @@
     /// [`Pin`]: ../pin/struct.Pin.html
     #[inline]
     #[stable(feature = "pin", since = "1.33.0")]
-    pub fn as_pin_ref<'a>(self: Pin<&'a Option<T>>) -> Option<Pin<&'a T>> {
+    pub fn as_pin_ref(self: Pin<&Self>) -> Option<Pin<&T>> {
         unsafe {
             Pin::get_ref(self).as_ref().map(|x| Pin::new_unchecked(x))
         }
@@ -306,7 +306,7 @@
     /// [`Pin`]: ../pin/struct.Pin.html
     #[inline]
     #[stable(feature = "pin", since = "1.33.0")]
-    pub fn as_pin_mut<'a>(self: Pin<&'a mut Option<T>>) -> Option<Pin<&'a mut T>> {
+    pub fn as_pin_mut(self: Pin<&mut Self>) -> Option<Pin<&mut T>> {
         unsafe {
             Pin::get_unchecked_mut(self).as_mut().map(|x| Pin::new_unchecked(x))
         }
diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs
index 1080fd3..1dc6d54 100644
--- a/src/libcore/pin.rs
+++ b/src/libcore/pin.rs
@@ -233,7 +233,7 @@
 //! # type Field = i32;
 //! # struct Struct { field: Field }
 //! impl Struct {
-//!     fn pin_get_field<'a>(self: Pin<&'a mut Self>) -> &'a mut Field {
+//!     fn pin_get_field(self: Pin<&mut Self>) -> &mut Field {
 //!         // This is okay because `field` is never considered pinned.
 //!         unsafe { &mut self.get_unchecked_mut().field }
 //!     }
@@ -257,7 +257,7 @@
 //! # type Field = i32;
 //! # struct Struct { field: Field }
 //! impl Struct {
-//!     fn pin_get_field<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut Field> {
+//!     fn pin_get_field(self: Pin<&mut Self>) -> Pin<&mut Field> {
 //!         // This is okay because `field` is pinned when `self` is.
 //!         unsafe { self.map_unchecked_mut(|s| &mut s.field) }
 //!     }
@@ -549,7 +549,7 @@
     /// ruled out by the contract of `Pin::new_unchecked`.
     #[stable(feature = "pin", since = "1.33.0")]
     #[inline(always)]
-    pub fn as_ref(self: &Pin<P>) -> Pin<&P::Target> {
+    pub fn as_ref(&self) -> Pin<&P::Target> {
         unsafe { Pin::new_unchecked(&*self.pointer) }
     }
 
@@ -584,9 +584,30 @@
     /// the pointee cannot move after `Pin<Pointer<T>>` got created.
     /// "Malicious" implementations of `Pointer::DerefMut` are likewise
     /// ruled out by the contract of `Pin::new_unchecked`.
+    ///
+    /// This method is useful when doing multiple calls to functions that consume the pinned type.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use std::pin::Pin;
+    ///
+    /// # struct Type {}
+    /// impl Type {
+    ///     fn method(self: Pin<&mut Self>) {
+    ///         // do something
+    ///     }
+    ///
+    ///     fn call_method_twice(mut self: Pin<&mut Self>) {
+    ///         // `method` consumes `self`, so reborrow the `Pin<&mut Self>` via `as_mut`.
+    ///         self.as_mut().method();
+    ///         self.as_mut().method();
+    ///     }
+    /// }
+    /// ```
     #[stable(feature = "pin", since = "1.33.0")]
     #[inline(always)]
-    pub fn as_mut(self: &mut Pin<P>) -> Pin<&mut P::Target> {
+    pub fn as_mut(&mut self) -> Pin<&mut P::Target> {
         unsafe { Pin::new_unchecked(&mut *self.pointer) }
     }
 
@@ -596,7 +617,7 @@
     /// run before being overwritten, so no pinning guarantee is violated.
     #[stable(feature = "pin", since = "1.33.0")]
     #[inline(always)]
-    pub fn set(self: &mut Pin<P>, value: P::Target)
+    pub fn set(&mut self, value: P::Target)
     where
         P::Target: Sized,
     {
@@ -621,7 +642,7 @@
     ///
     /// [`pin` module]: ../../std/pin/index.html#projections-and-structural-pinning
     #[stable(feature = "pin", since = "1.33.0")]
-    pub unsafe fn map_unchecked<U, F>(self: Pin<&'a T>, func: F) -> Pin<&'a U> where
+    pub unsafe fn map_unchecked<U, F>(self, func: F) -> Pin<&'a U> where
         F: FnOnce(&T) -> &U,
     {
         let pointer = &*self.pointer;
@@ -648,7 +669,7 @@
     /// ["pinning projections"]: ../../std/pin/index.html#projections-and-structural-pinning
     #[stable(feature = "pin", since = "1.33.0")]
     #[inline(always)]
-    pub fn get_ref(self: Pin<&'a T>) -> &'a T {
+    pub fn get_ref(self) -> &'a T {
         self.pointer
     }
 }
@@ -657,7 +678,7 @@
     /// Converts this `Pin<&mut T>` into a `Pin<&T>` with the same lifetime.
     #[stable(feature = "pin", since = "1.33.0")]
     #[inline(always)]
-    pub fn into_ref(self: Pin<&'a mut T>) -> Pin<&'a T> {
+    pub fn into_ref(self) -> Pin<&'a T> {
         Pin { pointer: self.pointer }
     }
 
@@ -672,7 +693,7 @@
     /// with the same lifetime as the original `Pin`.
     #[stable(feature = "pin", since = "1.33.0")]
     #[inline(always)]
-    pub fn get_mut(self: Pin<&'a mut T>) -> &'a mut T
+    pub fn get_mut(self) -> &'a mut T
         where T: Unpin,
     {
         self.pointer
@@ -690,7 +711,7 @@
     /// instead.
     #[stable(feature = "pin", since = "1.33.0")]
     #[inline(always)]
-    pub unsafe fn get_unchecked_mut(self: Pin<&'a mut T>) -> &'a mut T {
+    pub unsafe fn get_unchecked_mut(self) -> &'a mut T {
         self.pointer
     }
 
@@ -710,7 +731,7 @@
     ///
     /// [`pin` module]: ../../std/pin/index.html#projections-and-structural-pinning
     #[stable(feature = "pin", since = "1.33.0")]
-    pub unsafe fn map_unchecked_mut<U, F>(self: Pin<&'a mut T>, func: F) -> Pin<&'a mut U> where
+    pub unsafe fn map_unchecked_mut<U, F>(self, func: F) -> Pin<&'a mut U> where
         F: FnOnce(&mut T) -> &mut U,
     {
         let pointer = Pin::get_unchecked_mut(self);
diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml
index 66071d6..0834faf 100644
--- a/src/librustc/Cargo.toml
+++ b/src/librustc/Cargo.toml
@@ -30,8 +30,8 @@
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
 backtrace = "0.3.3"
-parking_lot = "0.7"
-byteorder = { version = "1.1", features = ["i128"]}
+parking_lot = "0.9"
+byteorder = { version = "1.3" }
 chalk-engine = { version = "0.9.0", default-features=false }
 rustc_fs_util = { path = "../librustc_fs_util" }
 smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index b50cfa0..48f7fc4 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -1316,7 +1316,7 @@
                             ImplTraitContext::Universal(in_band_ty_params),
                         );
                         // Set the name to `impl Bound1 + Bound2`.
-                        let ident = Ident::from_str(&pprust::ty_to_string(t)).with_span_pos(span);
+                        let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span);
                         in_band_ty_params.push(hir::GenericParam {
                             hir_id: self.lower_node_id(def_node_id),
                             name: ParamName::Plain(ident),
@@ -2682,12 +2682,8 @@
         bounds.iter().map(|bound| self.lower_param_bound(bound, itctx.reborrow())).collect()
     }
 
-    fn lower_block_with_stmts(
-        &mut self,
-        b: &Block,
-        targeted_by_break: bool,
-        mut stmts: Vec<hir::Stmt>,
-    ) -> P<hir::Block> {
+    fn lower_block(&mut self, b: &Block, targeted_by_break: bool) -> P<hir::Block> {
+        let mut stmts = vec![];
         let mut expr = None;
 
         for (index, stmt) in b.stmts.iter().enumerate() {
@@ -2712,8 +2708,11 @@
         })
     }
 
-    fn lower_block(&mut self, b: &Block, targeted_by_break: bool) -> P<hir::Block> {
-        self.lower_block_with_stmts(b, targeted_by_break, vec![])
+    /// Lowers a block directly to an expression, presuming that it
+    /// has no attributes and is not targeted by a `break`.
+    fn lower_block_expr(&mut self, b: &Block) -> hir::Expr {
+        let block = self.lower_block(b, false);
+        self.expr_block(block, ThinVec::new())
     }
 
     fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
diff --git a/src/librustc/hir/lowering/expr.rs b/src/librustc/hir/lowering/expr.rs
index a46cdab..990728f 100644
--- a/src/librustc/hir/lowering/expr.rs
+++ b/src/librustc/hir/lowering/expr.rs
@@ -90,10 +90,7 @@
             ),
             ExprKind::Async(capture_clause, closure_node_id, ref block) => {
                 self.make_async_expr(capture_clause, closure_node_id, None, block.span, |this| {
-                    this.with_new_scopes(|this| {
-                        let block = this.lower_block(block, false);
-                        this.expr_block(block, ThinVec::new())
-                    })
+                    this.with_new_scopes(|this| this.lower_block_expr(block))
                 })
             }
             ExprKind::Await(ref expr) => self.lower_expr_await(e.span, expr),
@@ -284,8 +281,7 @@
         let else_arm = self.arm(hir_vec![else_pat], P(else_expr));
 
         // Handle then + scrutinee:
-        let then_blk = self.lower_block(then, false);
-        let then_expr = self.expr_block(then_blk, ThinVec::new());
+        let then_expr = self.lower_block_expr(then);
         let (then_pat, scrutinee, desugar) = match cond.node {
             // `<pat> => <then>`:
             ExprKind::Let(ref pat, ref scrutinee) => {
@@ -335,8 +331,7 @@
         };
 
         // Handle then + scrutinee:
-        let then_blk = self.lower_block(body, false);
-        let then_expr = self.expr_block(then_blk, ThinVec::new());
+        let then_expr = self.lower_block_expr(body);
         let (then_pat, scrutinee, desugar, source) = match cond.node {
             ExprKind::Let(ref pat, ref scrutinee) => {
                 // to:
@@ -356,7 +351,7 @@
                 //
                 // ```
                 // 'label: loop {
-                //     match DropTemps($cond) {
+                //     match drop-temps { $cond } {
                 //         true => $body,
                 //         _ => break,
                 //     }
@@ -1310,7 +1305,7 @@
     /// `{ let _t = $expr; _t }` but should provide better compile-time performance.
     ///
     /// The drop order can be important in e.g. `if expr { .. }`.
-    fn expr_drop_temps(
+    pub(super) fn expr_drop_temps(
         &mut self,
         span: Span,
         expr: P<hir::Expr>,
diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs
index 5f82e42..61be40a 100644
--- a/src/librustc/hir/lowering/item.rs
+++ b/src/librustc/hir/lowering/item.rs
@@ -1071,10 +1071,7 @@
     }
 
     fn lower_fn_body_block(&mut self, decl: &FnDecl, body: &Block) -> hir::BodyId {
-        self.lower_fn_body(decl, |this| {
-            let body = this.lower_block(body, false);
-            this.expr_block(body, ThinVec::new())
-        })
+        self.lower_fn_body(decl, |this| this.lower_block_expr(body))
     }
 
     pub(super) fn lower_const_body(&mut self, expr: &Expr) -> hir::BodyId {
@@ -1102,8 +1099,7 @@
             // from:
             //
             //     async fn foo(<pattern>: <ty>, <pattern>: <ty>, <pattern>: <ty>) {
-            //       async move {
-            //       }
+            //         <body>
             //     }
             //
             // into:
@@ -1116,11 +1112,19 @@
             //         let <pattern> = __arg1;
             //         let __arg0 = __arg0;
             //         let <pattern> = __arg0;
+            //         drop-temps { <body> } // see comments later in fn for details
             //       }
             //     }
             //
             // If `<pattern>` is a simple ident, then it is lowered to a single
             // `let <pattern> = <pattern>;` statement as an optimization.
+            //
+            // Note that the body is embedded in `drop-temps`; an
+            // equivalent desugaring would be `return { <body>
+            // };`. The key point is that we wish to drop all the
+            // let-bound variables and temporaries created in the body
+            // (and its tail expression!) before we drop the
+            // parameters (c.f. rust-lang/rust#64512).
             for (index, parameter) in decl.inputs.iter().enumerate() {
                 let parameter = this.lower_param(parameter);
                 let span = parameter.pat.span;
@@ -1219,8 +1223,36 @@
             let async_expr = this.make_async_expr(
                 CaptureBy::Value, closure_id, None, body.span,
                 |this| {
-                    let body = this.lower_block_with_stmts(body, false, statements);
-                    this.expr_block(body, ThinVec::new())
+                    // Create a block from the user's function body:
+                    let user_body = this.lower_block_expr(body);
+
+                    // Transform into `drop-temps { <user-body> }`, an expression:
+                    let desugared_span = this.mark_span_with_reason(
+                        DesugaringKind::Async,
+                        user_body.span,
+                        None,
+                    );
+                    let user_body = this.expr_drop_temps(
+                        desugared_span,
+                        P(user_body),
+                        ThinVec::new(),
+                    );
+
+                    // As noted above, create the final block like
+                    //
+                    // ```
+                    // {
+                    //   let $param_pattern = $raw_param;
+                    //   ...
+                    //   drop-temps { <user-body> }
+                    // }
+                    // ```
+                    let body = this.block_all(
+                        desugared_span,
+                        statements.into(),
+                        Some(P(user_body)),
+                    );
+                    this.expr_block(P(body), ThinVec::new())
                 });
             (HirVec::from(parameters), this.expr(body.span, async_expr, ThinVec::new()))
         })
diff --git a/src/librustc/infer/equate.rs b/src/librustc/infer/equate.rs
index 5dfa0d2..96d40bc 100644
--- a/src/librustc/infer/equate.rs
+++ b/src/librustc/infer/equate.rs
@@ -97,7 +97,7 @@
                self.tag(),
                a,
                b);
-        let origin = Subtype(self.fields.trace.clone());
+        let origin = Subtype(box self.fields.trace.clone());
         self.fields.infcx.borrow_region_constraints()
                          .make_eqregion(origin, a, b);
         Ok(a)
diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs
index b4fb018..bfa8353 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs
@@ -30,7 +30,7 @@
             Some(RegionResolutionError::SubSupConflict(
                 vid,
                 _,
-                SubregionOrigin::Subtype(TypeTrace {
+                SubregionOrigin::Subtype(box TypeTrace {
                     cause,
                     values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
                 }),
@@ -50,7 +50,7 @@
             Some(RegionResolutionError::SubSupConflict(
                 vid,
                 _,
-                SubregionOrigin::Subtype(TypeTrace {
+                SubregionOrigin::Subtype(box TypeTrace {
                     cause,
                     values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
                 }),
@@ -70,7 +70,7 @@
             Some(RegionResolutionError::SubSupConflict(
                 vid,
                 _,
-                SubregionOrigin::Subtype(TypeTrace {
+                SubregionOrigin::Subtype(box TypeTrace {
                     cause,
                     values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
                 }),
@@ -92,7 +92,7 @@
                 _,
                 _,
                 _,
-                SubregionOrigin::Subtype(TypeTrace {
+                SubregionOrigin::Subtype(box TypeTrace {
                     cause,
                     values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
                 }),
@@ -108,7 +108,7 @@
             )),
 
             Some(RegionResolutionError::ConcreteFailure(
-                SubregionOrigin::Subtype(TypeTrace {
+                SubregionOrigin::Subtype(box TypeTrace {
                     cause,
                     values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
                 }),
@@ -125,7 +125,7 @@
             )),
 
             Some(RegionResolutionError::ConcreteFailure(
-                SubregionOrigin::Subtype(TypeTrace {
+                SubregionOrigin::Subtype(box TypeTrace {
                     cause,
                     values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
                 }),
@@ -142,7 +142,7 @@
             )),
 
             Some(RegionResolutionError::ConcreteFailure(
-                SubregionOrigin::Subtype(TypeTrace {
+                SubregionOrigin::Subtype(box TypeTrace {
                     cause,
                     values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
                 }),
@@ -192,23 +192,28 @@
             vid, sub_placeholder, sup_placeholder, trait_def_id, expected_substs, actual_substs
         );
 
-        let mut err = self.tcx().sess.struct_span_err(
-            cause.span(self.tcx()),
-            &format!(
-                "implementation of `{}` is not general enough",
-                self.tcx().def_path_str(trait_def_id),
-            ),
+        let span = cause.span(self.tcx());
+        let msg = format!(
+            "implementation of `{}` is not general enough",
+            self.tcx().def_path_str(trait_def_id),
+        );
+        let mut err = self.tcx().sess.struct_span_err(span, &msg);
+        err.span_label(
+            self.tcx().def_span(trait_def_id),
+            format!("trait `{}` defined here", self.tcx().def_path_str(trait_def_id)),
         );
 
-        match cause.code {
-            ObligationCauseCode::ItemObligation(def_id) => {
-                err.note(&format!(
-                    "Due to a where-clause on `{}`,",
-                    self.tcx().def_path_str(def_id),
-                ));
-            }
-            _ => (),
-        }
+        let leading_ellipsis = if let ObligationCauseCode::ItemObligation(def_id) = cause.code {
+            err.span_label(span, "doesn't satisfy where-clause");
+            err.span_label(
+                self.tcx().def_span(def_id),
+                &format!("due to a where-clause on `{}`...", self.tcx().def_path_str(def_id)),
+            );
+            true
+        } else {
+            err.span_label(span, &msg);
+            false
+        };
 
         let expected_trait_ref = self.infcx.resolve_vars_if_possible(&ty::TraitRef {
             def_id: trait_def_id,
@@ -295,6 +300,7 @@
             expected_has_vid,
             actual_has_vid,
             any_self_ty_has_vid,
+            leading_ellipsis,
         );
 
         err
@@ -318,6 +324,7 @@
         expected_has_vid: Option<usize>,
         actual_has_vid: Option<usize>,
         any_self_ty_has_vid: bool,
+        leading_ellipsis: bool,
     ) {
         // HACK(eddyb) maybe move this in a more central location.
         #[derive(Copy, Clone)]
@@ -392,13 +399,15 @@
 
             let mut note = if passive_voice {
                 format!(
-                    "`{}` would have to be implemented for the type `{}`",
+                    "{}`{}` would have to be implemented for the type `{}`",
+                    if leading_ellipsis { "..." } else { "" },
                     expected_trait_ref,
                     expected_trait_ref.map(|tr| tr.self_ty()),
                 )
             } else {
                 format!(
-                    "`{}` must implement `{}`",
+                    "{}`{}` must implement `{}`",
+                    if leading_ellipsis { "..." } else { "" },
                     expected_trait_ref.map(|tr| tr.self_ty()),
                     expected_trait_ref,
                 )
@@ -407,20 +416,20 @@
             match (has_sub, has_sup) {
                 (Some(n1), Some(n2)) => {
                     let _ = write!(note,
-                        ", for any two lifetimes `'{}` and `'{}`",
+                        ", for any two lifetimes `'{}` and `'{}`...",
                         std::cmp::min(n1, n2),
                         std::cmp::max(n1, n2),
                     );
                 }
                 (Some(n), _) | (_, Some(n)) => {
                     let _ = write!(note,
-                        ", for any lifetime `'{}`",
+                        ", for any lifetime `'{}`...",
                         n,
                     );
                 }
                 (None, None) => if let Some(n) = expected_has_vid {
                     let _ = write!(note,
-                        ", for some specific lifetime `'{}`",
+                        ", for some specific lifetime `'{}`...",
                         n,
                     );
                 },
@@ -439,13 +448,13 @@
 
             let mut note = if passive_voice {
                 format!(
-                    "but `{}` is actually implemented for the type `{}`",
+                    "...but `{}` is actually implemented for the type `{}`",
                     actual_trait_ref,
                     actual_trait_ref.map(|tr| tr.self_ty()),
                 )
             } else {
                 format!(
-                    "but `{}` actually implements `{}`",
+                    "...but `{}` actually implements `{}`",
                     actual_trait_ref.map(|tr| tr.self_ty()),
                     actual_trait_ref,
                 )
diff --git a/src/librustc/infer/error_reporting/note.rs b/src/librustc/infer/error_reporting/note.rs
index caed428..115ffea 100644
--- a/src/librustc/infer/error_reporting/note.rs
+++ b/src/librustc/infer/error_reporting/note.rs
@@ -138,7 +138,7 @@
                                           sup: Region<'tcx>)
                                           -> DiagnosticBuilder<'tcx> {
         match origin {
-            infer::Subtype(trace) => {
+            infer::Subtype(box trace) => {
                 let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
                 let mut err = self.report_and_explain_type_error(trace, &terr);
                 self.tcx.note_and_explain_region(region_scope_tree, &mut err, "", sup, "...");
@@ -450,7 +450,7 @@
     ) -> DiagnosticBuilder<'tcx> {
         // I can't think how to do better than this right now. -nikomatsakis
         match placeholder_origin {
-            infer::Subtype(trace) => {
+            infer::Subtype(box trace) => {
                 let terr = TypeError::RegionsPlaceholderMismatch;
                 self.report_and_explain_type_error(trace, &terr)
             }
diff --git a/src/librustc/infer/glb.rs b/src/librustc/infer/glb.rs
index 2cef521..10e4532 100644
--- a/src/librustc/infer/glb.rs
+++ b/src/librustc/infer/glb.rs
@@ -57,7 +57,7 @@
                a,
                b);
 
-        let origin = Subtype(self.fields.trace.clone());
+        let origin = Subtype(box self.fields.trace.clone());
         Ok(self.fields.infcx.borrow_region_constraints().glb_regions(self.tcx(), origin, a, b))
     }
 
diff --git a/src/librustc/infer/lub.rs b/src/librustc/infer/lub.rs
index e20372f..8b64cda 100644
--- a/src/librustc/infer/lub.rs
+++ b/src/librustc/infer/lub.rs
@@ -57,7 +57,7 @@
                a,
                b);
 
-        let origin = Subtype(self.fields.trace.clone());
+        let origin = Subtype(box self.fields.trace.clone());
         Ok(self.fields.infcx.borrow_region_constraints().lub_regions(self.tcx(), origin, a, b))
     }
 
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index 8638f42..a886c44 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -254,7 +254,7 @@
 #[derive(Clone, Debug)]
 pub enum SubregionOrigin<'tcx> {
     /// Arose from a subtyping relation
-    Subtype(TypeTrace<'tcx>),
+    Subtype(Box<TypeTrace<'tcx>>),
 
     /// Stack-allocated closures cannot outlive innermost loop
     /// or function so as to ensure we only require finite stack
@@ -340,6 +340,10 @@
     },
 }
 
+// `SubregionOrigin` is used a lot. Make sure it doesn't unintentionally get bigger.
+#[cfg(target_arch = "x86_64")]
+static_assert_size!(SubregionOrigin<'_>, 32);
+
 /// Places that type/region parameters can appear.
 #[derive(Clone, Copy, Debug)]
 pub enum ParameterOrigin {
diff --git a/src/librustc/infer/sub.rs b/src/librustc/infer/sub.rs
index cd1d206..76db55e 100644
--- a/src/librustc/infer/sub.rs
+++ b/src/librustc/infer/sub.rs
@@ -130,7 +130,7 @@
         // FIXME -- we have more fine-grained information available
         // from the "cause" field, we could perhaps give more tailored
         // error messages.
-        let origin = SubregionOrigin::Subtype(self.fields.trace.clone());
+        let origin = SubregionOrigin::Subtype(box self.fields.trace.clone());
         self.fields.infcx.borrow_region_constraints()
                          .make_subregion(origin, a, b);
 
diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs
index 09c822f..ac99ccd 100644
--- a/src/librustc/mir/interpret/error.rs
+++ b/src/librustc/mir/interpret/error.rs
@@ -213,6 +213,15 @@
     eprintln!("\n\nAn error occurred in miri:\n{:?}", backtrace);
 }
 
+impl From<ErrorHandled> for InterpErrorInfo<'tcx> {
+    fn from(err: ErrorHandled) -> Self {
+        match err {
+            ErrorHandled::Reported => err_inval!(ReferencedConstant),
+            ErrorHandled::TooGeneric => err_inval!(TooGeneric),
+        }.into()
+    }
+}
+
 impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
     fn from(kind: InterpError<'tcx>) -> Self {
         let backtrace = match env::var("RUSTC_CTFE_BACKTRACE") {
@@ -313,6 +322,9 @@
     }
 }
 
+/// Error information for when the program we executed turned out not to actually be a valid
+/// program. This cannot happen in stand-alone Miri, but it can happen during CTFE/ConstProp
+/// where we work on generic code or execution does not have all information available.
 #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
 pub enum InvalidProgramInfo<'tcx> {
     /// Resolution can fail if we are in a too generic context.
@@ -342,6 +354,7 @@
     }
 }
 
+/// Error information for when the program caused Undefined Behavior.
 #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
 pub enum UndefinedBehaviorInfo {
     /// Free-form case. Only for errors that are never caught!
@@ -364,12 +377,19 @@
     }
 }
 
+/// Error information for when the program did something that might (or might not) be correct
+/// to do according to the Rust spec, but due to limitations in the interpreter, the
+/// operation could not be carried out. These limitations can differ between CTFE and the
+/// Miri engine, e.g., CTFE does not support casting pointers to "real" integers.
+///
+/// Currently, we also use this as fall-back error kind for errors that have not been
+/// categorized yet.
 #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
 pub enum UnsupportedOpInfo<'tcx> {
     /// Free-form case. Only for errors that are never caught!
     Unsupported(String),
 
-    // -- Everything below is not classified yet --
+    // -- Everything below is not categorized yet --
     FunctionAbiMismatch(Abi, Abi),
     FunctionArgMismatch(Ty<'tcx>, Ty<'tcx>),
     FunctionRetMismatch(Ty<'tcx>, Ty<'tcx>),
@@ -536,6 +556,8 @@
     }
 }
 
+/// Error information for when the program exhausted the resources granted to it
+/// by the interpreter.
 #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
 pub enum ResourceExhaustionInfo {
     /// The stack grew too big.
diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs
index 4ebc2e7..c726094 100644
--- a/src/librustc/query/mod.rs
+++ b/src/librustc/query/mod.rs
@@ -462,15 +462,6 @@
             no_force
             desc { "extract field of const" }
         }
-
-        /// Produces an absolute path representation of the given type. See also the documentation
-        /// on `std::any::type_name`.
-        query type_name(key: Ty<'tcx>) -> &'tcx ty::Const<'tcx> {
-            eval_always
-            no_force
-            desc { "get absolute path of type" }
-        }
-
     }
 
     TypeChecking {
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index c74b2fe..723855c 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -7,6 +7,7 @@
 use crate::session::search_paths::SearchPath;
 
 use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::sync::Lrc;
 
 use rustc_target::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, RelroLevel};
 use rustc_target::spec::{Target, TargetTriple};
@@ -19,6 +20,7 @@
 use syntax::parse::token;
 use syntax::symbol::{sym, Symbol};
 use syntax::feature_gate::UnstableFeatures;
+use syntax::source_map::SourceMap;
 
 use errors::emitter::HumanReadableErrorType;
 use errors::{ColorConfig, FatalError, Handler};
@@ -1850,11 +1852,20 @@
     opts
 }
 
+struct NullEmitter;
+
+impl errors::emitter::Emitter for NullEmitter {
+    fn emit_diagnostic(&mut self, _: &errors::DiagnosticBuilder<'_>) {}
+}
+
 // Converts strings provided as `--cfg [cfgspec]` into a `crate_cfg`.
 pub fn parse_cfgspecs(cfgspecs: Vec<String>) -> FxHashSet<(String, Option<String>)> {
     syntax::with_default_globals(move || {
         let cfg = cfgspecs.into_iter().map(|s| {
-            let sess = ParseSess::new(FilePathMapping::empty());
+
+            let cm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
+            let handler = Handler::with_emitter(false, None, Box::new(NullEmitter));
+            let sess = ParseSess::with_span_handler(handler, cm);
             let filename = FileName::cfg_spec_source_code(&s);
             let mut parser = new_parser_from_source_str(&sess, filename, s.to_string());
 
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 25d921b..0155803 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -205,26 +205,24 @@
 fn validate_hir_id_for_typeck_tables(local_id_root: Option<DefId>,
                                      hir_id: hir::HirId,
                                      mut_access: bool) {
-    if cfg!(debug_assertions) {
-        if let Some(local_id_root) = local_id_root {
-            if hir_id.owner != local_id_root.index {
-                ty::tls::with(|tcx| {
-                    bug!("node {} with HirId::owner {:?} cannot be placed in \
-                          TypeckTables with local_id_root {:?}",
-                         tcx.hir().node_to_string(hir_id),
-                         DefId::local(hir_id.owner),
-                         local_id_root)
-                });
-            }
-        } else {
-            // We use "Null Object" TypeckTables in some of the analysis passes.
-            // These are just expected to be empty and their `local_id_root` is
-            // `None`. Therefore we cannot verify whether a given `HirId` would
-            // be a valid key for the given table. Instead we make sure that
-            // nobody tries to write to such a Null Object table.
-            if mut_access {
-                bug!("access to invalid TypeckTables")
-            }
+    if let Some(local_id_root) = local_id_root {
+        if hir_id.owner != local_id_root.index {
+            ty::tls::with(|tcx| {
+                bug!("node {} with HirId::owner {:?} cannot be placed in \
+                        TypeckTables with local_id_root {:?}",
+                        tcx.hir().node_to_string(hir_id),
+                        DefId::local(hir_id.owner),
+                        local_id_root)
+            });
+        }
+    } else {
+        // We use "Null Object" TypeckTables in some of the analysis passes.
+        // These are just expected to be empty and their `local_id_root` is
+        // `None`. Therefore we cannot verify whether a given `HirId` would
+        // be a valid key for the given table. Instead we make sure that
+        // nobody tries to write to such a Null Object table.
+        if mut_access {
+            bug!("access to invalid TypeckTables")
         }
     }
 }
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 41e4295..5ca819e 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -1938,9 +1938,15 @@
     pub vis: Visibility,
 }
 
-/// The definition of an abstract data type -- a struct or enum.
+/// The definition of a user-defined type, e.g., a `struct`, `enum`, or `union`.
 ///
 /// These are all interned (by `intern_adt_def`) into the `adt_defs` table.
+///
+/// The initialism *"Adt"* stands for an [*algebraic data type (ADT)*][adt].
+/// This is slightly wrong because `union`s are not ADTs.
+/// Moreover, Rust only allows recursive data types through indirection.
+///
+/// [adt]: https://en.wikipedia.org/wiki/Algebraic_data_type
 pub struct AdtDef {
     /// `DefId` of the struct, enum or union item.
     pub did: DefId,
@@ -2894,6 +2900,13 @@
     pub fn impls_are_allowed_to_overlap(self, def_id1: DefId, def_id2: DefId)
                                         -> Option<ImplOverlapKind>
     {
+        // If either trait impl references an error, they're allowed to overlap,
+        // as one of them essentially doesn't exist.
+        if self.impl_trait_ref(def_id1).map_or(false, |tr| tr.references_error()) ||
+            self.impl_trait_ref(def_id2).map_or(false, |tr| tr.references_error()) {
+            return Some(ImplOverlapKind::Permitted);
+        }
+
         let is_legit = if self.features().overlapping_marker_traits {
             let trait1_is_empty = self.impl_trait_ref(def_id1)
                 .map_or(false, |trait_ref| {
diff --git a/src/librustc_asan/build.rs b/src/librustc_asan/build.rs
index cc856ba..645707c 100644
--- a/src/librustc_asan/build.rs
+++ b/src/librustc_asan/build.rs
@@ -4,6 +4,7 @@
 use cmake::Config;
 
 fn main() {
+    println!("cargo:rerun-if-env-changed=RUSTC_BUILD_SANITIZERS");
     if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) {
         return;
     }
diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs
index 5fbfe91..3f3c5ac1 100644
--- a/src/librustc_codegen_llvm/intrinsic.rs
+++ b/src/librustc_codegen_llvm/intrinsic.rs
@@ -15,6 +15,7 @@
 use rustc_codegen_ssa::base::{to_immediate, wants_msvc_seh, compare_simd_types};
 use rustc::ty::{self, Ty};
 use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, Primitive};
+use rustc::mir::interpret::GlobalId;
 use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
 use rustc::hir;
 use syntax::ast::{self, FloatTy};
@@ -81,13 +82,14 @@
 impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
     fn codegen_intrinsic_call(
         &mut self,
-        callee_ty: Ty<'tcx>,
+        instance: ty::Instance<'tcx>,
         fn_ty: &FnType<'tcx, Ty<'tcx>>,
         args: &[OperandRef<'tcx, &'ll Value>],
         llresult: &'ll Value,
         span: Span,
     ) {
         let tcx = self.tcx;
+        let callee_ty = instance.ty(tcx);
 
         let (def_id, substs) = match callee_ty.sty {
             ty::FnDef(def_id, substs) => (def_id, substs),
@@ -133,10 +135,6 @@
                 let llfn = self.get_intrinsic(&("llvm.debugtrap"));
                 self.call(llfn, &[], None)
             }
-            "size_of" => {
-                let tp_ty = substs.type_at(0);
-                self.const_usize(self.size_of(tp_ty).bytes())
-            }
             "va_start" => {
                 self.va_start(args[0].immediate())
             }
@@ -188,10 +186,6 @@
                     self.const_usize(self.size_of(tp_ty).bytes())
                 }
             }
-            "min_align_of" => {
-                let tp_ty = substs.type_at(0);
-                self.const_usize(self.align_of(tp_ty).bytes())
-            }
             "min_align_of_val" => {
                 let tp_ty = substs.type_at(0);
                 if let OperandValue::Pair(_, meta) = args[0].val {
@@ -201,18 +195,19 @@
                     self.const_usize(self.align_of(tp_ty).bytes())
                 }
             }
-            "pref_align_of" => {
-                let tp_ty = substs.type_at(0);
-                self.const_usize(self.layout_of(tp_ty).align.pref.bytes())
-            }
+            "size_of" |
+            "pref_align_of" |
+            "min_align_of" |
+            "needs_drop" |
+            "type_id" |
             "type_name" => {
-                let tp_ty = substs.type_at(0);
-                let ty_name = self.tcx.type_name(tp_ty);
+                let gid = GlobalId {
+                    instance,
+                    promoted: None,
+                };
+                let ty_name = self.tcx.const_eval(ty::ParamEnv::reveal_all().and(gid)).unwrap();
                 OperandRef::from_const(self, ty_name).immediate_or_packed_pair(self)
             }
-            "type_id" => {
-                self.const_u64(self.tcx.type_id_hash(substs.type_at(0)))
-            }
             "init" => {
                 let ty = substs.type_at(0);
                 if !self.layout_of(ty).is_zst() {
@@ -235,11 +230,6 @@
             "uninit" | "forget" => {
                 return;
             }
-            "needs_drop" => {
-                let tp_ty = substs.type_at(0);
-
-                self.const_bool(self.type_needs_drop(tp_ty))
-            }
             "offset" => {
                 let ptr = args[0].immediate();
                 let offset = args[1].immediate();
diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs
index 9f2c303..34e39af 100644
--- a/src/librustc_codegen_llvm/lib.rs
+++ b/src/librustc_codegen_llvm/lib.rs
@@ -226,21 +226,21 @@
                 for &(name, _) in back::write::RELOC_MODEL_ARGS.iter() {
                     println!("    {}", name);
                 }
-                println!("");
+                println!();
             }
             PrintRequest::CodeModels => {
                 println!("Available code models:");
                 for &(name, _) in back::write::CODE_GEN_MODEL_ARGS.iter(){
                     println!("    {}", name);
                 }
-                println!("");
+                println!();
             }
             PrintRequest::TlsModels => {
                 println!("Available TLS models:");
                 for &(name, _) in back::write::TLS_MODEL_ARGS.iter(){
                     println!("    {}", name);
                 }
-                println!("");
+                println!();
             }
             req => llvm_util::print(req, sess),
         }
diff --git a/src/librustc_codegen_ssa/Cargo.toml b/src/librustc_codegen_ssa/Cargo.toml
index 89a6ec2..bc028d6 100644
--- a/src/librustc_codegen_ssa/Cargo.toml
+++ b/src/librustc_codegen_ssa/Cargo.toml
@@ -17,8 +17,8 @@
 log = "0.4.5"
 libc = "0.2.44"
 jobserver = "0.1.11"
-parking_lot = "0.7"
-tempfile = "3.0.5"
+parking_lot = "0.9"
+tempfile = "3.1"
 
 rustc_serialize = { path = "../libserialize", package = "serialize" }
 syntax = { path = "../libsyntax" }
diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index 8829a33..1bb0ea5 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -667,8 +667,7 @@
             }).collect();
 
 
-            let callee_ty = instance.as_ref().unwrap().ty(bx.tcx());
-            bx.codegen_intrinsic_call(callee_ty, &fn_ty, &args, dest,
+            bx.codegen_intrinsic_call(*instance.as_ref().unwrap(), &fn_ty, &args, dest,
                                       terminator.source_info.span);
 
             if let ReturnDest::IndirectOperand(dst, _) = ret_dest {
diff --git a/src/librustc_codegen_ssa/traits/intrinsic.rs b/src/librustc_codegen_ssa/traits/intrinsic.rs
index ede30a0..7c79cd6 100644
--- a/src/librustc_codegen_ssa/traits/intrinsic.rs
+++ b/src/librustc_codegen_ssa/traits/intrinsic.rs
@@ -1,6 +1,6 @@
 use super::BackendTypes;
 use crate::mir::operand::OperandRef;
-use rustc::ty::Ty;
+use rustc::ty::{self, Ty};
 use rustc_target::abi::call::FnType;
 use syntax_pos::Span;
 
@@ -10,7 +10,7 @@
     /// add them to librustc_codegen_llvm/context.rs
     fn codegen_intrinsic_call(
         &mut self,
-        callee_ty: Ty<'tcx>,
+        instance: ty::Instance<'tcx>,
         fn_ty: &FnType<'tcx, Ty<'tcx>>,
         args: &[OperandRef<'tcx, Self::Value>],
         llresult: Self::Value,
diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml
index 288676c..be9f79c 100644
--- a/src/librustc_data_structures/Cargo.toml
+++ b/src/librustc_data_structures/Cargo.toml
@@ -26,5 +26,5 @@
 smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }
 
 [dependencies.parking_lot]
-version = "0.7"
+version = "0.9"
 features = ["nightly"]
diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs
index 6f40d05..6e80b48 100644
--- a/src/librustc_data_structures/indexed_vec.rs
+++ b/src/librustc_data_structures/indexed_vec.rs
@@ -149,7 +149,7 @@
 
             #[inline]
             $v const unsafe fn from_u32_unchecked(value: u32) -> Self {
-                unsafe { $type { private: value } }
+                $type { private: value }
             }
 
             /// Extracts the value of this index as an integer.
diff --git a/src/librustc_data_structures/obligation_forest/graphviz.rs b/src/librustc_data_structures/obligation_forest/graphviz.rs
index a0363e1..b2120b1 100644
--- a/src/librustc_data_structures/obligation_forest/graphviz.rs
+++ b/src/librustc_data_structures/obligation_forest/graphviz.rs
@@ -74,9 +74,9 @@
             .flat_map(|i| {
                 let node = &self.nodes[i];
 
-                node.parent.iter().map(|p| p.get())
-                    .chain(node.dependents.iter().map(|p| p.get()))
-                    .map(move |p| (p, i))
+                node.parent.iter()
+                    .chain(node.dependents.iter())
+                    .map(move |p| (p.index(), i))
             })
             .collect()
     }
diff --git a/src/librustc_data_structures/obligation_forest/mod.rs b/src/librustc_data_structures/obligation_forest/mod.rs
index 6c52e62..189506b 100644
--- a/src/librustc_data_structures/obligation_forest/mod.rs
+++ b/src/librustc_data_structures/obligation_forest/mod.rs
@@ -9,7 +9,7 @@
 //! `ObligationForest` supports two main public operations (there are a
 //! few others not discussed here):
 //!
-//! 1. Add a new root obligations (`push_tree`).
+//! 1. Add a new root obligations (`register_obligation`).
 //! 2. Process the pending obligations (`process_obligations`).
 //!
 //! When a new obligation `N` is added, it becomes the root of an
@@ -20,13 +20,13 @@
 //! with every pending obligation (so that will include `N`, the first
 //! time). The callback also receives a (mutable) reference to the
 //! per-tree state `T`. The callback should process the obligation `O`
-//! that it is given and return one of three results:
+//! that it is given and return a `ProcessResult`:
 //!
-//! - `Ok(None)` -> ambiguous result. Obligation was neither a success
+//! - `Unchanged` -> ambiguous result. Obligation was neither a success
 //!   nor a failure. It is assumed that further attempts to process the
 //!   obligation will yield the same result unless something in the
 //!   surrounding environment changes.
-//! - `Ok(Some(C))` - the obligation was *shallowly successful*. The
+//! - `Changed(C)` - the obligation was *shallowly successful*. The
 //!   vector `C` is a list of subobligations. The meaning of this is that
 //!   `O` was successful on the assumption that all the obligations in `C`
 //!   are also successful. Therefore, `O` is only considered a "true"
@@ -34,7 +34,7 @@
 //!   state and the obligations in `C` become the new pending
 //!   obligations. They will be processed the next time you call
 //!   `process_obligations`.
-//! - `Err(E)` -> obligation failed with error `E`. We will collect this
+//! - `Error(E)` -> obligation failed with error `E`. We will collect this
 //!   error and return it from `process_obligations`, along with the
 //!   "backtrace" of obligations (that is, the list of obligations up to
 //!   and including the root of the failed obligation). No further
@@ -47,55 +47,50 @@
 //! - `completed`: a list of obligations where processing was fully
 //!   completed without error (meaning that all transitive subobligations
 //!   have also been completed). So, for example, if the callback from
-//!   `process_obligations` returns `Ok(Some(C))` for some obligation `O`,
+//!   `process_obligations` returns `Changed(C)` for some obligation `O`,
 //!   then `O` will be considered completed right away if `C` is the
 //!   empty vector. Otherwise it will only be considered completed once
 //!   all the obligations in `C` have been found completed.
 //! - `errors`: a list of errors that occurred and associated backtraces
 //!   at the time of error, which can be used to give context to the user.
 //! - `stalled`: if true, then none of the existing obligations were
-//!   *shallowly successful* (that is, no callback returned `Ok(Some(_))`).
+//!   *shallowly successful* (that is, no callback returned `Changed(_)`).
 //!   This implies that all obligations were either errors or returned an
 //!   ambiguous result, which means that any further calls to
 //!   `process_obligations` would simply yield back further ambiguous
 //!   results. This is used by the `FulfillmentContext` to decide when it
 //!   has reached a steady state.
 //!
-//! #### Snapshots
-//!
-//! The `ObligationForest` supports a limited form of snapshots; see
-//! `start_snapshot`, `commit_snapshot`, and `rollback_snapshot`. In
-//! particular, you can use a snapshot to roll back new root
-//! obligations. However, it is an error to attempt to
-//! `process_obligations` during a snapshot.
-//!
 //! ### Implementation details
 //!
 //! For the most part, comments specific to the implementation are in the
 //! code. This file only contains a very high-level overview. Basically,
 //! the forest is stored in a vector. Each element of the vector is a node
-//! in some tree. Each node in the vector has the index of an (optional)
-//! parent and (for convenience) its root (which may be itself). It also
-//! has a current state, described by `NodeState`. After each
-//! processing step, we compress the vector to remove completed and error
-//! nodes, which aren't needed anymore.
+//! in some tree. Each node in the vector has the index of its dependents,
+//! including the first dependent which is known as the parent. It also
+//! has a current state, described by `NodeState`. After each processing
+//! step, we compress the vector to remove completed and error nodes, which
+//! aren't needed anymore.
 
 use crate::fx::{FxHashMap, FxHashSet};
+use crate::indexed_vec::Idx;
+use crate::newtype_index;
 
-use std::cell::Cell;
+use std::cell::{Cell, RefCell};
 use std::collections::hash_map::Entry;
 use std::fmt::Debug;
 use std::hash;
 use std::marker::PhantomData;
 
-mod node_index;
-use self::node_index::NodeIndex;
-
 mod graphviz;
 
 #[cfg(test)]
 mod tests;
 
+newtype_index! {
+    pub struct NodeIndex { .. }
+}
+
 pub trait ForestObligation : Clone + Debug {
     type Predicate : Clone + hash::Hash + Eq + Debug;
 
@@ -148,18 +143,22 @@
     /// At the end of processing, those nodes will be removed by a
     /// call to `compress`.
     ///
-    /// At all times we maintain the invariant that every node appears
-    /// at a higher index than its parent. This is needed by the
-    /// backtrace iterator (which uses `split_at`).
+    /// Ideally, this would be an `IndexVec<NodeIndex, Node<O>>`. But that is
+    /// slower, because this vector is accessed so often that the
+    /// `u32`-to-`usize` conversions required for accesses are significant.
     nodes: Vec<Node<O>>,
 
     /// A cache of predicates that have been successfully completed.
     done_cache: FxHashSet<O::Predicate>,
 
-    /// An cache of the nodes in `nodes`, indexed by predicate.
+    /// A cache of the nodes in `nodes`, indexed by predicate. Unfortunately,
+    /// its contents are not guaranteed to match those of `nodes`. See the
+    /// comments in `process_obligation` for details.
     waiting_cache: FxHashMap<O::Predicate, NodeIndex>,
 
-    scratch: Option<Vec<usize>>,
+    /// A scratch vector reused in various operations, to avoid allocating new
+    /// vectors.
+    scratch: RefCell<Vec<usize>>,
 
     obligation_tree_id_generator: ObligationTreeIdGenerator,
 
@@ -178,19 +177,41 @@
     obligation: O,
     state: Cell<NodeState>,
 
-    /// The parent of a node - the original obligation of
-    /// which it is a subobligation. Except for error reporting,
-    /// it is just like any member of `dependents`.
+    /// The parent of a node - the original obligation of which it is a
+    /// subobligation. Except for error reporting, it is just like any member
+    /// of `dependents`.
+    ///
+    /// Unlike `ObligationForest::nodes`, this uses `NodeIndex` rather than
+    /// `usize` for the index, because keeping the size down is more important
+    /// than the cost of converting to a `usize` for indexing.
     parent: Option<NodeIndex>,
 
-    /// Obligations that depend on this obligation for their
-    /// completion. They must all be in a non-pending state.
+    /// Obligations that depend on this obligation for their completion. They
+    /// must all be in a non-pending state.
+    ///
+    /// This uses `NodeIndex` for the same reason as `parent`.
     dependents: Vec<NodeIndex>,
 
     /// Identifier of the obligation tree to which this node belongs.
     obligation_tree_id: ObligationTreeId,
 }
 
+impl<O> Node<O> {
+    fn new(
+        parent: Option<NodeIndex>,
+        obligation: O,
+        obligation_tree_id: ObligationTreeId
+    ) -> Node<O> {
+        Node {
+            obligation,
+            state: Cell::new(NodeState::Pending),
+            parent,
+            dependents: vec![],
+            obligation_tree_id,
+        }
+    }
+}
+
 /// The state of one node in some tree within the forest. This
 /// represents the current state of processing for the obligation (of
 /// type `O`) associated with this node.
@@ -262,7 +283,7 @@
             nodes: vec![],
             done_cache: Default::default(),
             waiting_cache: Default::default(),
-            scratch: Some(vec![]),
+            scratch: RefCell::new(vec![]),
             obligation_tree_id_generator: (0..).map(ObligationTreeId),
             error_cache: Default::default(),
         }
@@ -275,14 +296,12 @@
     }
 
     /// Registers an obligation.
-    ///
-    /// This CAN be done in a snapshot
     pub fn register_obligation(&mut self, obligation: O) {
         // Ignore errors here - there is no guarantee of success.
         let _ = self.register_obligation_at(obligation, None);
     }
 
-    // returns Err(()) if we already know this obligation failed.
+    // Returns Err(()) if we already know this obligation failed.
     fn register_obligation_at(&mut self, obligation: O, parent: Option<NodeIndex>)
                               -> Result<(), ()>
     {
@@ -294,15 +313,16 @@
             Entry::Occupied(o) => {
                 debug!("register_obligation_at({:?}, {:?}) - duplicate of {:?}!",
                        obligation, parent, o.get());
-                let node = &mut self.nodes[o.get().get()];
-                if let Some(parent) = parent {
+                let node = &mut self.nodes[o.get().index()];
+                if let Some(parent_index) = parent {
                     // If the node is already in `waiting_cache`, it's already
                     // been marked with a parent. (It's possible that parent
                     // has been cleared by `apply_rewrites`, though.) So just
                     // dump `parent` into `node.dependents`... unless it's
                     // already in `node.dependents` or `node.parent`.
-                    if !node.dependents.contains(&parent) && Some(parent) != node.parent {
-                        node.dependents.push(parent);
+                    if !node.dependents.contains(&parent_index) &&
+                       Some(parent_index) != node.parent {
+                        node.dependents.push(parent_index);
                     }
                 }
                 if let NodeState::Error = node.state.get() {
@@ -316,9 +336,8 @@
                        obligation, parent, self.nodes.len());
 
                 let obligation_tree_id = match parent {
-                    Some(p) => {
-                        let parent_node = &self.nodes[p.get()];
-                        parent_node.obligation_tree_id
+                    Some(parent_index) => {
+                        self.nodes[parent_index.index()].obligation_tree_id
                     }
                     None => self.obligation_tree_id_generator.next().unwrap()
                 };
@@ -342,13 +361,11 @@
     }
 
     /// Converts all remaining obligations to the given error.
-    ///
-    /// This cannot be done during a snapshot.
     pub fn to_errors<E: Clone>(&mut self, error: E) -> Vec<Error<O, E>> {
         let mut errors = vec![];
-        for index in 0..self.nodes.len() {
-            if let NodeState::Pending = self.nodes[index].state.get() {
-                let backtrace = self.error_at(index);
+        for (i, node) in self.nodes.iter().enumerate() {
+            if let NodeState::Pending = node.state.get() {
+                let backtrace = self.error_at(i);
                 errors.push(Error {
                     error: error.clone(),
                     backtrace,
@@ -373,7 +390,6 @@
 
     fn insert_into_error_cache(&mut self, node_index: usize) {
         let node = &self.nodes[node_index];
-
         self.error_cache
             .entry(node.obligation_tree_id)
             .or_default()
@@ -393,16 +409,22 @@
         let mut errors = vec![];
         let mut stalled = true;
 
-        for index in 0..self.nodes.len() {
-            debug!("process_obligations: node {} == {:?}", index, self.nodes[index]);
+        for i in 0..self.nodes.len() {
+            let node = &mut self.nodes[i];
 
-            let result = match self.nodes[index] {
-                Node { ref state, ref mut obligation, .. } if state.get() == NodeState::Pending =>
-                    processor.process_obligation(obligation),
+            debug!("process_obligations: node {} == {:?}", i, node);
+
+            // `processor.process_obligation` can modify the predicate within
+            // `node.obligation`, and that predicate is the key used for
+            // `self.waiting_cache`. This means that `self.waiting_cache` can
+            // get out of sync with `nodes`. It's not very common, but it does
+            // happen, and code in `compress` has to allow for it.
+            let result = match node.state.get() {
+                NodeState::Pending => processor.process_obligation(&mut node.obligation),
                 _ => continue
             };
 
-            debug!("process_obligations: node {} got result {:?}", index, result);
+            debug!("process_obligations: node {} got result {:?}", i, result);
 
             match result {
                 ProcessResult::Unchanged => {
@@ -411,23 +433,23 @@
                 ProcessResult::Changed(children) => {
                     // We are not (yet) stalled.
                     stalled = false;
-                    self.nodes[index].state.set(NodeState::Success);
+                    node.state.set(NodeState::Success);
 
                     for child in children {
                         let st = self.register_obligation_at(
                             child,
-                            Some(NodeIndex::new(index))
+                            Some(NodeIndex::new(i))
                         );
                         if let Err(()) = st {
-                            // error already reported - propagate it
+                            // Error already reported - propagate it
                             // to our node.
-                            self.error_at(index);
+                            self.error_at(i);
                         }
                     }
                 }
                 ProcessResult::Error(err) => {
                     stalled = false;
-                    let backtrace = self.error_at(index);
+                    let backtrace = self.error_at(i);
                     errors.push(Error {
                         error: err,
                         backtrace,
@@ -448,8 +470,6 @@
 
         self.mark_as_waiting();
         self.process_cycles(processor);
-
-        // Now we have to compress the result
         let completed = self.compress(do_completed);
 
         debug!("process_obligations: complete");
@@ -465,97 +485,92 @@
     /// report all cycles between them. This should be called
     /// after `mark_as_waiting` marks all nodes with pending
     /// subobligations as NodeState::Waiting.
-    fn process_cycles<P>(&mut self, processor: &mut P)
+    fn process_cycles<P>(&self, processor: &mut P)
         where P: ObligationProcessor<Obligation=O>
     {
-        let mut stack = self.scratch.take().unwrap();
+        let mut stack = self.scratch.replace(vec![]);
         debug_assert!(stack.is_empty());
 
         debug!("process_cycles()");
 
-        for index in 0..self.nodes.len() {
+        for (i, node) in self.nodes.iter().enumerate() {
             // For rustc-benchmarks/inflate-0.1.0 this state test is extremely
             // hot and the state is almost always `Pending` or `Waiting`. It's
             // a win to handle the no-op cases immediately to avoid the cost of
             // the function call.
-            let state = self.nodes[index].state.get();
-            match state {
+            match node.state.get() {
                 NodeState::Waiting | NodeState::Pending | NodeState::Done | NodeState::Error => {},
-                _ => self.find_cycles_from_node(&mut stack, processor, index),
+                _ => self.find_cycles_from_node(&mut stack, processor, i),
             }
         }
 
         debug!("process_cycles: complete");
 
         debug_assert!(stack.is_empty());
-        self.scratch = Some(stack);
+        self.scratch.replace(stack);
     }
 
-    fn find_cycles_from_node<P>(&self, stack: &mut Vec<usize>,
-                                processor: &mut P, index: usize)
+    fn find_cycles_from_node<P>(&self, stack: &mut Vec<usize>, processor: &mut P, i: usize)
         where P: ObligationProcessor<Obligation=O>
     {
-        let node = &self.nodes[index];
-        let state = node.state.get();
-        match state {
+        let node = &self.nodes[i];
+        match node.state.get() {
             NodeState::OnDfsStack => {
-                let index =
-                    stack.iter().rposition(|n| *n == index).unwrap();
-                processor.process_backedge(stack[index..].iter().map(GetObligation(&self.nodes)),
+                let i = stack.iter().rposition(|n| *n == i).unwrap();
+                processor.process_backedge(stack[i..].iter().map(GetObligation(&self.nodes)),
                                            PhantomData);
             }
             NodeState::Success => {
                 node.state.set(NodeState::OnDfsStack);
-                stack.push(index);
-                for dependent in node.parent.iter().chain(node.dependents.iter()) {
-                    self.find_cycles_from_node(stack, processor, dependent.get());
+                stack.push(i);
+                for index in node.parent.iter().chain(node.dependents.iter()) {
+                    self.find_cycles_from_node(stack, processor, index.index());
                 }
                 stack.pop();
                 node.state.set(NodeState::Done);
             },
             NodeState::Waiting | NodeState::Pending => {
-                // this node is still reachable from some pending node. We
+                // This node is still reachable from some pending node. We
                 // will get to it when they are all processed.
             }
             NodeState::Done | NodeState::Error => {
-                // already processed that node
+                // Already processed that node.
             }
         };
     }
 
     /// Returns a vector of obligations for `p` and all of its
     /// ancestors, putting them into the error state in the process.
-    fn error_at(&mut self, p: usize) -> Vec<O> {
-        let mut error_stack = self.scratch.take().unwrap();
+    fn error_at(&self, mut i: usize) -> Vec<O> {
+        let mut error_stack = self.scratch.replace(vec![]);
         let mut trace = vec![];
 
-        let mut n = p;
         loop {
-            self.nodes[n].state.set(NodeState::Error);
-            trace.push(self.nodes[n].obligation.clone());
-            error_stack.extend(self.nodes[n].dependents.iter().map(|x| x.get()));
+            let node = &self.nodes[i];
+            node.state.set(NodeState::Error);
+            trace.push(node.obligation.clone());
+            error_stack.extend(node.dependents.iter().map(|index| index.index()));
 
-            // loop to the parent
-            match self.nodes[n].parent {
-                Some(q) => n = q.get(),
+            // Loop to the parent.
+            match node.parent {
+                Some(parent_index) => i = parent_index.index(),
                 None => break
             }
         }
 
         while let Some(i) = error_stack.pop() {
-            match self.nodes[i].state.get() {
+            let node = &self.nodes[i];
+            match node.state.get() {
                 NodeState::Error => continue,
-                _ => self.nodes[i].state.set(NodeState::Error),
+                _ => node.state.set(NodeState::Error),
             }
 
-            let node = &self.nodes[i];
-
             error_stack.extend(
-                node.parent.iter().chain(node.dependents.iter()).map(|x| x.get())
+                node.parent.iter().chain(node.dependents.iter()).map(|index| index.index())
             );
         }
 
-        self.scratch = Some(error_stack);
+        self.scratch.replace(error_stack);
         trace
     }
 
@@ -563,7 +578,7 @@
     #[inline(always)]
     fn inlined_mark_neighbors_as_waiting_from(&self, node: &Node<O>) {
         for dependent in node.parent.iter().chain(node.dependents.iter()) {
-            self.mark_as_waiting_from(&self.nodes[dependent.get()]);
+            self.mark_as_waiting_from(&self.nodes[dependent.index()]);
         }
     }
 
@@ -609,7 +624,7 @@
     #[inline(never)]
     fn compress(&mut self, do_completed: DoCompleted) -> Option<Vec<O>> {
         let nodes_len = self.nodes.len();
-        let mut node_rewrites: Vec<_> = self.scratch.take().unwrap();
+        let mut node_rewrites: Vec<_> = self.scratch.replace(vec![]);
         node_rewrites.extend(0..nodes_len);
         let mut dead_nodes = 0;
 
@@ -620,7 +635,8 @@
         //     self.nodes[i - dead_nodes..i] are all dead
         //     self.nodes[i..] are unchanged
         for i in 0..self.nodes.len() {
-            match self.nodes[i].state.get() {
+            let node = &self.nodes[i];
+            match node.state.get() {
                 NodeState::Pending | NodeState::Waiting => {
                     if dead_nodes > 0 {
                         self.nodes.swap(i, i - dead_nodes);
@@ -628,13 +644,16 @@
                     }
                 }
                 NodeState::Done => {
-                    // Avoid cloning the key (predicate) in case it exists in the waiting cache
+                    // This lookup can fail because the contents of
+                    // `self.waiting_cache` is not guaranteed to match those of
+                    // `self.nodes`. See the comment in `process_obligation`
+                    // for more details.
                     if let Some((predicate, _)) = self.waiting_cache
-                        .remove_entry(self.nodes[i].obligation.as_predicate())
+                        .remove_entry(node.obligation.as_predicate())
                     {
                         self.done_cache.insert(predicate);
                     } else {
-                        self.done_cache.insert(self.nodes[i].obligation.as_predicate().clone());
+                        self.done_cache.insert(node.obligation.as_predicate().clone());
                     }
                     node_rewrites[i] = nodes_len;
                     dead_nodes += 1;
@@ -643,7 +662,7 @@
                     // We *intentionally* remove the node from the cache at this point. Otherwise
                     // tests must come up with a different type on every type error they
                     // check against.
-                    self.waiting_cache.remove(self.nodes[i].obligation.as_predicate());
+                    self.waiting_cache.remove(node.obligation.as_predicate());
                     node_rewrites[i] = nodes_len;
                     dead_nodes += 1;
                     self.insert_into_error_cache(i);
@@ -655,12 +674,11 @@
         // No compression needed.
         if dead_nodes == 0 {
             node_rewrites.truncate(0);
-            self.scratch = Some(node_rewrites);
+            self.scratch.replace(node_rewrites);
             return if do_completed == DoCompleted::Yes { Some(vec![]) } else { None };
         }
 
-        // Pop off all the nodes we killed and extract the success
-        // stories.
+        // Pop off all the nodes we killed and extract the success stories.
         let successful = if do_completed == DoCompleted::Yes {
             Some((0..dead_nodes)
                 .map(|_| self.nodes.pop().unwrap())
@@ -679,7 +697,7 @@
         self.apply_rewrites(&node_rewrites);
 
         node_rewrites.truncate(0);
-        self.scratch = Some(node_rewrites);
+        self.scratch.replace(node_rewrites);
 
         successful
     }
@@ -689,58 +707,41 @@
 
         for node in &mut self.nodes {
             if let Some(index) = node.parent {
-                let new_index = node_rewrites[index.get()];
-                if new_index >= nodes_len {
-                    // parent dead due to error
+                let new_i = node_rewrites[index.index()];
+                if new_i >= nodes_len {
                     node.parent = None;
                 } else {
-                    node.parent = Some(NodeIndex::new(new_index));
+                    node.parent = Some(NodeIndex::new(new_i));
                 }
             }
 
             let mut i = 0;
             while i < node.dependents.len() {
-                let new_index = node_rewrites[node.dependents[i].get()];
-                if new_index >= nodes_len {
+                let new_i = node_rewrites[node.dependents[i].index()];
+                if new_i >= nodes_len {
                     node.dependents.swap_remove(i);
                 } else {
-                    node.dependents[i] = NodeIndex::new(new_index);
+                    node.dependents[i] = NodeIndex::new(new_i);
                     i += 1;
                 }
             }
         }
 
-        let mut kill_list = vec![];
-        for (predicate, index) in &mut self.waiting_cache {
-            let new_index = node_rewrites[index.get()];
-            if new_index >= nodes_len {
-                kill_list.push(predicate.clone());
+        // This updating of `self.waiting_cache` is necessary because the
+        // removal of nodes within `compress` can fail. See above.
+        self.waiting_cache.retain(|_predicate, index| {
+            let new_i = node_rewrites[index.index()];
+            if new_i >= nodes_len {
+                false
             } else {
-                *index = NodeIndex::new(new_index);
+                *index = NodeIndex::new(new_i);
+                true
             }
-        }
-
-        for predicate in kill_list { self.waiting_cache.remove(&predicate); }
+        });
     }
 }
 
-impl<O> Node<O> {
-    fn new(
-        parent: Option<NodeIndex>,
-        obligation: O,
-        obligation_tree_id: ObligationTreeId
-    ) -> Node<O> {
-        Node {
-            obligation,
-            state: Cell::new(NodeState::Pending),
-            parent,
-            dependents: vec![],
-            obligation_tree_id,
-        }
-    }
-}
-
-// I need a Clone closure
+// I need a Clone closure.
 #[derive(Clone)]
 struct GetObligation<'a, O>(&'a [Node<O>]);
 
diff --git a/src/librustc_data_structures/obligation_forest/node_index.rs b/src/librustc_data_structures/obligation_forest/node_index.rs
deleted file mode 100644
index 69ea473..0000000
--- a/src/librustc_data_structures/obligation_forest/node_index.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-use std::num::NonZeroU32;
-use std::u32;
-
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub struct NodeIndex {
-    index: NonZeroU32,
-}
-
-impl NodeIndex {
-    #[inline]
-    pub fn new(value: usize) -> NodeIndex {
-        assert!(value < (u32::MAX as usize));
-        NodeIndex { index: NonZeroU32::new((value as u32) + 1).unwrap() }
-    }
-
-    #[inline]
-    pub fn get(self) -> usize {
-        (self.index.get() - 1) as usize
-    }
-}
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 005cdcf..8c5d853 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -134,8 +134,11 @@
 
 impl Callbacks for TimePassesCallbacks {
     fn config(&mut self, config: &mut interface::Config) {
+        // If a --prints=... option has been given, we don't print the "total"
+        // time because it will mess up the --prints output. See #64339.
         self.time_passes =
-            config.opts.debugging_opts.time_passes || config.opts.debugging_opts.time;
+            config.opts.prints.is_empty() &&
+            (config.opts.debugging_opts.time_passes || config.opts.debugging_opts.time);
     }
 }
 
diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs
index 6660836..d238de2 100644
--- a/src/librustc_errors/emitter.rs
+++ b/src/librustc_errors/emitter.rs
@@ -1144,15 +1144,18 @@
                 buffer.prepend(0, " ", Style::NoStyle);
             }
             draw_note_separator(&mut buffer, 0, max_line_num_len + 1);
-            let level_str = level.to_string();
-            if !level_str.is_empty() {
-                buffer.append(0, &level_str, Style::MainHeaderMsg);
-                buffer.append(0, ": ", Style::NoStyle);
+            if *level != Level::FailureNote {
+                let level_str = level.to_string();
+                if !level_str.is_empty() {
+                    buffer.append(0, &level_str, Style::MainHeaderMsg);
+                    buffer.append(0, ": ", Style::NoStyle);
+                }
             }
             self.msg_to_buffer(&mut buffer, msg, max_line_num_len, "note", None);
         } else {
             let level_str = level.to_string();
-            if !level_str.is_empty() {
+            // The failure note level itself does not provide any useful diagnostic information
+            if *level != Level::FailureNote && !level_str.is_empty() {
                 buffer.append(0, &level_str, Style::Level(level.clone()));
             }
             // only render error codes, not lint codes
@@ -1161,7 +1164,7 @@
                 buffer.append(0, &code, Style::Level(level.clone()));
                 buffer.append(0, "]", Style::Level(level.clone()));
             }
-            if !level_str.is_empty() {
+            if *level != Level::FailureNote && !level_str.is_empty() {
                 buffer.append(0, ": ", header_style);
             }
             for &(ref text, _) in msg.iter() {
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index c1fba41..8b543be 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -833,7 +833,7 @@
             Warning => "warning",
             Note => "note",
             Help => "help",
-            FailureNote => "",
+            FailureNote => "failure-note",
             Cancelled => panic!("Shouldn't call on cancelled error"),
         }
     }
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index 561bf20..c397509 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -370,7 +370,8 @@
                                      right_pos: Option<BytePos>) {
         match value.node {
             ast::ExprKind::Paren(ref inner) => {
-                if !Self::is_expr_parens_necessary(inner, followed_by_block) {
+                if !Self::is_expr_parens_necessary(inner, followed_by_block) &&
+                    value.attrs.is_empty() {
                     let expr_text = if let Ok(snippet) = cx.sess().source_map()
                         .span_to_snippet(value.span) {
                             snippet
@@ -618,24 +619,19 @@
             }
 
             // Trigger the lint if the nested item is a non-self single item
-            let node_ident;
-            match items[0].0.kind {
+            let node_name = match items[0].0.kind {
                 ast::UseTreeKind::Simple(rename, ..) => {
                     let orig_ident = items[0].0.prefix.segments.last().unwrap().ident;
                     if orig_ident.name == kw::SelfLower {
                         return;
                     }
-                    node_ident = rename.unwrap_or(orig_ident);
+                    rename.unwrap_or(orig_ident).name
                 }
-                ast::UseTreeKind::Glob => {
-                    node_ident = ast::Ident::from_str("*");
-                }
-                ast::UseTreeKind::Nested(_) => {
-                    return;
-                }
-            }
+                ast::UseTreeKind::Glob => Symbol::intern("*"),
+                ast::UseTreeKind::Nested(_) => return,
+            };
 
-            let msg = format!("braces around {} is unnecessary", node_ident.name);
+            let msg = format!("braces around {} is unnecessary", node_name);
             cx.span_lint(UNUSED_IMPORT_BRACES, item.span, &msg);
         }
     }
diff --git a/src/librustc_lsan/build.rs b/src/librustc_lsan/build.rs
index d5f3e37..73720d8 100644
--- a/src/librustc_lsan/build.rs
+++ b/src/librustc_lsan/build.rs
@@ -4,6 +4,7 @@
 use cmake::Config;
 
 fn main() {
+    println!("cargo:rerun-if-env-changed=RUSTC_BUILD_SANITIZERS");
     if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) {
         return;
     }
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index d6450f0..a1e3bbc 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -444,7 +444,8 @@
             .insert(local_span, (name.to_string(), data.get_span(id.index, sess)));
 
         LoadedMacro::MacroDef(ast::Item {
-            ident: ast::Ident::from_str(&name.as_str()),
+            // FIXME: cross-crate hygiene
+            ident: ast::Ident::with_dummy_span(name.as_symbol()),
             id: ast::DUMMY_NODE_ID,
             span: local_span,
             attrs: attrs.iter().cloned().collect(),
diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml
index e027360..0691390 100644
--- a/src/librustc_mir/Cargo.toml
+++ b/src/librustc_mir/Cargo.toml
@@ -24,6 +24,6 @@
 rustc_serialize = { path = "../libserialize", package = "serialize" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
-byteorder = { version = "1.1", features = ["i128"] }
+byteorder = { version = "1.3" }
 rustc_apfloat = { path = "../librustc_apfloat" }
 smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }
diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/conflict_errors.rs
index 4b4516d..81359c6 100644
--- a/src/librustc_mir/borrow_check/conflict_errors.rs
+++ b/src/librustc_mir/borrow_check/conflict_errors.rs
@@ -614,8 +614,9 @@
                     projection,
                 } = first_borrowed_place;
 
-                for (i, elem) in projection.iter().enumerate().rev() {
-                    let proj_base = &projection[..i];
+                let mut cursor = &**projection;
+                while let [proj_base @ .., elem] = cursor {
+                    cursor = proj_base;
 
                     match elem {
                         ProjectionElem::Field(field, _) if union_ty(base, proj_base).is_some() => {
@@ -637,8 +638,9 @@
                     projection,
                 } = second_borrowed_place;
 
-                for (i, elem) in projection.iter().enumerate().rev() {
-                    let proj_base = &projection[..i];
+                let mut cursor = &**projection;
+                while let [proj_base @ .., elem] = cursor {
+                    cursor = proj_base;
 
                     if let ProjectionElem::Field(field, _) = elem {
                         if let Some(union_ty) = union_ty(base, proj_base) {
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 5ef7046..1d35762 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -1758,7 +1758,10 @@
         debug!("check_if_assigned_path_is_moved place: {:?}", place);
 
         // None case => assigning to `x` does not require `x` be initialized.
-        for (i, elem) in place.projection.iter().enumerate().rev() {
+        let mut cursor = &*place.projection;
+        while let [proj_base @ .., elem] = cursor {
+            cursor = proj_base;
+
             match elem {
                 ProjectionElem::Index(_/*operand*/) |
                 ProjectionElem::ConstantIndex { .. } |
@@ -1771,8 +1774,6 @@
 
                 // assigning to (*P) requires P to be initialized
                 ProjectionElem::Deref => {
-                    let proj_base = &place.projection[..i];
-
                     self.check_if_full_path_is_moved(
                         location, InitializationRequiringAction::Use,
                         (PlaceRef {
@@ -1790,7 +1791,6 @@
                 }
 
                 ProjectionElem::Field(..) => {
-                    let proj_base = &place.projection[..i];
                     // if type of `P` has a dtor, then
                     // assigning to `P.f` requires `P` itself
                     // be already initialized
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
index efa1858..26a89b4 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
@@ -13,7 +13,7 @@
 use rustc::mir::{ConstraintCategory, Location, Body};
 use rustc::ty::{self, RegionVid};
 use rustc_data_structures::indexed_vec::IndexVec;
-use rustc_errors::{Diagnostic, DiagnosticBuilder};
+use rustc_errors::DiagnosticBuilder;
 use std::collections::VecDeque;
 use syntax::errors::Applicability;
 use syntax::symbol::kw;
@@ -22,7 +22,7 @@
 mod region_name;
 mod var_name;
 
-crate use self::region_name::{RegionName, RegionNameSource};
+crate use self::region_name::{RegionName, RegionNameSource, RegionErrorNamingCtx};
 
 impl ConstraintDescription for ConstraintCategory {
     fn description(&self) -> &'static str {
@@ -54,6 +54,39 @@
     NotVisited,
 }
 
+/// Various pieces of state used when reporting borrow checker errors.
+pub struct ErrorReportingCtx<'a, 'b, 'tcx> {
+    /// The region inference context used for borrow chekcing this MIR body.
+    #[allow(dead_code)] // FIXME(mark-i-m): used by outlives suggestions
+    region_infcx: &'b RegionInferenceContext<'tcx>,
+
+    /// The inference context used for type checking.
+    infcx: &'b InferCtxt<'a, 'tcx>,
+
+    /// The MIR def we are reporting errors on.
+    mir_def_id: DefId,
+
+    /// The MIR body we are reporting errors on (for convenience).
+    body: &'b Body<'tcx>,
+
+    /// Any upvars for the MIR body we have kept track of during borrow checking.
+    upvars: &'b [Upvar],
+}
+
+/// Information about the various region constraints involved in a borrow checker error.
+#[derive(Clone, Debug)]
+pub struct ErrorConstraintInfo {
+    // fr: outlived_fr
+    fr: RegionVid,
+    fr_is_local: bool,
+    outlived_fr: RegionVid,
+    outlived_fr_is_local: bool,
+
+    // Category and span for best blame constraint
+    category: ConstraintCategory,
+    span: Span,
+}
+
 impl<'tcx> RegionInferenceContext<'tcx> {
     /// Tries to find the best constraint to blame for the fact that
     /// `R: from_region`, where `R` is some region that meets
@@ -257,16 +290,16 @@
     /// ```
     ///
     /// Here we would be invoked with `fr = 'a` and `outlived_fr = `'b`.
-    pub(super) fn report_error(
-        &self,
+    pub(super) fn report_error<'a>(
+        &'a self,
         body: &Body<'tcx>,
         upvars: &[Upvar],
-        infcx: &InferCtxt<'_, 'tcx>,
+        infcx: &'a InferCtxt<'a, 'tcx>,
         mir_def_id: DefId,
         fr: RegionVid,
         outlived_fr: RegionVid,
-        errors_buffer: &mut Vec<Diagnostic>,
-    ) {
+        renctx: &mut RegionErrorNamingCtx,
+    ) -> DiagnosticBuilder<'a> {
         debug!("report_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr);
 
         let (category, _, span) = self.best_blame_constraint(body, fr, |r| {
@@ -279,8 +312,7 @@
             let tables = infcx.tcx.typeck_tables_of(mir_def_id);
             let nice = NiceRegionError::new_from_span(infcx, span, o, f, Some(tables));
             if let Some(diag) = nice.try_report_from_nll() {
-                diag.buffer(errors_buffer);
-                return;
+                return diag;
             }
         }
 
@@ -293,45 +325,28 @@
             "report_error: fr_is_local={:?} outlived_fr_is_local={:?} category={:?}",
             fr_is_local, outlived_fr_is_local, category
         );
+
+        let errctx = ErrorReportingCtx {
+            region_infcx: self,
+            infcx,
+            mir_def_id,
+            body,
+            upvars,
+        };
+
+        let errci = ErrorConstraintInfo {
+            fr, outlived_fr, fr_is_local, outlived_fr_is_local, category, span
+        };
+
         match (category, fr_is_local, outlived_fr_is_local) {
             (ConstraintCategory::Return, true, false) if self.is_closure_fn_mut(infcx, fr) => {
-                self.report_fnmut_error(
-                    body,
-                    upvars,
-                    infcx,
-                    mir_def_id,
-                    fr,
-                    outlived_fr,
-                    span,
-                    errors_buffer,
-                )
+                self.report_fnmut_error(&errctx, &errci, renctx)
             }
             (ConstraintCategory::Assignment, true, false)
-            | (ConstraintCategory::CallArgument, true, false) => self.report_escaping_data_error(
-                body,
-                upvars,
-                infcx,
-                mir_def_id,
-                fr,
-                outlived_fr,
-                category,
-                span,
-                errors_buffer,
-            ),
-            _ => self.report_general_error(
-                body,
-                upvars,
-                infcx,
-                mir_def_id,
-                fr,
-                fr_is_local,
-                outlived_fr,
-                outlived_fr_is_local,
-                category,
-                span,
-                errors_buffer,
-            ),
-        };
+            | (ConstraintCategory::CallArgument, true, false) =>
+                self.report_escaping_data_error(&errctx, &errci, renctx),
+            _ => self.report_general_error(&errctx, &errci, renctx),
+        }
     }
 
     /// We have a constraint `fr1: fr2` that is not satisfied, where
@@ -379,19 +394,19 @@
     /// ```
     fn report_fnmut_error(
         &self,
-        body: &Body<'tcx>,
-        upvars: &[Upvar],
-        infcx: &InferCtxt<'_, 'tcx>,
-        mir_def_id: DefId,
-        _fr: RegionVid,
-        outlived_fr: RegionVid,
-        span: Span,
-        errors_buffer: &mut Vec<Diagnostic>,
-    ) {
-        let mut diag = infcx
+        errctx: &ErrorReportingCtx<'_, '_, 'tcx>,
+        errci: &ErrorConstraintInfo,
+        renctx: &mut RegionErrorNamingCtx,
+    ) -> DiagnosticBuilder<'_> {
+        let ErrorConstraintInfo {
+            outlived_fr, span, ..
+        } = errci;
+
+        let mut diag = errctx
+            .infcx
             .tcx
             .sess
-            .struct_span_err(span, "captured variable cannot escape `FnMut` closure body");
+            .struct_span_err(*span, "captured variable cannot escape `FnMut` closure body");
 
         // We should check if the return type of this closure is in fact a closure - in that
         // case, we can special case the error further.
@@ -403,11 +418,9 @@
             "returns a reference to a captured variable which escapes the closure body"
         };
 
-        diag.span_label(span, message);
+        diag.span_label(*span, message);
 
-        match self.give_region_a_name(infcx, body, upvars, mir_def_id, outlived_fr, &mut 1)
-            .unwrap().source
-        {
+        match self.give_region_a_name(errctx, renctx, *outlived_fr).unwrap().source {
             RegionNameSource::NamedEarlyBoundRegion(fr_span)
             | RegionNameSource::NamedFreeRegion(fr_span)
             | RegionNameSource::SynthesizedFreeEnvRegion(fr_span, _)
@@ -427,7 +440,7 @@
         );
         diag.note("...therefore, they cannot allow references to captured variables to escape");
 
-        diag.buffer(errors_buffer);
+        diag
     }
 
     /// Reports a error specifically for when data is escaping a closure.
@@ -444,20 +457,22 @@
     /// ```
     fn report_escaping_data_error(
         &self,
-        body: &Body<'tcx>,
-        upvars: &[Upvar],
-        infcx: &InferCtxt<'_, 'tcx>,
-        mir_def_id: DefId,
-        fr: RegionVid,
-        outlived_fr: RegionVid,
-        category: ConstraintCategory,
-        span: Span,
-        errors_buffer: &mut Vec<Diagnostic>,
-    ) {
+        errctx: &ErrorReportingCtx<'_, '_, 'tcx>,
+        errci: &ErrorConstraintInfo,
+        renctx: &mut RegionErrorNamingCtx,
+    ) -> DiagnosticBuilder<'_> {
+        let ErrorReportingCtx {
+            infcx, body, upvars, ..
+        } = errctx;
+
+        let ErrorConstraintInfo {
+            span, category, ..
+        } = errci;
+
         let fr_name_and_span =
-            self.get_var_name_and_span_for_region(infcx.tcx, body, upvars, fr);
+            self.get_var_name_and_span_for_region(infcx.tcx, body, upvars, errci.fr);
         let outlived_fr_name_and_span =
-            self.get_var_name_and_span_for_region(infcx.tcx, body, upvars, outlived_fr);
+            self.get_var_name_and_span_for_region(infcx.tcx, body, upvars, errci.outlived_fr);
 
         let escapes_from = match self.universal_regions.defining_ty {
             DefiningTy::Closure(..) => "closure",
@@ -469,27 +484,23 @@
         // Revert to the normal error in these cases.
         // Assignments aren't "escapes" in function items.
         if (fr_name_and_span.is_none() && outlived_fr_name_and_span.is_none())
-            || (category == ConstraintCategory::Assignment && escapes_from == "function")
+            || (*category == ConstraintCategory::Assignment && escapes_from == "function")
             || escapes_from == "const"
         {
             return self.report_general_error(
-                body,
-                upvars,
-                infcx,
-                mir_def_id,
-                fr,
-                true,
-                outlived_fr,
-                false,
-                category,
-                span,
-                errors_buffer,
+                errctx,
+                &ErrorConstraintInfo {
+                    fr_is_local: true,
+                    outlived_fr_is_local: false,
+                    .. *errci
+                },
+                renctx,
             );
         }
 
         let mut diag = borrowck_errors::borrowed_data_escapes_closure(
             infcx.tcx,
-            span,
+            *span,
             escapes_from,
         );
 
@@ -513,12 +524,12 @@
             );
 
             diag.span_label(
-                span,
+                *span,
                 format!("`{}` escapes the {} body here", fr_name, escapes_from),
             );
         }
 
-        diag.buffer(errors_buffer);
+        diag
     }
 
     /// Reports a region inference error for the general case with named/synthesized lifetimes to
@@ -538,41 +549,37 @@
     /// ```
     fn report_general_error(
         &self,
-        body: &Body<'tcx>,
-        upvars: &[Upvar],
-        infcx: &InferCtxt<'_, 'tcx>,
-        mir_def_id: DefId,
-        fr: RegionVid,
-        fr_is_local: bool,
-        outlived_fr: RegionVid,
-        outlived_fr_is_local: bool,
-        category: ConstraintCategory,
-        span: Span,
-        errors_buffer: &mut Vec<Diagnostic>,
-    ) {
+        errctx: &ErrorReportingCtx<'_, '_, 'tcx>,
+        errci: &ErrorConstraintInfo,
+        renctx: &mut RegionErrorNamingCtx,
+    ) -> DiagnosticBuilder<'_> {
+        let ErrorReportingCtx {
+            infcx, mir_def_id, ..
+        } = errctx;
+        let ErrorConstraintInfo {
+            fr, fr_is_local, outlived_fr, outlived_fr_is_local, span, category, ..
+        } = errci;
+
         let mut diag = infcx.tcx.sess.struct_span_err(
-            span,
+            *span,
             "lifetime may not live long enough"
         );
 
-        let counter = &mut 1;
-        let fr_name = self.give_region_a_name(
-            infcx, body, upvars, mir_def_id, fr, counter).unwrap();
-        fr_name.highlight_region_name(&mut diag);
-        let outlived_fr_name =
-            self.give_region_a_name(infcx, body, upvars, mir_def_id, outlived_fr, counter).unwrap();
-        outlived_fr_name.highlight_region_name(&mut diag);
-
-        let mir_def_name = if infcx.tcx.is_closure(mir_def_id) {
+        let mir_def_name = if infcx.tcx.is_closure(*mir_def_id) {
             "closure"
         } else {
             "function"
         };
 
+        let fr_name = self.give_region_a_name(errctx, renctx, *fr).unwrap();
+        fr_name.highlight_region_name(&mut diag);
+        let outlived_fr_name = self.give_region_a_name(errctx, renctx, *outlived_fr).unwrap();
+        outlived_fr_name.highlight_region_name(&mut diag);
+
         match (category, outlived_fr_is_local, fr_is_local) {
             (ConstraintCategory::Return, true, _) => {
                 diag.span_label(
-                    span,
+                    *span,
                     format!(
                         "{} was supposed to return data with lifetime `{}` but it is returning \
                          data with lifetime `{}`",
@@ -582,7 +589,7 @@
             }
             _ => {
                 diag.span_label(
-                    span,
+                    *span,
                     format!(
                         "{}requires that `{}` must outlive `{}`",
                         category.description(),
@@ -593,9 +600,9 @@
             }
         }
 
-        self.add_static_impl_trait_suggestion(infcx, &mut diag, fr, fr_name, outlived_fr);
+        self.add_static_impl_trait_suggestion(infcx, &mut diag, *fr, fr_name, *outlived_fr);
 
-        diag.buffer(errors_buffer);
+        diag
     }
 
     /// Adds a suggestion to errors where a `impl Trait` is returned.
@@ -704,8 +711,14 @@
             borrow_region,
             |r| self.provides_universal_region(r, borrow_region, outlived_region)
         );
-        let outlived_fr_name =
-            self.give_region_a_name(infcx, body, upvars, mir_def_id, outlived_region, &mut 1);
+
+        let mut renctx = RegionErrorNamingCtx::new();
+        let errctx = ErrorReportingCtx {
+            infcx, body, upvars, mir_def_id,
+            region_infcx: self,
+        };
+        let outlived_fr_name = self.give_region_a_name(&errctx, &mut renctx, outlived_region);
+
         (category, from_closure, span, outlived_fr_name)
     }
 
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
index 75a3162..6fa9426 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
@@ -1,5 +1,9 @@
 use std::fmt::{self, Display};
-use crate::borrow_check::nll::region_infer::RegionInferenceContext;
+
+use crate::borrow_check::nll::region_infer::{
+    RegionInferenceContext,
+    error_reporting::ErrorReportingCtx,
+};
 use crate::borrow_check::nll::universal_regions::DefiningTy;
 use crate::borrow_check::nll::ToRegionVid;
 use crate::borrow_check::Upvar;
@@ -13,29 +17,75 @@
 use rustc::ty::print::RegionHighlightMode;
 use rustc_errors::DiagnosticBuilder;
 use syntax::symbol::kw;
-use syntax_pos::Span;
-use syntax_pos::symbol::InternedString;
+use rustc_data_structures::fx::FxHashMap;
+use syntax_pos::{Span, symbol::InternedString};
 
-#[derive(Debug)]
+/// A name for a particular region used in emitting diagnostics. This name could be a generated
+/// name like `'1`, a name used by the user like `'a`, or a name like `'static`.
+#[derive(Debug, Clone)]
 crate struct RegionName {
+    /// The name of the region (interned).
     crate name: InternedString,
+    /// Where the region comes from.
     crate source: RegionNameSource,
 }
 
-#[derive(Debug)]
+/// Denotes the source of a region that is named by a `RegionName`. For example, a free region that
+/// was named by the user would get `NamedFreeRegion` and `'static` lifetime would get `Static`.
+/// This helps to print the right kinds of diagnostics.
+#[derive(Debug, Clone)]
 crate enum RegionNameSource {
+    /// A bound (not free) region that was substituted at the def site (not an HRTB).
     NamedEarlyBoundRegion(Span),
+    /// A free region that the user has a name (`'a`) for.
     NamedFreeRegion(Span),
+    /// The `'static` region.
     Static,
+    /// The free region corresponding to the environment of a closure.
     SynthesizedFreeEnvRegion(Span, String),
+    /// The region name corresponds to a region where the type annotation is completely missing
+    /// from the code, e.g. in a closure arguments `|x| { ... }`, where `x` is a reference.
     CannotMatchHirTy(Span, String),
+    /// The region name corresponds a reference that was found by traversing the type in the HIR.
     MatchedHirTy(Span),
+    /// A region name from the generics list of a struct/enum/union.
     MatchedAdtAndSegment(Span),
+    /// The region corresponding to a closure upvar.
     AnonRegionFromUpvar(Span, String),
+    /// The region corresponding to the return type of a closure.
     AnonRegionFromOutput(Span, String, String),
     AnonRegionFromYieldTy(Span, String),
 }
 
+/// Records region names that have been assigned before so that we can use the same ones in later
+/// diagnostics.
+#[derive(Debug, Clone)]
+crate struct RegionErrorNamingCtx {
+    /// Record the region names generated for each region in the given
+    /// MIR def so that we can reuse them later in help/error messages.
+    renctx: FxHashMap<RegionVid, RegionName>,
+
+    /// The counter for generating new region names.
+    counter: usize,
+}
+
+impl RegionErrorNamingCtx {
+    crate fn new() -> Self {
+        Self {
+            counter: 1,
+            renctx: FxHashMap::default(),
+        }
+    }
+
+    crate fn get(&self, region: &RegionVid) -> Option<&RegionName> {
+        self.renctx.get(region)
+    }
+
+    crate fn insert(&mut self, region: RegionVid, name: RegionName) {
+        self.renctx.insert(region, name);
+    }
+}
+
 impl RegionName {
     #[allow(dead_code)]
     crate fn was_named(&self) -> bool {
@@ -63,43 +113,40 @@
         self.name
     }
 
-    crate fn highlight_region_name(
-        &self,
-        diag: &mut DiagnosticBuilder<'_>
-    ) {
+    crate fn highlight_region_name(&self, diag: &mut DiagnosticBuilder<'_>) {
         match &self.source {
-            RegionNameSource::NamedFreeRegion(span) |
-            RegionNameSource::NamedEarlyBoundRegion(span) => {
-                diag.span_label(
-                    *span,
-                    format!("lifetime `{}` defined here", self),
-                );
-            },
+            RegionNameSource::NamedFreeRegion(span)
+            | RegionNameSource::NamedEarlyBoundRegion(span) => {
+                diag.span_label(*span, format!("lifetime `{}` defined here", self));
+            }
             RegionNameSource::SynthesizedFreeEnvRegion(span, note) => {
                 diag.span_label(
                     *span,
                     format!("lifetime `{}` represents this closure's body", self),
                 );
                 diag.note(&note);
-            },
+            }
             RegionNameSource::CannotMatchHirTy(span, type_name) => {
                 diag.span_label(*span, format!("has type `{}`", type_name));
-            },
+            }
             RegionNameSource::MatchedHirTy(span) => {
                 diag.span_label(
                     *span,
                     format!("let's call the lifetime of this reference `{}`", self),
                 );
-            },
+            }
             RegionNameSource::MatchedAdtAndSegment(span) => {
                 diag.span_label(*span, format!("let's call this `{}`", self));
-            },
+            }
             RegionNameSource::AnonRegionFromUpvar(span, upvar_name) => {
                 diag.span_label(
                     *span,
-                    format!("lifetime `{}` appears in the type of `{}`", self, upvar_name),
+                    format!(
+                        "lifetime `{}` appears in the type of `{}`",
+                        self, upvar_name
+                    ),
                 );
-            },
+            }
             RegionNameSource::AnonRegionFromOutput(span, mir_description, type_name) => {
                 diag.span_label(
                     *span,
@@ -151,39 +198,49 @@
     /// and then return the name `'1` for us to use.
     crate fn give_region_a_name(
         &self,
-        infcx: &InferCtxt<'_, 'tcx>,
-        body: &Body<'tcx>,
-        upvars: &[Upvar],
-        mir_def_id: DefId,
+        errctx: &ErrorReportingCtx<'_, '_, 'tcx>,
+        renctx: &mut RegionErrorNamingCtx,
         fr: RegionVid,
-        counter: &mut usize,
     ) -> Option<RegionName> {
-        debug!("give_region_a_name(fr={:?}, counter={})", fr, counter);
+        let ErrorReportingCtx {
+            infcx, body, mir_def_id, upvars, ..
+        } = errctx;
+
+        debug!("give_region_a_name(fr={:?}, counter={:?})", fr, renctx.counter);
 
         assert!(self.universal_regions.is_universal_region(fr));
 
-        let value = self.give_name_from_error_region(infcx.tcx, mir_def_id, fr, counter)
+        if let Some(value) = renctx.get(&fr) {
+            return Some(value.clone());
+        }
+
+        let value = self
+            .give_name_from_error_region(infcx.tcx, *mir_def_id, fr, renctx)
             .or_else(|| {
                 self.give_name_if_anonymous_region_appears_in_arguments(
-                    infcx, body, mir_def_id, fr, counter,
+                    infcx, body, *mir_def_id, fr, renctx,
                 )
             })
             .or_else(|| {
                 self.give_name_if_anonymous_region_appears_in_upvars(
-                    infcx.tcx, upvars, fr, counter,
+                    infcx.tcx, upvars, fr, renctx
                 )
             })
             .or_else(|| {
                 self.give_name_if_anonymous_region_appears_in_output(
-                    infcx, body, mir_def_id, fr, counter,
+                    infcx, body, *mir_def_id, fr, renctx,
                 )
             })
             .or_else(|| {
                 self.give_name_if_anonymous_region_appears_in_yield_ty(
-                    infcx, body, mir_def_id, fr, counter,
+                    infcx, body, *mir_def_id, fr, renctx,
                 )
             });
 
+        if let Some(ref value) = value {
+            renctx.insert(fr, value.clone());
+        }
+
         debug!("give_region_a_name: gave name {:?}", value);
         value
     }
@@ -197,7 +254,7 @@
         tcx: TyCtxt<'tcx>,
         mir_def_id: DefId,
         fr: RegionVid,
-        counter: &mut usize,
+        renctx: &mut RegionErrorNamingCtx,
     ) -> Option<RegionName> {
         let error_region = self.to_error_region(fr)?;
 
@@ -208,7 +265,7 @@
                     let span = self.get_named_span(tcx, error_region, ebr.name);
                     Some(RegionName {
                         name: ebr.name,
-                        source: RegionNameSource::NamedEarlyBoundRegion(span)
+                        source: RegionNameSource::NamedEarlyBoundRegion(span),
                     })
                 } else {
                     None
@@ -227,12 +284,10 @@
                         name,
                         source: RegionNameSource::NamedFreeRegion(span),
                     })
-                },
+                }
 
                 ty::BoundRegion::BrEnv => {
-                    let mir_hir_id = tcx.hir()
-                                        .as_local_hir_id(mir_def_id)
-                                        .expect("non-local mir");
+                    let mir_hir_id = tcx.hir().as_local_hir_id(mir_def_id).expect("non-local mir");
                     let def_ty = self.universal_regions.defining_ty;
 
                     if let DefiningTy::Closure(def_id, substs) = def_ty {
@@ -243,7 +298,7 @@
                         } else {
                             bug!("Closure is not defined by a closure expr");
                         };
-                        let region_name = self.synthesize_region_name(counter);
+                        let region_name = self.synthesize_region_name(renctx);
 
                         let closure_kind_ty = substs.closure_kind_ty(def_id, tcx);
                         let note = match closure_kind_ty.to_opt_closure_kind() {
@@ -265,7 +320,7 @@
                             name: region_name,
                             source: RegionNameSource::SynthesizedFreeEnvRegion(
                                 args_span,
-                                note.to_string()
+                                note.to_string(),
                             ),
                         })
                     } else {
@@ -335,7 +390,7 @@
         body: &Body<'tcx>,
         mir_def_id: DefId,
         fr: RegionVid,
-        counter: &mut usize,
+        renctx: &mut RegionErrorNamingCtx,
     ) -> Option<RegionName> {
         let implicit_inputs = self.universal_regions.defining_ty.implicit_inputs();
         let argument_index = self.get_argument_index_for_region(infcx.tcx, fr)?;
@@ -349,12 +404,12 @@
             fr,
             arg_ty,
             argument_index,
-            counter,
+            renctx,
         ) {
             return Some(region_name);
         }
 
-        self.give_name_if_we_cannot_match_hir_ty(infcx, body, fr, arg_ty, counter)
+        self.give_name_if_we_cannot_match_hir_ty(infcx, body, fr, arg_ty, renctx)
     }
 
     fn give_name_if_we_can_match_hir_ty_from_argument(
@@ -365,7 +420,7 @@
         needle_fr: RegionVid,
         argument_ty: Ty<'tcx>,
         argument_index: usize,
-        counter: &mut usize,
+        renctx: &mut RegionErrorNamingCtx,
     ) -> Option<RegionName> {
         let mir_hir_id = infcx.tcx.hir().as_local_hir_id(mir_def_id)?;
         let fn_decl = infcx.tcx.hir().fn_decl_by_hir_id(mir_hir_id)?;
@@ -379,7 +434,7 @@
                 body,
                 needle_fr,
                 argument_ty,
-                counter,
+                renctx,
             ),
 
             _ => self.give_name_if_we_can_match_hir_ty(
@@ -387,7 +442,7 @@
                 needle_fr,
                 argument_ty,
                 argument_hir_ty,
-                counter,
+                renctx,
             ),
         }
     }
@@ -409,10 +464,11 @@
         body: &Body<'tcx>,
         needle_fr: RegionVid,
         argument_ty: Ty<'tcx>,
-        counter: &mut usize,
+        renctx: &mut RegionErrorNamingCtx,
     ) -> Option<RegionName> {
+        let counter = renctx.counter;
         let mut highlight = RegionHighlightMode::default();
-        highlight.highlighting_region_vid(needle_fr, *counter);
+        highlight.highlighting_region_vid(needle_fr, counter);
         let type_name = infcx.extract_type_name(&argument_ty, Some(highlight)).0;
 
         debug!(
@@ -428,7 +484,7 @@
                 // This counter value will already have been used, so this function will increment
                 // it so the next value will be used next and return the region name that would
                 // have been used.
-                name: self.synthesize_region_name(counter),
+                name: self.synthesize_region_name(renctx),
                 source: RegionNameSource::CannotMatchHirTy(span, type_name),
             })
         } else {
@@ -455,7 +511,7 @@
     /// type. Once we find that, we can use the span of the `hir::Ty`
     /// to add the highlight.
     ///
-    /// This is a somewhat imperfect process, so long the way we also
+    /// This is a somewhat imperfect process, so along the way we also
     /// keep track of the **closest** type we've found. If we fail to
     /// find the exact `&` or `'_` to highlight, then we may fall back
     /// to highlighting that closest type instead.
@@ -465,7 +521,7 @@
         needle_fr: RegionVid,
         argument_ty: Ty<'tcx>,
         argument_hir_ty: &hir::Ty,
-        counter: &mut usize,
+        renctx: &mut RegionErrorNamingCtx,
     ) -> Option<RegionName> {
         let search_stack: &mut Vec<(Ty<'tcx>, &hir::Ty)> =
             &mut vec![(argument_ty, argument_hir_ty)];
@@ -483,7 +539,7 @@
                     hir::TyKind::Rptr(_lifetime, referent_hir_ty),
                 ) => {
                     if region.to_region_vid() == needle_fr {
-                        let region_name = self.synthesize_region_name(counter);
+                        let region_name = self.synthesize_region_name(renctx);
 
                         // Just grab the first character, the `&`.
                         let source_map = tcx.sess.source_map();
@@ -515,7 +571,7 @@
                                 substs,
                                 needle_fr,
                                 last_segment,
-                                counter,
+                                renctx,
                                 search_stack,
                             ) {
                                 return Some(name);
@@ -559,18 +615,19 @@
         substs: SubstsRef<'tcx>,
         needle_fr: RegionVid,
         last_segment: &'hir hir::PathSegment,
-        counter: &mut usize,
+        renctx: &mut RegionErrorNamingCtx,
         search_stack: &mut Vec<(Ty<'tcx>, &'hir hir::Ty)>,
     ) -> Option<RegionName> {
         // Did the user give explicit arguments? (e.g., `Foo<..>`)
         let args = last_segment.args.as_ref()?;
-        let lifetime = self.try_match_adt_and_generic_args(substs, needle_fr, args, search_stack)?;
+        let lifetime =
+            self.try_match_adt_and_generic_args(substs, needle_fr, args, search_stack)?;
         match lifetime.name {
             hir::LifetimeName::Param(_)
             | hir::LifetimeName::Error
             | hir::LifetimeName::Static
             | hir::LifetimeName::Underscore => {
-                let region_name = self.synthesize_region_name(counter);
+                let region_name = self.synthesize_region_name(renctx);
                 let ampersand_span = lifetime.span;
                 Some(RegionName {
                     name: region_name,
@@ -657,12 +714,12 @@
         tcx: TyCtxt<'tcx>,
         upvars: &[Upvar],
         fr: RegionVid,
-        counter: &mut usize,
+        renctx: &mut RegionErrorNamingCtx,
     ) -> Option<RegionName> {
         let upvar_index = self.get_upvar_index_for_region(tcx, fr)?;
         let (upvar_name, upvar_span) =
             self.get_upvar_name_and_span_for_region(tcx, upvars, upvar_index);
-        let region_name = self.synthesize_region_name(counter);
+        let region_name = self.synthesize_region_name(renctx);
 
         Some(RegionName {
             name: region_name,
@@ -680,7 +737,7 @@
         body: &Body<'tcx>,
         mir_def_id: DefId,
         fr: RegionVid,
-        counter: &mut usize,
+        renctx: &mut RegionErrorNamingCtx,
     ) -> Option<RegionName> {
         let tcx = infcx.tcx;
 
@@ -694,7 +751,7 @@
         }
 
         let mut highlight = RegionHighlightMode::default();
-        highlight.highlighting_region_vid(fr, *counter);
+        highlight.highlighting_region_vid(fr, renctx.counter);
         let type_name = infcx.extract_type_name(&return_ty, Some(highlight)).0;
 
         let mir_hir_id = tcx.hir().as_local_hir_id(mir_def_id).expect("non-local mir");
@@ -725,11 +782,11 @@
             // This counter value will already have been used, so this function will increment it
             // so the next value will be used next and return the region name that would have been
             // used.
-            name: self.synthesize_region_name(counter),
+            name: self.synthesize_region_name(renctx),
             source: RegionNameSource::AnonRegionFromOutput(
                 return_span,
                 mir_description.to_string(),
-                type_name
+                type_name,
             ),
         })
     }
@@ -740,7 +797,7 @@
         body: &Body<'tcx>,
         mir_def_id: DefId,
         fr: RegionVid,
-        counter: &mut usize,
+        renctx: &mut RegionErrorNamingCtx,
     ) -> Option<RegionName> {
         // Note: generators from `async fn` yield `()`, so we don't have to
         // worry about them here.
@@ -757,7 +814,7 @@
         }
 
         let mut highlight = RegionHighlightMode::default();
-        highlight.highlighting_region_vid(fr, *counter);
+        highlight.highlighting_region_vid(fr, renctx.counter);
         let type_name = infcx.extract_type_name(&yield_ty, Some(highlight)).0;
 
         let mir_hir_id = tcx.hir().as_local_hir_id(mir_def_id).expect("non-local mir");
@@ -780,16 +837,15 @@
         );
 
         Some(RegionName {
-            name: self.synthesize_region_name(counter),
+            name: self.synthesize_region_name(renctx),
             source: RegionNameSource::AnonRegionFromYieldTy(yield_span, type_name),
         })
     }
 
-    /// Creates a synthetic region named `'1`, incrementing the
-    /// counter.
-    fn synthesize_region_name(&self, counter: &mut usize) -> InternedString {
-        let c = *counter;
-        *counter += 1;
+    /// Creates a synthetic region named `'1`, incrementing the counter.
+    fn synthesize_region_name(&self, renctx: &mut RegionErrorNamingCtx) -> InternedString {
+        let c = renctx.counter;
+        renctx.counter += 1;
 
         InternedString::intern(&format!("'{:?}", c))
     }
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
index 4038872..78e7943 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
@@ -1,15 +1,20 @@
-use super::universal_regions::UniversalRegions;
-use crate::borrow_check::nll::constraints::graph::NormalConstraintGraph;
-use crate::borrow_check::nll::constraints::{
-    ConstraintSccIndex, OutlivesConstraint, OutlivesConstraintSet,
+use std::rc::Rc;
+
+use crate::borrow_check::nll::{
+    constraints::{
+        graph::NormalConstraintGraph,
+        ConstraintSccIndex,
+        OutlivesConstraint,
+        OutlivesConstraintSet,
+    },
+    member_constraints::{MemberConstraintSet, NllMemberConstraintIndex},
+    region_infer::values::{
+        PlaceholderIndices, RegionElement, ToElementIndex
+    },
+    type_check::{free_region_relations::UniversalRegionRelations, Locations},
 };
-use crate::borrow_check::nll::member_constraints::{MemberConstraintSet, NllMemberConstraintIndex};
-use crate::borrow_check::nll::region_infer::values::{
-    PlaceholderIndices, RegionElement, ToElementIndex,
-};
-use crate::borrow_check::nll::type_check::free_region_relations::UniversalRegionRelations;
-use crate::borrow_check::nll::type_check::Locations;
 use crate::borrow_check::Upvar;
+
 use rustc::hir::def_id::DefId;
 use rustc::infer::canonical::QueryOutlivesConstraint;
 use rustc::infer::opaque_types;
@@ -31,16 +36,16 @@
 use rustc_errors::{Diagnostic, DiagnosticBuilder};
 use syntax_pos::Span;
 
-use std::rc::Rc;
+crate use self::error_reporting::{RegionName, RegionNameSource, RegionErrorNamingCtx};
+use self::values::{LivenessValues, RegionValueElements, RegionValues};
+use super::universal_regions::UniversalRegions;
+use super::ToRegionVid;
 
 mod dump_mir;
 mod error_reporting;
-crate use self::error_reporting::{RegionName, RegionNameSource};
 mod graphviz;
-pub mod values;
-use self::values::{LivenessValues, RegionValueElements, RegionValues};
 
-use super::ToRegionVid;
+pub mod values;
 
 pub struct RegionInferenceContext<'tcx> {
     /// Contains the definition for every region variable. Region
@@ -487,6 +492,12 @@
             errors_buffer,
         );
 
+        // If we produce any errors, we keep track of the names of all regions, so that we can use
+        // the same error names in any suggestions we produce. Note that we need names to be unique
+        // across different errors for the same MIR def so that we can make suggestions that fix
+        // multiple problems.
+        let mut region_naming = RegionErrorNamingCtx::new();
+
         self.check_universal_regions(
             infcx,
             body,
@@ -494,6 +505,7 @@
             mir_def_id,
             outlives_requirements.as_mut(),
             errors_buffer,
+            &mut region_naming,
         );
 
         self.check_member_constraints(infcx, mir_def_id, errors_buffer);
@@ -1312,6 +1324,7 @@
         mir_def_id: DefId,
         mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
         errors_buffer: &mut Vec<Diagnostic>,
+        region_naming: &mut RegionErrorNamingCtx,
     ) {
         for (fr, fr_definition) in self.definitions.iter_enumerated() {
             match fr_definition.origin {
@@ -1327,6 +1340,7 @@
                         fr,
                         &mut propagated_outlives_requirements,
                         errors_buffer,
+                        region_naming,
                     );
                 }
 
@@ -1358,6 +1372,7 @@
         longer_fr: RegionVid,
         propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
         errors_buffer: &mut Vec<Diagnostic>,
+        region_naming: &mut RegionErrorNamingCtx,
     ) {
         debug!("check_universal_region(fr={:?})", longer_fr);
 
@@ -1385,6 +1400,7 @@
                 mir_def_id,
                 propagated_outlives_requirements,
                 errors_buffer,
+                region_naming,
             );
             return;
         }
@@ -1401,8 +1417,13 @@
                 mir_def_id,
                 propagated_outlives_requirements,
                 errors_buffer,
+                region_naming,
             ) {
                 // continuing to iterate just reports more errors than necessary
+                //
+                // FIXME It would also allow us to report more Outlives Suggestions, though, so
+                // it's not clear that that's a bad thing. Somebody should try commenting out this
+                // line and see it is actually a regression.
                 return;
             }
         }
@@ -1418,6 +1439,7 @@
         mir_def_id: DefId,
         propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
         errors_buffer: &mut Vec<Diagnostic>,
+        region_naming: &mut RegionErrorNamingCtx,
     ) -> Option<ErrorReported> {
         // If it is known that `fr: o`, carry on.
         if self.universal_region_relations.outlives(longer_fr, shorter_fr) {
@@ -1466,7 +1488,18 @@
         //
         // Note: in this case, we use the unapproximated regions to report the
         // error. This gives better error messages in some cases.
-        self.report_error(body, upvars, infcx, mir_def_id, longer_fr, shorter_fr, errors_buffer);
+        let db = self.report_error(
+            body,
+            upvars,
+            infcx,
+            mir_def_id,
+            longer_fr,
+            shorter_fr,
+            region_naming,
+        );
+
+        db.buffer(errors_buffer);
+
         Some(ErrorReported)
     }
 
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index 1d17bae..62bff34 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -2417,9 +2417,12 @@
             "add_reborrow_constraint({:?}, {:?}, {:?})",
             location, borrow_region, borrowed_place
         );
-        for (i, elem) in borrowed_place.projection.iter().enumerate().rev() {
+
+        let mut cursor = &*borrowed_place.projection;
+        while let [proj_base @ .., elem] = cursor {
+            cursor = proj_base;
+
             debug!("add_reborrow_constraint - iteration {:?}", elem);
-            let proj_base = &borrowed_place.projection[..i];
 
             match elem {
                 ProjectionElem::Deref => {
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs
index aa261f8..2b0237c 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir/build/matches/mod.rs
@@ -1296,8 +1296,9 @@
         // Insert a Shallow borrow of the prefixes of any fake borrows.
         for place in fake_borrows
         {
-            for (i, elem) in place.projection.iter().enumerate().rev() {
-                let proj_base = &place.projection[..i];
+            let mut cursor = &*place.projection;
+            while let [proj_base @ .., elem] = cursor {
+                cursor = proj_base;
 
                 if let ProjectionElem::Deref = elem {
                     // Insert a shallow borrow after a deref. For other
diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs
index 57ddaa4..4351598 100644
--- a/src/librustc_mir/const_eval.rs
+++ b/src/librustc_mir/const_eval.rs
@@ -15,6 +15,7 @@
 use rustc::ty::layout::{self, LayoutOf, VariantIdx};
 use rustc::traits::Reveal;
 use rustc_data_structures::fx::FxHashMap;
+use crate::interpret::eval_nullary_intrinsic;
 
 use syntax::source_map::{Span, DUMMY_SP};
 
@@ -134,9 +135,8 @@
     ecx: &mut CompileTimeEvalContext<'mir, 'tcx>,
     cid: GlobalId<'tcx>,
     body: &'mir mir::Body<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
 ) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
-    debug!("eval_body_using_ecx: {:?}, {:?}", cid, param_env);
+    debug!("eval_body_using_ecx: {:?}, {:?}", cid, ecx.param_env);
     let tcx = ecx.tcx.tcx;
     let layout = ecx.layout_of(body.return_ty().subst(tcx, cid.instance.substs))?;
     assert!(!layout.is_unsized());
@@ -162,7 +162,6 @@
         ecx,
         cid.instance.def_id(),
         ret,
-        param_env,
     )?;
 
     debug!("eval_body_using_ecx done: {:?}", *ret);
@@ -604,6 +603,23 @@
             other => return other,
         }
     }
+
+    // We call `const_eval` for zero arg intrinsics, too, in order to cache their value.
+    // Catch such calls and evaluate them instead of trying to load a constant's MIR.
+    if let ty::InstanceDef::Intrinsic(def_id) = key.value.instance.def {
+        let ty = key.value.instance.ty(tcx);
+        let substs = match ty.sty {
+            ty::FnDef(_, substs) => substs,
+            _ => bug!("intrinsic with type {:?}", ty),
+        };
+        return eval_nullary_intrinsic(tcx, key.param_env, def_id, substs)
+            .map_err(|error| {
+                let span = tcx.def_span(def_id);
+                let error = ConstEvalErr { error: error.kind, stacktrace: vec![], span };
+                error.report_as_error(tcx.at(span), "could not evaluate nullary intrinsic")
+            })
+    }
+
     tcx.const_eval_raw(key).and_then(|val| {
         validate_and_turn_into_const(tcx, val, key)
     })
@@ -658,7 +674,7 @@
 
     let res = ecx.load_mir(cid.instance.def, cid.promoted);
     res.and_then(
-        |body| eval_body_using_ecx(&mut ecx, cid, body, key.param_env)
+        |body| eval_body_using_ecx(&mut ecx, cid, body)
     ).and_then(|place| {
         Ok(RawConst {
             alloc_id: place.ptr.assert_ptr().alloc_id,
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 054b65f..78996ed 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -14,7 +14,6 @@
 use rustc::ty::query::TyCtxtAt;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc::mir::interpret::{
-    ErrorHandled,
     GlobalId, Scalar, Pointer, FrameInfo, AllocId,
     InterpResult, truncate, sign_extend,
 };
@@ -672,14 +671,7 @@
         // Our result will later be validated anyway, and there seems no good reason
         // to have to fail early here.  This is also more consistent with
         // `Memory::get_static_alloc` which has to use `const_eval_raw` to avoid cycles.
-        let val = self.tcx.const_eval_raw(param_env.and(gid)).map_err(|err| {
-            match err {
-                ErrorHandled::Reported =>
-                    err_inval!(ReferencedConstant),
-                ErrorHandled::TooGeneric =>
-                    err_inval!(TooGeneric),
-            }
-        })?;
+        let val = self.tcx.const_eval_raw(param_env.and(gid))?;
         self.raw_const_to_mplace(val)
     }
 
diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs
index 4cbbc0f..95647ce 100644
--- a/src/librustc_mir/interpret/intern.rs
+++ b/src/librustc_mir/interpret/intern.rs
@@ -3,7 +3,7 @@
 //! After a const evaluation has computed a value, before we destroy the const evaluator's session
 //! memory, we need to extract all memory allocations to the global memory pool so they stay around.
 
-use rustc::ty::{Ty, TyCtxt, ParamEnv, self};
+use rustc::ty::{Ty, self};
 use rustc::mir::interpret::{InterpResult, ErrorHandled};
 use rustc::hir;
 use rustc::hir::def_id::DefId;
@@ -11,32 +11,29 @@
 use rustc_data_structures::fx::FxHashSet;
 
 use syntax::ast::Mutability;
-use syntax_pos::Span;
 
 use super::{
-    ValueVisitor, MemoryKind, Pointer, AllocId, MPlaceTy, Scalar,
+    ValueVisitor, MemoryKind, AllocId, MPlaceTy, Scalar,
 };
 use crate::const_eval::{CompileTimeInterpreter, CompileTimeEvalContext};
 
 struct InternVisitor<'rt, 'mir, 'tcx> {
-    /// previously encountered safe references
-    ref_tracking: &'rt mut RefTracking<(MPlaceTy<'tcx>, Mutability, InternMode)>,
+    /// The ectx from which we intern.
     ecx: &'rt mut CompileTimeEvalContext<'mir, 'tcx>,
-    param_env: ParamEnv<'tcx>,
+    /// Previously encountered safe references.
+    ref_tracking: &'rt mut RefTracking<(MPlaceTy<'tcx>, Mutability, InternMode)>,
+    /// A list of all encountered allocations. After type-based interning, we traverse this list to
+    /// also intern allocations that are only referenced by a raw pointer or inside a union.
+    leftover_allocations: &'rt mut FxHashSet<AllocId>,
     /// The root node of the value that we're looking at. This field is never mutated and only used
     /// for sanity assertions that will ICE when `const_qualif` screws up.
     mode: InternMode,
     /// This field stores the mutability of the value *currently* being checked.
-    /// It is set to mutable when an `UnsafeCell` is encountered
-    /// When recursing across a reference, we don't recurse but store the
-    /// value to be checked in `ref_tracking` together with the mutability at which we are checking
-    /// the value.
-    /// When encountering an immutable reference, we treat everything as immutable that is behind
-    /// it.
+    /// When encountering a mutable reference, we determine the pointee mutability
+    /// taking into account the mutability of the context: `& &mut i32` is entirely immutable,
+    /// despite the nested mutable reference!
+    /// The field gets updated when an `UnsafeCell` is encountered.
     mutability: Mutability,
-    /// A list of all encountered relocations. After type-based interning, we traverse this list to
-    /// also intern allocations that are only referenced by a raw pointer or inside a union.
-    leftover_relocations: &'rt mut FxHashSet<AllocId>,
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Hash, Eq)]
@@ -45,9 +42,10 @@
     /// `static`. In a `static mut` we start out as mutable and thus can also contain further `&mut`
     /// that will actually be treated as mutable.
     Static,
-    /// UnsafeCell is OK in the value of a constant, but not behind references in a constant
+    /// UnsafeCell is OK in the value of a constant: `const FOO = Cell::new(0)` creates
+    /// a new cell every time it is used.
     ConstBase,
-    /// `UnsafeCell` ICEs
+    /// `UnsafeCell` ICEs.
     Const,
 }
 
@@ -55,48 +53,100 @@
 /// into the memory of other constants or statics
 struct IsStaticOrFn;
 
+/// Intern an allocation without looking at its children.
+/// `mode` is the mode of the environment where we found this pointer.
+/// `mutablity` is the mutability of the place to be interned; even if that says
+/// `immutable` things might become mutable if `ty` is not frozen.
+/// `ty` can be `None` if there is no potential interior mutability
+/// to account for (e.g. for vtables).
+fn intern_shallow<'rt, 'mir, 'tcx>(
+    ecx: &'rt mut CompileTimeEvalContext<'mir, 'tcx>,
+    leftover_allocations: &'rt mut FxHashSet<AllocId>,
+    mode: InternMode,
+    alloc_id: AllocId,
+    mutability: Mutability,
+    ty: Option<Ty<'tcx>>,
+) -> InterpResult<'tcx, Option<IsStaticOrFn>> {
+    trace!(
+        "InternVisitor::intern {:?} with {:?}",
+        alloc_id, mutability,
+    );
+    // remove allocation
+    let tcx = ecx.tcx;
+    let memory = ecx.memory_mut();
+    let (kind, mut alloc) = match memory.alloc_map.remove(&alloc_id) {
+        Some(entry) => entry,
+        None => {
+            // Pointer not found in local memory map. It is either a pointer to the global
+            // map, or dangling.
+            // If the pointer is dangling (neither in local nor global memory), we leave it
+            // to validation to error. The `delay_span_bug` ensures that we don't forget such
+            // a check in validation.
+            if tcx.alloc_map.lock().get(alloc_id).is_none() {
+                tcx.sess.delay_span_bug(ecx.tcx.span, "tried to intern dangling pointer");
+            }
+            // treat dangling pointers like other statics
+            // just to stop trying to recurse into them
+            return Ok(Some(IsStaticOrFn));
+        },
+    };
+    // This match is just a canary for future changes to `MemoryKind`, which most likely need
+    // changes in this function.
+    match kind {
+        MemoryKind::Stack | MemoryKind::Vtable => {},
+    }
+    // Set allocation mutability as appropriate. This is used by LLVM to put things into
+    // read-only memory, and also by Miri when evluating other constants/statics that
+    // access this one.
+    if mode == InternMode::Static {
+        // When `ty` is `None`, we assume no interior mutability.
+        let frozen = ty.map_or(true, |ty| ty.is_freeze(
+            ecx.tcx.tcx,
+            ecx.param_env,
+            ecx.tcx.span,
+        ));
+        // For statics, allocation mutability is the combination of the place mutability and
+        // the type mutability.
+        // The entire allocation needs to be mutable if it contains an `UnsafeCell` anywhere.
+        if mutability == Mutability::Immutable && frozen {
+            alloc.mutability = Mutability::Immutable;
+        } else {
+            // Just making sure we are not "upgrading" an immutable allocation to mutable.
+            assert_eq!(alloc.mutability, Mutability::Mutable);
+        }
+    } else {
+        // We *could* be non-frozen at `ConstBase`, for constants like `Cell::new(0)`.
+        // But we still intern that as immutable as the memory cannot be changed once the
+        // initial value was computed.
+        // Constants are never mutable.
+        assert_eq!(
+            mutability, Mutability::Immutable,
+            "Something went very wrong: mutability requested for a constant"
+        );
+        alloc.mutability = Mutability::Immutable;
+    };
+    // link the alloc id to the actual allocation
+    let alloc = tcx.intern_const_alloc(alloc);
+    leftover_allocations.extend(alloc.relocations().iter().map(|&(_, ((), reloc))| reloc));
+    tcx.alloc_map.lock().set_alloc_id_memory(alloc_id, alloc);
+    Ok(None)
+}
+
 impl<'rt, 'mir, 'tcx> InternVisitor<'rt, 'mir, 'tcx> {
-    /// Intern an allocation without looking at its children
     fn intern_shallow(
         &mut self,
-        ptr: Pointer,
+        alloc_id: AllocId,
         mutability: Mutability,
+        ty: Option<Ty<'tcx>>,
     ) -> InterpResult<'tcx, Option<IsStaticOrFn>> {
-        trace!(
-            "InternVisitor::intern {:?} with {:?}",
-            ptr, mutability,
-        );
-        // remove allocation
-        let tcx = self.ecx.tcx;
-        let memory = self.ecx.memory_mut();
-        let (kind, mut alloc) = match memory.alloc_map.remove(&ptr.alloc_id) {
-            Some(entry) => entry,
-            None => {
-                // if the pointer is dangling (neither in local nor global memory), we leave it
-                // to validation to error. The `delay_span_bug` ensures that we don't forget such
-                // a check in validation.
-                if tcx.alloc_map.lock().get(ptr.alloc_id).is_none() {
-                    tcx.sess.delay_span_bug(self.ecx.tcx.span, "tried to intern dangling pointer");
-                }
-                // treat dangling pointers like other statics
-                // just to stop trying to recurse into them
-                return Ok(Some(IsStaticOrFn));
-            },
-        };
-        // This match is just a canary for future changes to `MemoryKind`, which most likely need
-        // changes in this function.
-        match kind {
-            MemoryKind::Stack | MemoryKind::Vtable => {},
-        }
-        // Ensure llvm knows to only put this into immutable memory if the value is immutable either
-        // by being behind a reference or by being part of a static or const without interior
-        // mutability
-        alloc.mutability = mutability;
-        // link the alloc id to the actual allocation
-        let alloc = tcx.intern_const_alloc(alloc);
-        self.leftover_relocations.extend(alloc.relocations().iter().map(|&(_, ((), reloc))| reloc));
-        tcx.alloc_map.lock().set_alloc_id_memory(ptr.alloc_id, alloc);
-        Ok(None)
+        intern_shallow(
+            self.ecx,
+            self.leftover_allocations,
+            self.mode,
+            alloc_id,
+            mutability,
+            ty,
+        )
     }
 }
 
@@ -119,14 +169,16 @@
     ) -> InterpResult<'tcx> {
         if let Some(def) = mplace.layout.ty.ty_adt_def() {
             if Some(def.did) == self.ecx.tcx.lang_items().unsafe_cell_type() {
-                // We are crossing over an `UnsafeCell`, we can mutate again
+                // We are crossing over an `UnsafeCell`, we can mutate again. This means that
+                // References we encounter inside here are interned as pointing to mutable
+                // allocations.
                 let old = std::mem::replace(&mut self.mutability, Mutability::Mutable);
                 assert_ne!(
                     self.mode, InternMode::Const,
                     "UnsafeCells are not allowed behind references in constants. This should have \
                     been prevented statically by const qualification. If this were allowed one \
-                    would be able to change a constant at one use site and other use sites may \
-                    arbitrarily decide to change, too.",
+                    would be able to change a constant at one use site and other use sites could \
+                    observe that mutation.",
                 );
                 let walked = self.walk_aggregate(mplace, fields);
                 self.mutability = old;
@@ -145,12 +197,13 @@
             // Handle trait object vtables
             if let Ok(meta) = value.to_meta() {
                 if let ty::Dynamic(..) =
-                    self.ecx.tcx.struct_tail_erasing_lifetimes(referenced_ty, self.param_env).sty
+                    self.ecx.tcx.struct_tail_erasing_lifetimes(
+                        referenced_ty, self.ecx.param_env).sty
                 {
                     if let Ok(vtable) = meta.unwrap().to_ptr() {
                         // explitly choose `Immutable` here, since vtables are immutable, even
                         // if the reference of the fat pointer is mutable
-                        self.intern_shallow(vtable, Mutability::Immutable)?;
+                        self.intern_shallow(vtable.alloc_id, Mutability::Immutable, None)?;
                     }
                 }
             }
@@ -177,7 +230,7 @@
                     (InternMode::Const, hir::Mutability::MutMutable) => {
                         match referenced_ty.sty {
                             ty::Array(_, n)
-                                if n.eval_usize(self.ecx.tcx.tcx, self.param_env) == 0 => {}
+                                if n.eval_usize(self.ecx.tcx.tcx, self.ecx.param_env) == 0 => {}
                             ty::Slice(_)
                                 if value.to_meta().unwrap().unwrap().to_usize(self.ecx)? == 0 => {}
                             _ => bug!("const qualif failed to prevent mutable references"),
@@ -195,21 +248,13 @@
                     (Mutability::Mutable, hir::Mutability::MutMutable) => Mutability::Mutable,
                     _ => Mutability::Immutable,
                 };
-                // Compute the mutability of the allocation
-                let intern_mutability = intern_mutability(
-                    self.ecx.tcx.tcx,
-                    self.param_env,
-                    mplace.layout.ty,
-                    self.ecx.tcx.span,
-                    mutability,
-                );
                 // Recursing behind references changes the intern mode for constants in order to
                 // cause assertions to trigger if we encounter any `UnsafeCell`s.
                 let mode = match self.mode {
                     InternMode::ConstBase => InternMode::Const,
                     other => other,
                 };
-                match self.intern_shallow(ptr, intern_mutability)? {
+                match self.intern_shallow(ptr.alloc_id, mutability, Some(mplace.layout.ty))? {
                     // No need to recurse, these are interned already and statics may have
                     // cycles, so we don't want to recurse there
                     Some(IsStaticOrFn) => {},
@@ -224,69 +269,45 @@
     }
 }
 
-/// Figure out the mutability of the allocation.
-/// Mutable if it has interior mutability *anywhere* in the type.
-fn intern_mutability<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    param_env: ParamEnv<'tcx>,
-    ty: Ty<'tcx>,
-    span: Span,
-    mutability: Mutability,
-) -> Mutability {
-    let has_interior_mutability = !ty.is_freeze(tcx, param_env, span);
-    if has_interior_mutability {
-        Mutability::Mutable
-    } else {
-        mutability
-    }
-}
-
 pub fn intern_const_alloc_recursive(
     ecx: &mut CompileTimeEvalContext<'mir, 'tcx>,
     def_id: DefId,
     ret: MPlaceTy<'tcx>,
-    // FIXME(oli-obk): can we scrap the param env? I think we can, the final value of a const eval
-    // must always be monomorphic, right?
-    param_env: ty::ParamEnv<'tcx>,
 ) -> InterpResult<'tcx> {
     let tcx = ecx.tcx;
     // this `mutability` is the mutability of the place, ignoring the type
-    let (mutability, base_intern_mode) = match tcx.static_mutability(def_id) {
+    let (base_mutability, base_intern_mode) = match tcx.static_mutability(def_id) {
         Some(hir::Mutability::MutImmutable) => (Mutability::Immutable, InternMode::Static),
-        None => (Mutability::Immutable, InternMode::ConstBase),
         // `static mut` doesn't care about interior mutability, it's mutable anyway
         Some(hir::Mutability::MutMutable) => (Mutability::Mutable, InternMode::Static),
+        // consts, promoteds. FIXME: what about array lengths, array initializers?
+        None => (Mutability::Immutable, InternMode::ConstBase),
     };
 
-    // type based interning
-    let mut ref_tracking = RefTracking::new((ret, mutability, base_intern_mode));
-    let leftover_relocations = &mut FxHashSet::default();
-
-    // This mutability is the combination of the place mutability and the type mutability. If either
-    // is mutable, `alloc_mutability` is mutable. This exists because the entire allocation needs
-    // to be mutable if it contains an `UnsafeCell` anywhere. The other `mutability` exists so that
-    // the visitor does not treat everything outside the `UnsafeCell` as mutable.
-    let alloc_mutability = intern_mutability(
-        tcx.tcx, param_env, ret.layout.ty, tcx.span, mutability,
-    );
+    // Type based interning.
+    // `ref_tracking` tracks typed references we have seen and still need to crawl for
+    // more typed information inside them.
+    // `leftover_allocations` collects *all* allocations we see, because some might not
+    // be available in a typed way. They get interned at the end.
+    let mut ref_tracking = RefTracking::new((ret, base_mutability, base_intern_mode));
+    let leftover_allocations = &mut FxHashSet::default();
 
     // start with the outermost allocation
-    InternVisitor {
-        ref_tracking: &mut ref_tracking,
+    intern_shallow(
         ecx,
-        mode: base_intern_mode,
-        leftover_relocations,
-        param_env,
-        mutability,
-    }.intern_shallow(ret.ptr.to_ptr()?, alloc_mutability)?;
+        leftover_allocations,
+        base_intern_mode,
+        ret.ptr.to_ptr()?.alloc_id,
+        base_mutability,
+        Some(ret.layout.ty)
+    )?;
 
     while let Some(((mplace, mutability, mode), _)) = ref_tracking.todo.pop() {
         let interned = InternVisitor {
             ref_tracking: &mut ref_tracking,
             ecx,
             mode,
-            leftover_relocations,
-            param_env,
+            leftover_allocations,
             mutability,
         }.visit_value(mplace);
         if let Err(error) = interned {
@@ -309,15 +330,23 @@
     // Intern the rest of the allocations as mutable. These might be inside unions, padding, raw
     // pointers, ... So we can't intern them according to their type rules
 
-    let mut todo: Vec<_> = leftover_relocations.iter().cloned().collect();
+    let mut todo: Vec<_> = leftover_allocations.iter().cloned().collect();
     while let Some(alloc_id) = todo.pop() {
-        if let Some((_, alloc)) = ecx.memory_mut().alloc_map.remove(&alloc_id) {
-            // We can't call the `intern` method here, as its logic is tailored to safe references.
-            // So we hand-roll the interning logic here again
+        if let Some((_, mut alloc)) = ecx.memory_mut().alloc_map.remove(&alloc_id) {
+            // We can't call the `intern_shallow` method here, as its logic is tailored to safe
+            // references and a `leftover_allocations` set (where we only have a todo-list here).
+            // So we hand-roll the interning logic here again.
+            if base_intern_mode != InternMode::Static {
+                // If it's not a static, it *must* be immutable.
+                // We cannot have mutable memory inside a constant.
+                // FIXME: ideally we would assert that they already are immutable, to double-
+                // check our static checks.
+                alloc.mutability = Mutability::Immutable;
+            }
             let alloc = tcx.intern_const_alloc(alloc);
             tcx.alloc_map.lock().set_alloc_id_memory(alloc_id, alloc);
             for &(_, ((), reloc)) in alloc.relocations().iter() {
-                if leftover_relocations.insert(reloc) {
+                if leftover_allocations.insert(reloc) {
                     todo.push(reloc);
                 }
             }
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index 0f2305e..ec09e69 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -5,17 +5,18 @@
 use syntax::symbol::Symbol;
 use rustc::ty;
 use rustc::ty::layout::{LayoutOf, Primitive, Size};
+use rustc::ty::subst::SubstsRef;
+use rustc::hir::def_id::DefId;
+use rustc::ty::TyCtxt;
 use rustc::mir::BinOp;
-use rustc::mir::interpret::{InterpResult, Scalar};
+use rustc::mir::interpret::{InterpResult, Scalar, GlobalId, ConstValue};
 
 use super::{
-    Machine, PlaceTy, OpTy, InterpCx, Immediate,
+    Machine, PlaceTy, OpTy, InterpCx,
 };
 
 mod type_name;
 
-pub use type_name::*;
-
 fn numeric_intrinsic<'tcx, Tag>(
     name: &str,
     bits: u128,
@@ -37,6 +38,50 @@
     Ok(Scalar::from_uint(bits_out, size))
 }
 
+/// The logic for all nullary intrinsics is implemented here. These intrinsics don't get evaluated
+/// inside an `InterpCx` and instead have their value computed directly from rustc internal info.
+crate fn eval_nullary_intrinsic<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    def_id: DefId,
+    substs: SubstsRef<'tcx>,
+) -> InterpResult<'tcx, &'tcx ty::Const<'tcx>> {
+    let tp_ty = substs.type_at(0);
+    let name = &*tcx.item_name(def_id).as_str();
+    Ok(match name {
+        "type_name" => {
+            let alloc = type_name::alloc_type_name(tcx, tp_ty);
+            tcx.mk_const(ty::Const {
+                val: ConstValue::Slice {
+                    data: alloc,
+                    start: 0,
+                    end: alloc.len(),
+                },
+                ty: tcx.mk_static_str(),
+            })
+        },
+        "needs_drop" => ty::Const::from_bool(tcx, tp_ty.needs_drop(tcx, param_env)),
+        "size_of" |
+        "min_align_of" |
+        "pref_align_of" => {
+            let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(e)))?;
+            let n = match name {
+                "pref_align_of" => layout.align.pref.bytes(),
+                "min_align_of" => layout.align.abi.bytes(),
+                "size_of" => layout.size.bytes(),
+                _ => bug!(),
+            };
+            ty::Const::from_usize(tcx, n)
+        },
+        "type_id" => ty::Const::from_bits(
+            tcx,
+            tcx.type_id_hash(tp_ty).into(),
+            param_env.and(tcx.types.u64),
+        ),
+        other => bug!("`{}` is not a zero arg intrinsic", other),
+    })
+}
+
 impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     /// Returns `true` if emulation happened.
     pub fn emulate_intrinsic(
@@ -49,41 +94,19 @@
 
         let intrinsic_name = &self.tcx.item_name(instance.def_id()).as_str()[..];
         match intrinsic_name {
-            "min_align_of" => {
-                let elem_ty = substs.type_at(0);
-                let elem_align = self.layout_of(elem_ty)?.align.abi.bytes();
-                let align_val = Scalar::from_uint(elem_align, dest.layout.size);
-                self.write_scalar(align_val, dest)?;
-            }
-
-            "needs_drop" => {
-                let ty = substs.type_at(0);
-                let ty_needs_drop = ty.needs_drop(self.tcx.tcx, self.param_env);
-                let val = Scalar::from_bool(ty_needs_drop);
-                self.write_scalar(val, dest)?;
-            }
-
-            "size_of" => {
-                let ty = substs.type_at(0);
-                let size = self.layout_of(ty)?.size.bytes() as u128;
-                let size_val = Scalar::from_uint(size, dest.layout.size);
-                self.write_scalar(size_val, dest)?;
-            }
-
-            "type_id" => {
-                let ty = substs.type_at(0);
-                let type_id = self.tcx.type_id_hash(ty) as u128;
-                let id_val = Scalar::from_uint(type_id, dest.layout.size);
-                self.write_scalar(id_val, dest)?;
-            }
-
+            "min_align_of" |
+            "pref_align_of" |
+            "needs_drop" |
+            "size_of" |
+            "type_id" |
             "type_name" => {
-                let alloc = alloc_type_name(self.tcx.tcx, substs.type_at(0));
-                let name_id = self.tcx.alloc_map.lock().create_memory_alloc(alloc);
-                let id_ptr = self.memory.tag_static_base_pointer(name_id.into());
-                let alloc_len = alloc.size.bytes();
-                let name_val = Immediate::new_slice(Scalar::Ptr(id_ptr), alloc_len, self);
-                self.write_immediate(name_val, dest)?;
+                let gid = GlobalId {
+                    instance,
+                    promoted: None,
+                };
+                let val = self.tcx.const_eval(self.param_env.and(gid))?;
+                let val = self.eval_const_to_op(val, None)?;
+                self.copy_op(val, dest)?;
             }
 
             | "ctpop"
diff --git a/src/librustc_mir/interpret/intrinsics/type_name.rs b/src/librustc_mir/interpret/intrinsics/type_name.rs
index 032d16a..1e765a4 100644
--- a/src/librustc_mir/interpret/intrinsics/type_name.rs
+++ b/src/librustc_mir/interpret/intrinsics/type_name.rs
@@ -7,7 +7,7 @@
 use rustc::hir::map::{DefPathData, DisambiguatedDefPathData};
 use rustc::hir::def_id::CrateNum;
 use std::fmt::Write;
-use rustc::mir::interpret::{Allocation, ConstValue};
+use rustc::mir::interpret::Allocation;
 
 struct AbsolutePathPrinter<'tcx> {
     tcx: TyCtxt<'tcx>,
@@ -213,22 +213,11 @@
     }
 }
 
-/// Produces an absolute path representation of the given type. See also the documentation on
-/// `std::any::type_name`
-pub fn type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx ty::Const<'tcx> {
-    let alloc = alloc_type_name(tcx, ty);
-    tcx.mk_const(ty::Const {
-        val: ConstValue::Slice {
-            data: alloc,
-            start: 0,
-            end: alloc.len(),
-        },
-        ty: tcx.mk_static_str(),
-    })
-}
-
 /// Directly returns an `Allocation` containing an absolute path representation of the given type.
-pub(super) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx Allocation {
+crate fn alloc_type_name<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    ty: Ty<'tcx>
+) -> &'tcx Allocation {
     let path = AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path;
     let alloc = Allocation::from_byte_aligned_bytes(path.into_bytes());
     tcx.intern_const_alloc(alloc)
diff --git a/src/librustc_mir/interpret/mod.rs b/src/librustc_mir/interpret/mod.rs
index 45d2434..0c61be2 100644
--- a/src/librustc_mir/interpret/mod.rs
+++ b/src/librustc_mir/interpret/mod.rs
@@ -34,6 +34,6 @@
 
 pub use self::validity::RefTracking;
 
-pub(super) use self::intrinsics::type_name;
-
 pub use self::intern::intern_const_alloc_recursive;
+
+crate use self::intrinsics::eval_nullary_intrinsic;
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index f27db35..034ad5b 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -59,5 +59,4 @@
         let (param_env, (value, field)) = param_env_and_value.into_parts();
         const_eval::const_field(tcx, param_env, None, field, value)
     };
-    providers.type_name = interpret::type_name;
 }
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index f8af9b9..39aa5c7 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -407,8 +407,9 @@
         place: &Place<'tcx>,
         is_mut_use: bool,
     ) {
-        for (i, elem) in place.projection.iter().enumerate().rev() {
-            let proj_base = &place.projection[..i];
+        let mut cursor = &*place.projection;
+        while let [proj_base @ .., elem] = cursor {
+            cursor = proj_base;
 
             match elem {
                 ProjectionElem::Field(..) => {
diff --git a/src/librustc_mir/util/alignment.rs b/src/librustc_mir/util/alignment.rs
index b4c97f9..a75c1af 100644
--- a/src/librustc_mir/util/alignment.rs
+++ b/src/librustc_mir/util/alignment.rs
@@ -38,8 +38,9 @@
 where
     L: HasLocalDecls<'tcx>,
 {
-    for (i, elem) in place.projection.iter().enumerate().rev() {
-        let proj_base = &place.projection[..i];
+    let mut cursor = &*place.projection;
+    while let [proj_base @ .., elem] = cursor {
+        cursor = proj_base;
 
         match elem {
             // encountered a Deref, which is ABI-aligned
diff --git a/src/librustc_msan/build.rs b/src/librustc_msan/build.rs
index de1676f..a81786e 100644
--- a/src/librustc_msan/build.rs
+++ b/src/librustc_msan/build.rs
@@ -4,6 +4,7 @@
 use cmake::Config;
 
 fn main() {
+    println!("cargo:rerun-if-env-changed=RUSTC_BUILD_SANITIZERS");
     if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) {
         return;
     }
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index f97fcb0..74f68e5 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -40,7 +40,7 @@
 use syntax::ext::hygiene::{ExpnId, Transparency, SyntaxContext};
 use syntax::ast::{self, Name, NodeId, Ident, FloatTy, IntTy, UintTy};
 use syntax::ext::base::{SyntaxExtension, MacroKind, SpecialDerives};
-use syntax::symbol::{Symbol, kw, sym};
+use syntax::symbol::{kw, sym};
 
 use syntax::visit::{self, Visitor};
 use syntax::attr;
@@ -241,7 +241,7 @@
 
     fn names_to_string(segments: &[Segment]) -> String {
         names_to_string(&segments.iter()
-                            .map(|seg| seg.ident)
+                            .map(|seg| seg.ident.name)
                             .collect::<Vec<_>>())
     }
 }
@@ -951,7 +951,7 @@
     struct_constructors: DefIdMap<(Res, ty::Visibility)>,
 
     /// Features enabled for this crate.
-    active_features: FxHashSet<Symbol>,
+    active_features: FxHashSet<Name>,
 
     /// Stores enum visibilities to properly build a reduced graph
     /// when visiting the correspondent variants.
@@ -1018,8 +1018,8 @@
     fn resolve_str_path(
         &mut self,
         span: Span,
-        crate_root: Option<Symbol>,
-        components: &[Symbol],
+        crate_root: Option<Name>,
+        components: &[Name],
         ns: Namespace,
     ) -> (ast::Path, Res) {
         let root = if crate_root.is_some() {
@@ -2555,7 +2555,7 @@
     fn add_suggestion_for_rename_of_use(
         &self,
         err: &mut DiagnosticBuilder<'_>,
-        name: Symbol,
+        name: Name,
         directive: &ImportDirective<'_>,
         binding_span: Span,
     ) {
@@ -2770,22 +2770,22 @@
     }
 }
 
-fn names_to_string(idents: &[Ident]) -> String {
+fn names_to_string(names: &[Name]) -> String {
     let mut result = String::new();
-    for (i, ident) in idents.iter()
-                            .filter(|ident| ident.name != kw::PathRoot)
+    for (i, name) in names.iter()
+                            .filter(|name| **name != kw::PathRoot)
                             .enumerate() {
         if i > 0 {
             result.push_str("::");
         }
-        result.push_str(&ident.as_str());
+        result.push_str(&name.as_str());
     }
     result
 }
 
 fn path_names_to_string(path: &Path) -> String {
     names_to_string(&path.segments.iter()
-                        .map(|seg| seg.ident)
+                        .map(|seg| seg.ident.name)
                         .collect::<Vec<_>>())
 }
 
@@ -2793,15 +2793,14 @@
 fn module_to_string(module: Module<'_>) -> Option<String> {
     let mut names = Vec::new();
 
-    fn collect_mod(names: &mut Vec<Ident>, module: Module<'_>) {
+    fn collect_mod(names: &mut Vec<Name>, module: Module<'_>) {
         if let ModuleKind::Def(.., name) = module.kind {
             if let Some(parent) = module.parent {
-                names.push(Ident::with_dummy_span(name));
+                names.push(name);
                 collect_mod(names, parent);
             }
         } else {
-            // danger, shouldn't be ident?
-            names.push(Ident::from_str("<opaque>"));
+            names.push(Name::intern("<opaque>"));
             collect_mod(names, module.parent.unwrap());
         }
     }
@@ -2810,9 +2809,8 @@
     if names.is_empty() {
         return None;
     }
-    Some(names_to_string(&names.into_iter()
-                        .rev()
-                        .collect::<Vec<_>>()))
+    names.reverse();
+    Some(names_to_string(&names))
 }
 
 #[derive(Copy, Clone, Debug)]
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 9096d14..3900a3d 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -323,7 +323,7 @@
         self.check_stability_and_deprecation(&ext, path);
 
         Ok(if ext.macro_kind() != kind {
-            let expected = if kind == MacroKind::Attr { "attribute" } else { kind.descr() };
+            let expected = kind.descr_expected();
             let msg = format!("expected {}, found {} `{}`", expected, res.descr(), path);
             self.session.struct_span_err(path.span, &msg)
                         .span_label(path.span, format!("not {} {}", kind.article(), expected))
@@ -774,9 +774,8 @@
                 }
                 Err(..) => {
                     assert!(initial_binding.is_none());
-                    let bang = if kind == MacroKind::Bang { "!" } else { "" };
-                    let msg =
-                        format!("cannot find {} `{}{}` in this scope", kind.descr(), ident, bang);
+                    let expected = kind.descr_expected();
+                    let msg = format!("cannot find {} `{}` in this scope", expected, ident);
                     let mut err = self.session.struct_span_err(ident.span, &msg);
                     self.unresolved_macro_suggestions(&mut err, kind, &parent_scope, ident);
                     err.emit();
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index eb509f1..e77e829 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -1433,15 +1433,17 @@
     let global = !names.is_empty() && names[0].name == kw::PathRoot;
     if let Some(pos) = pos {
         let names = if global { &names[1..pos + 1] } else { &names[..pos + 1] };
-        names_to_string(names)
+        names_to_string(&names.iter().map(|ident| ident.name).collect::<Vec<_>>())
     } else {
         let names = if global { &names[1..] } else { names };
         if names.is_empty() {
             import_directive_subclass_to_string(subclass)
         } else {
-            format!("{}::{}",
-                    names_to_string(names),
-                    import_directive_subclass_to_string(subclass))
+            format!(
+                "{}::{}",
+                names_to_string(&names.iter().map(|ident| ident.name).collect::<Vec<_>>()),
+                import_directive_subclass_to_string(subclass),
+            )
         }
     }
 }
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 12c5ce1..55f6b91 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -130,6 +130,10 @@
         self.save_ctxt.span_from_span(span)
     }
 
+    fn lookup_def_id(&self, ref_id: NodeId) -> Option<DefId> {
+        self.save_ctxt.lookup_def_id(ref_id)
+    }
+
     pub fn dump_crate_info(&mut self, name: &str, krate: &ast::Crate) {
         let source_file = self.tcx.sess.local_crate_source_file.as_ref();
         let crate_root = source_file.map(|source_file| {
@@ -223,13 +227,6 @@
         }
     }
 
-    fn lookup_def_id(&self, ref_id: NodeId) -> Option<DefId> {
-        match self.save_ctxt.get_path_res(ref_id) {
-            Res::PrimTy(..) | Res::SelfTy(..) | Res::Err => None,
-            def => Some(def.def_id()),
-        }
-    }
-
     fn process_formals(&mut self, formals: &'l [ast::Param], qualname: &str) {
         for arg in formals {
             self.visit_pat(&arg.pat);
@@ -283,36 +280,32 @@
     ) {
         debug!("process_method: {}:{}", id, ident);
 
-        if let Some(mut method_data) = self.save_ctxt.get_method_data(id, ident, span) {
-            let sig_str = crate::make_signature(&sig.decl, &generics);
-            if body.is_some() {
-                self.nest_tables(
-                    id,
-                    |v| v.process_formals(&sig.decl.inputs, &method_data.qualname),
-                );
+        let hir_id = self.tcx.hir().node_to_hir_id(id);
+        self.nest_tables(id, |v| {
+            if let Some(mut method_data) = v.save_ctxt.get_method_data(id, ident, span) {
+                v.process_formals(&sig.decl.inputs, &method_data.qualname);
+                v.process_generic_params(&generics, &method_data.qualname, id);
+
+                method_data.value = crate::make_signature(&sig.decl, &generics);
+                method_data.sig = sig::method_signature(id, ident, generics, sig, &v.save_ctxt);
+
+                v.dumper.dump_def(&access_from_vis!(v.save_ctxt, vis, hir_id), method_data);
             }
 
-            self.process_generic_params(&generics, &method_data.qualname, id);
+            // walk arg and return types
+            for arg in &sig.decl.inputs {
+                v.visit_ty(&arg.ty);
+            }
 
-            method_data.value = sig_str;
-            method_data.sig = sig::method_signature(id, ident, generics, sig, &self.save_ctxt);
-            let hir_id = self.tcx.hir().node_to_hir_id(id);
-            self.dumper.dump_def(&access_from_vis!(self.save_ctxt, vis, hir_id), method_data);
-        }
+            if let ast::FunctionRetTy::Ty(ref ret_ty) = sig.decl.output {
+                v.visit_ty(ret_ty);
+            }
 
-        // walk arg and return types
-        for arg in &sig.decl.inputs {
-            self.visit_ty(&arg.ty);
-        }
-
-        if let ast::FunctionRetTy::Ty(ref ret_ty) = sig.decl.output {
-            self.visit_ty(ret_ty);
-        }
-
-        // walk the fn body
-        if let Some(body) = body {
-            self.nest_tables(id, |v| v.visit_block(body));
-        }
+            // walk the fn body
+            if let Some(body) = body {
+                v.visit_block(body);
+            }
+        });
     }
 
     fn process_struct_field_def(&mut self, field: &ast::StructField, parent_id: NodeId) {
@@ -377,26 +370,31 @@
         ty_params: &'l ast::Generics,
         body: &'l ast::Block,
     ) {
-        if let Some(fn_data) = self.save_ctxt.get_item_data(item) {
-            down_cast_data!(fn_data, DefData, item.span);
-            self.nest_tables(
-                item.id,
-                |v| v.process_formals(&decl.inputs, &fn_data.qualname),
-            );
-            self.process_generic_params(ty_params, &fn_data.qualname, item.id);
-            let hir_id = self.tcx.hir().node_to_hir_id(item.id);
-            self.dumper.dump_def(&access_from!(self.save_ctxt, item, hir_id), fn_data);
-        }
+        let hir_id = self.tcx.hir().node_to_hir_id(item.id);
+        self.nest_tables(item.id, |v| {
+            if let Some(fn_data) = v.save_ctxt.get_item_data(item) {
+                down_cast_data!(fn_data, DefData, item.span);
+                v.process_formals(&decl.inputs, &fn_data.qualname);
+                v.process_generic_params(ty_params, &fn_data.qualname, item.id);
 
-        for arg in &decl.inputs {
-            self.visit_ty(&arg.ty);
-        }
+                v.dumper.dump_def(&access_from!(v.save_ctxt, item, hir_id), fn_data);
+            }
 
-        if let ast::FunctionRetTy::Ty(ref ret_ty) = decl.output {
-            self.visit_ty(&ret_ty);
-        }
+            for arg in &decl.inputs {
+                v.visit_ty(&arg.ty)
+            }
 
-        self.nest_tables(item.id, |v| v.visit_block(&body));
+            if let ast::FunctionRetTy::Ty(ref ret_ty) = decl.output {
+                if let ast::TyKind::ImplTrait(..) = ret_ty.node {
+                    // FIXME: Opaque type desugaring prevents us from easily
+                    // processing trait bounds. See `visit_ty` for more details.
+                } else {
+                    v.visit_ty(&ret_ty);
+                }
+            }
+
+            v.visit_block(&body);
+        });
     }
 
     fn process_static_or_const_item(
@@ -1113,11 +1111,7 @@
                 // FIXME: uses of the assoc type should ideally point to this
                 // 'def' and the name here should be a ref to the def in the
                 // trait.
-                for bound in bounds.iter() {
-                    if let ast::GenericBound::Trait(trait_ref, _) = bound {
-                        self.process_path(trait_ref.trait_ref.ref_id, &trait_ref.trait_ref.path)
-                    }
-                }
+                self.process_bounds(&bounds);
             }
             ast::ImplItemKind::Macro(_) => {}
         }
@@ -1364,10 +1358,10 @@
                 self.visit_ty(&ty);
                 self.process_generic_params(ty_params, &qualname, item.id);
             }
-            OpaqueTy(ref _bounds, ref ty_params) => {
+            OpaqueTy(ref bounds, ref ty_params) => {
                 let qualname = format!("::{}",
                     self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id)));
-                // FIXME do something with _bounds
+
                 let value = String::new();
                 if !self.span.filter_generated(item.ident.span) {
                     let span = self.span_from_span(item.ident.span);
@@ -1393,6 +1387,7 @@
                     );
                 }
 
+                self.process_bounds(bounds);
                 self.process_generic_params(ty_params, &qualname, item.id);
             }
             Mac(_) => (),
@@ -1449,6 +1444,18 @@
                 self.visit_ty(element);
                 self.nest_tables(length.id, |v| v.visit_expr(&length.value));
             }
+            ast::TyKind::ImplTrait(id, ref bounds) => {
+                // FIXME: As of writing, the opaque type lowering introduces
+                // another DefPath scope/segment (used to declare the resulting
+                // opaque type item).
+                // However, the synthetic scope does *not* have associated
+                // typeck tables, which means we can't nest it and we fire an
+                // assertion when resolving the qualified type paths in trait
+                // bounds...
+                // This will panic if called on return type `impl Trait`, which
+                // we guard against in `process_fn`.
+                self.nest_tables(id, |v| v.process_bounds(bounds));
+            }
             _ => visit::walk_ty(self, t),
         }
     }
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 4bc098d..055ccf6 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -312,7 +312,7 @@
                     let impl_id = self.next_impl_id();
                     let span = self.span_from_span(sub_span);
 
-                    let type_data = self.lookup_ref_id(typ.id);
+                    let type_data = self.lookup_def_id(typ.id);
                     type_data.map(|type_data| {
                         Data::RelationData(Relation {
                             kind: RelationKind::Impl {
@@ -322,7 +322,7 @@
                             from: id_from_def_id(type_data),
                             to: trait_ref
                                 .as_ref()
-                                .and_then(|t| self.lookup_ref_id(t.ref_id))
+                                .and_then(|t| self.lookup_def_id(t.ref_id))
                                 .map(id_from_def_id)
                                 .unwrap_or_else(|| null_id()),
                         },
@@ -495,7 +495,7 @@
     }
 
     pub fn get_trait_ref_data(&self, trait_ref: &ast::TraitRef) -> Option<Ref> {
-        self.lookup_ref_id(trait_ref.ref_id).and_then(|def_id| {
+        self.lookup_def_id(trait_ref.ref_id).and_then(|def_id| {
             let span = trait_ref.path.span;
             if generated_code(span) {
                 return None;
@@ -870,7 +870,7 @@
         })
     }
 
-    fn lookup_ref_id(&self, ref_id: NodeId) -> Option<DefId> {
+    fn lookup_def_id(&self, ref_id: NodeId) -> Option<DefId> {
         match self.get_path_res(ref_id) {
             Res::PrimTy(_) | Res::SelfTy(..) | Res::Err => None,
             def => Some(def.def_id()),
diff --git a/src/librustc_tsan/build.rs b/src/librustc_tsan/build.rs
index 6df9691..f9333e1 100644
--- a/src/librustc_tsan/build.rs
+++ b/src/librustc_tsan/build.rs
@@ -4,6 +4,7 @@
 use cmake::Config;
 
 fn main() {
+    println!("cargo:rerun-if-env-changed=RUSTC_BUILD_SANITIZERS");
     if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) {
         return;
     }
diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
index 20442ab..af1d240 100644
--- a/src/libstd/Cargo.toml
+++ b/src/libstd/Cargo.toml
@@ -25,17 +25,11 @@
 unwind = { path = "../libunwind" }
 hashbrown = { version = "0.5.0", features = ['rustc-dep-of-std'] }
 
-[dependencies.backtrace]
+[dependencies.backtrace_rs]
+package = "backtrace"
 version = "0.3.37"
-default-features = false # don't use coresymbolication on OSX
-features = [
-  "rustc-dep-of-std", # enable build support for integrating into libstd
-  "dbghelp",          # backtrace/symbolize on MSVC
-  "libbacktrace",     # symbolize on most platforms
-  "libunwind",        # backtrace on most platforms
-  "dladdr",           # symbolize on platforms w/o libbacktrace
-]
-optional = true
+default-features = false # without the libstd `backtrace` feature, stub out everything
+features = [ "rustc-dep-of-std" ] # enable build support for integrating into libstd
 
 [dev-dependencies]
 rand = "0.7"
@@ -65,6 +59,13 @@
 [features]
 default = ["std_detect_file_io", "std_detect_dlsym_getauxval"]
 
+backtrace = [
+  "backtrace_rs/dbghelp",          # backtrace/symbolize on MSVC
+  "backtrace_rs/libbacktrace",     # symbolize on most platforms
+  "backtrace_rs/libunwind",        # backtrace on most platforms
+  "backtrace_rs/dladdr",           # symbolize on platforms w/o libbacktrace
+]
+
 panic-unwind = ["panic_unwind"]
 profiler = ["profiler_builtins"]
 compiler-builtins-c = ["alloc/compiler-builtins-c"]
diff --git a/src/libstd/backtrace.rs b/src/libstd/backtrace.rs
index 5d46ef7..61c42a5 100644
--- a/src/libstd/backtrace.rs
+++ b/src/libstd/backtrace.rs
@@ -97,6 +97,7 @@
 use crate::sync::Mutex;
 use crate::sys_common::backtrace::{output_filename, lock};
 use crate::vec::Vec;
+use backtrace_rs as backtrace;
 use backtrace::BytesOrWideString;
 
 /// A captured OS thread stack backtrace.
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
index b14e02a..b5265fe 100644
--- a/src/libstd/fs.rs
+++ b/src/libstd/fs.rs
@@ -1956,7 +1956,8 @@
 /// # Platform-specific behavior
 ///
 /// This function currently corresponds to the `opendir` function on Unix
-/// and the `FindFirstFile` function on Windows.
+/// and the `FindFirstFile` function on Windows. Advancing the iterator
+/// currently corresponds to `readdir` on Unix and `FindNextFile` on Windows.
 /// Note that, this [may change in the future][changes].
 ///
 /// [changes]: ../io/index.html#platform-specific-behavior
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index 0386dbd..be364a1 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -2326,10 +2326,10 @@
 /// An iterator over the contents of an instance of `BufRead` split on a
 /// particular byte.
 ///
-/// This struct is generally created by calling [`split`][split] on a
-/// `BufRead`. Please see the documentation of `split()` for more details.
+/// This struct is generally created by calling [`split`] on a `BufRead`.
+/// Please see the documentation of [`split`] for more details.
 ///
-/// [split]: trait.BufRead.html#method.split
+/// [`split`]: trait.BufRead.html#method.split
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Debug)]
 pub struct Split<B> {
@@ -2358,10 +2358,10 @@
 
 /// An iterator over the lines of an instance of `BufRead`.
 ///
-/// This struct is generally created by calling [`lines`][lines] on a
-/// `BufRead`. Please see the documentation of `lines()` for more details.
+/// This struct is generally created by calling [`lines`] on a `BufRead`.
+/// Please see the documentation of [`lines`] for more details.
 ///
-/// [lines]: trait.BufRead.html#method.lines
+/// [`lines`]: trait.BufRead.html#method.lines
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Debug)]
 pub struct Lines<B> {
diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs
index db4089c..28fb402 100644
--- a/src/libstd/panicking.rs
+++ b/src/libstd/panicking.rs
@@ -17,8 +17,7 @@
 use crate::raw;
 use crate::sys::stdio::panic_output;
 use crate::sys_common::rwlock::RWLock;
-use crate::sys_common::thread_info;
-use crate::sys_common::util;
+use crate::sys_common::{thread_info, util, backtrace};
 use crate::thread;
 
 #[cfg(not(test))]
@@ -157,20 +156,18 @@
 }
 
 fn default_hook(info: &PanicInfo<'_>) {
-    #[cfg(feature = "backtrace")]
-    use crate::sys_common::{backtrace as backtrace_mod};
-
     // If this is a double panic, make sure that we print a backtrace
     // for this panic. Otherwise only print it if logging is enabled.
-    #[cfg(feature = "backtrace")]
-    let log_backtrace = {
+    let log_backtrace = if cfg!(feature = "backtrace") {
         let panics = update_panic_count(0);
 
         if panics >= 2 {
-            Some(backtrace::PrintFmt::Full)
+            Some(backtrace_rs::PrintFmt::Full)
         } else {
-            backtrace_mod::log_enabled()
+            backtrace::log_enabled()
         }
+    } else {
+        None
     };
 
     // The current implementation always returns `Some`.
@@ -190,14 +187,13 @@
         let _ = writeln!(err, "thread '{}' panicked at '{}', {}",
                          name, msg, location);
 
-        #[cfg(feature = "backtrace")]
-        {
+        if cfg!(feature = "backtrace") {
             use crate::sync::atomic::{AtomicBool, Ordering};
 
             static FIRST_PANIC: AtomicBool = AtomicBool::new(true);
 
             if let Some(format) = log_backtrace {
-                let _ = backtrace_mod::print(err, format);
+                let _ = backtrace::print(err, format);
             } else if FIRST_PANIC.compare_and_swap(true, false, Ordering::SeqCst) {
                 let _ = writeln!(err, "note: run with `RUST_BACKTRACE=1` \
                                        environment variable to display a backtrace.");
diff --git a/src/libstd/process.rs b/src/libstd/process.rs
index c50025a..b8d57cf 100644
--- a/src/libstd/process.rs
+++ b/src/libstd/process.rs
@@ -422,7 +422,7 @@
 /// // Execute `ls` in the current directory of the program.
 /// list_dir.status().expect("process failed to execute");
 ///
-/// println!("");
+/// println!();
 ///
 /// // Change `ls` to execute in the root directory.
 /// list_dir.current_dir("/");
diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs
index 1a78abf..01711d4 100644
--- a/src/libstd/sys_common/backtrace.rs
+++ b/src/libstd/sys_common/backtrace.rs
@@ -7,10 +7,9 @@
 use crate::borrow::Cow;
 use crate::io::prelude::*;
 use crate::path::{self, Path, PathBuf};
-use crate::sync::atomic::{self, Ordering};
 use crate::sys::mutex::Mutex;
 
-use backtrace::{BacktraceFmt, BytesOrWideString, PrintFmt};
+use backtrace_rs::{BacktraceFmt, BytesOrWideString, PrintFmt};
 
 /// Max number of frames to print.
 const MAX_NB_FRAMES: usize = 100;
@@ -74,14 +73,14 @@
     bt_fmt.add_context()?;
     let mut idx = 0;
     let mut res = Ok(());
-    backtrace::trace_unsynchronized(|frame| {
+    backtrace_rs::trace_unsynchronized(|frame| {
         if print_fmt == PrintFmt::Short && idx > MAX_NB_FRAMES {
             return false;
         }
 
         let mut hit = false;
         let mut stop = false;
-        backtrace::resolve_frame_unsynchronized(frame, |symbol| {
+        backtrace_rs::resolve_frame_unsynchronized(frame, |symbol| {
             hit = true;
             if print_fmt == PrintFmt::Short {
                 if let Some(sym) = symbol.name().and_then(|s| s.as_str()) {
@@ -130,6 +129,8 @@
 // For now logging is turned off by default, and this function checks to see
 // whether the magical environment variable is present to see if it's turned on.
 pub fn log_enabled() -> Option<PrintFmt> {
+    use crate::sync::atomic::{self, Ordering};
+
     // Setting environment variables for Fuchsia components isn't a standard
     // or easily supported workflow. For now, always display backtraces.
     if cfg!(target_os = "fuchsia") {
diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs
index 9190a3b..cba3eca 100644
--- a/src/libstd/sys_common/mod.rs
+++ b/src/libstd/sys_common/mod.rs
@@ -41,7 +41,6 @@
 
 pub mod alloc;
 pub mod at_exit_imp;
-#[cfg(feature = "backtrace")]
 pub mod backtrace;
 pub mod condvar;
 pub mod io;
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 7759a98..384c055 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -977,13 +977,6 @@
         span.with_call_site_ctxt(self.current_expansion.id)
     }
 
-    /// Span with a context reproducing `macro_rules` hygiene (hygienic locals, unhygienic items).
-    /// FIXME: This should be eventually replaced either with `with_def_site_ctxt` (preferably),
-    /// or with `with_call_site_ctxt` (where necessary).
-    pub fn with_legacy_ctxt(&self, span: Span) -> Span {
-        span.with_legacy_ctxt(self.current_expansion.id)
-    }
-
     /// Returns span for the macro which originally caused the current expansion to happen.
     ///
     /// Stops backtracing at include! boundary.
@@ -1081,8 +1074,8 @@
     pub fn set_trace_macros(&mut self, x: bool) {
         self.ecfg.trace_mac = x
     }
-    pub fn ident_of(&self, st: &str) -> ast::Ident {
-        ast::Ident::from_str(st)
+    pub fn ident_of(&self, st: &str, sp: Span) -> ast::Ident {
+        ast::Ident::from_str_and_span(st, sp)
     }
     pub fn std_path(&self, components: &[Symbol]) -> Vec<ast::Ident> {
         let def_site = self.with_def_site_ctxt(DUMMY_SP);
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 06a5531..f1d0e0b 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -363,7 +363,7 @@
         self.expr(sp, ast::ExprKind::Field(expr, ident.with_span_pos(sp)))
     }
     pub fn expr_tup_field_access(&self, sp: Span, expr: P<ast::Expr>, idx: usize) -> P<ast::Expr> {
-        let ident = Ident::from_str(&idx.to_string()).with_span_pos(sp);
+        let ident = Ident::new(sym::integer(idx), sp);
         self.expr(sp, ast::ExprKind::Field(expr, ident))
     }
     pub fn expr_addr_of(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> {
@@ -525,7 +525,7 @@
         let err = self.std_path(&[sym::result, sym::Result, sym::Err]);
         let err_path = self.path_global(sp, err);
 
-        let binding_variable = self.ident_of("__try_var");
+        let binding_variable = self.ident_of("__try_var", sp);
         let binding_pat = self.pat_ident(sp, binding_variable);
         let binding_expr = self.expr_ident(sp, binding_variable);
 
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index 46ffa52..b27e9c5 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -877,9 +877,9 @@
         // Now `last` holds the complete set of NT tokens that could
         // end the sequence before SUFFIX. Check that every one works with `suffix`.
         'each_last: for token in &last.tokens {
-            if let TokenTree::MetaVarDecl(_, ref name, ref frag_spec) = *token {
+            if let TokenTree::MetaVarDecl(_, name, frag_spec) = *token {
                 for next_token in &suffix_first.tokens {
-                    match is_in_follow(next_token, &frag_spec.as_str()) {
+                    match is_in_follow(next_token, frag_spec.name) {
                         IsInFollow::Invalid(msg, help) => {
                             sess.span_diagnostic
                                 .struct_span_err(next_token.span(), &msg)
@@ -948,7 +948,7 @@
 
 fn token_can_be_followed_by_any(tok: &quoted::TokenTree) -> bool {
     if let quoted::TokenTree::MetaVarDecl(_, _, frag_spec) = *tok {
-        frag_can_be_followed_by_any(&frag_spec.as_str())
+        frag_can_be_followed_by_any(frag_spec.name)
     } else {
         // (Non NT's can always be followed by anthing in matchers.)
         true
@@ -963,15 +963,15 @@
 /// specifier which consumes at most one token tree can be followed by
 /// a fragment specifier (indeed, these fragments can be followed by
 /// ANYTHING without fear of future compatibility hazards).
-fn frag_can_be_followed_by_any(frag: &str) -> bool {
+fn frag_can_be_followed_by_any(frag: Symbol) -> bool {
     match frag {
-        "item"     | // always terminated by `}` or `;`
-        "block"    | // exactly one token tree
-        "ident"    | // exactly one token tree
-        "literal"  | // exactly one token tree
-        "meta"     | // exactly one token tree
-        "lifetime" | // exactly one token tree
-        "tt" =>   // exactly one token tree
+        sym::item     | // always terminated by `}` or `;`
+        sym::block    | // exactly one token tree
+        sym::ident    | // exactly one token tree
+        sym::literal  | // exactly one token tree
+        sym::meta     | // exactly one token tree
+        sym::lifetime | // exactly one token tree
+        sym::tt =>   // exactly one token tree
             true,
 
         _ =>
@@ -993,7 +993,7 @@
 /// break macros that were relying on that binary operator as a
 /// separator.
 // when changing this do not forget to update doc/book/macros.md!
-fn is_in_follow(tok: &quoted::TokenTree, frag: &str) -> IsInFollow {
+fn is_in_follow(tok: &quoted::TokenTree, frag: Symbol) -> IsInFollow {
     use quoted::TokenTree;
 
     if let TokenTree::Token(Token { kind: token::CloseDelim(_), .. }) = *tok {
@@ -1002,17 +1002,17 @@
         IsInFollow::Yes
     } else {
         match frag {
-            "item" => {
+            sym::item => {
                 // since items *must* be followed by either a `;` or a `}`, we can
                 // accept anything after them
                 IsInFollow::Yes
             }
-            "block" => {
+            sym::block => {
                 // anything can follow block, the braces provide an easy boundary to
                 // maintain
                 IsInFollow::Yes
             }
-            "stmt" | "expr" => {
+            sym::stmt | sym::expr => {
                 const TOKENS: &[&str] = &["`=>`", "`,`", "`;`"];
                 match tok {
                     TokenTree::Token(token) => match token.kind {
@@ -1022,7 +1022,7 @@
                     _ => IsInFollow::No(TOKENS),
                 }
             }
-            "pat" => {
+            sym::pat => {
                 const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`|`", "`if`", "`in`"];
                 match tok {
                     TokenTree::Token(token) => match token.kind {
@@ -1033,7 +1033,7 @@
                     _ => IsInFollow::No(TOKENS),
                 }
             }
-            "path" | "ty" => {
+            sym::path | sym::ty => {
                 const TOKENS: &[&str] = &[
                     "`{`", "`[`", "`=>`", "`,`", "`>`", "`=`", "`:`", "`;`", "`|`", "`as`",
                     "`where`",
@@ -1061,20 +1061,20 @@
                     _ => IsInFollow::No(TOKENS),
                 }
             }
-            "ident" | "lifetime" => {
+            sym::ident | sym::lifetime => {
                 // being a single token, idents and lifetimes are harmless
                 IsInFollow::Yes
             }
-            "literal" => {
+            sym::literal => {
                 // literals may be of a single token, or two tokens (negative numbers)
                 IsInFollow::Yes
             }
-            "meta" | "tt" => {
+            sym::meta | sym::tt => {
                 // being either a single token or a delimited sequence, tt is
                 // harmless
                 IsInFollow::Yes
             }
-            "vis" => {
+            sym::vis => {
                 // Explicitly disallow `priv`, on the off chance it comes back.
                 const TOKENS: &[&str] = &["`,`", "an ident", "a type"];
                 match tok {
@@ -1099,7 +1099,7 @@
                     _ => IsInFollow::No(TOKENS),
                 }
             }
-            "" => IsInFollow::Yes, // kw::Invalid
+            kw::Invalid => IsInFollow::Yes,
             _ => IsInFollow::Invalid(
                 format!("invalid fragment specifier `{}`", frag),
                 VALID_FRAGMENT_NAMES_MSG,
diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs
index baae615..cf19664 100644
--- a/src/libsyntax/parse/parser/item.rs
+++ b/src/libsyntax/parse/parser/item.rs
@@ -1256,7 +1256,7 @@
             for part in idents {
                 fixed_name.push_str(&format!("_{}", part.name));
             }
-            ident = Ident::from_str(&fixed_name).with_span_pos(fixed_name_sp);
+            ident = Ident::from_str_and_span(&fixed_name, fixed_name_sp);
 
             self.struct_span_err(fixed_name_sp, error_msg)
                 .span_label(fixed_name_sp, "dash-separated idents are not valid")
diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs
index 328b307..75d727b 100644
--- a/src/libsyntax_ext/asm.rs
+++ b/src/libsyntax_ext/asm.rs
@@ -62,7 +62,7 @@
     MacEager::expr(P(ast::Expr {
         id: ast::DUMMY_NODE_ID,
         node: ast::ExprKind::InlineAsm(P(inline_asm)),
-        span: cx.with_legacy_ctxt(sp),
+        span: cx.with_def_site_ctxt(sp),
         attrs: ThinVec::new(),
     }))
 }
diff --git a/src/libsyntax_ext/assert.rs b/src/libsyntax_ext/assert.rs
index 001996e..cbfe14f 100644
--- a/src/libsyntax_ext/assert.rs
+++ b/src/libsyntax_ext/assert.rs
@@ -23,7 +23,9 @@
         }
     };
 
-    let sp = cx.with_legacy_ctxt(sp);
+    // `core::panic` and `std::panic` are different macros, so we use call-site
+    // context to pick up whichever is currently in scope.
+    let sp = cx.with_call_site_ctxt(sp);
     let panic_call = Mac {
         path: Path::from_ident(Ident::new(sym::panic, sp)),
         tts: custom_message.unwrap_or_else(|| {
diff --git a/src/libsyntax_ext/cfg.rs b/src/libsyntax_ext/cfg.rs
index 0342e44..3c33baf 100644
--- a/src/libsyntax_ext/cfg.rs
+++ b/src/libsyntax_ext/cfg.rs
@@ -16,7 +16,7 @@
     sp: Span,
     tts: TokenStream,
 ) -> Box<dyn base::MacResult + 'static> {
-    let sp = cx.with_legacy_ctxt(sp);
+    let sp = cx.with_def_site_ctxt(sp);
 
     match parse_cfg(cx, sp, tts) {
         Ok(cfg) => {
diff --git a/src/libsyntax_ext/concat.rs b/src/libsyntax_ext/concat.rs
index fc56dff..16f0160 100644
--- a/src/libsyntax_ext/concat.rs
+++ b/src/libsyntax_ext/concat.rs
@@ -59,6 +59,6 @@
     } else if has_errors {
         return DummyResult::any(sp);
     }
-    let sp = cx.with_legacy_ctxt(sp);
+    let sp = cx.with_def_site_ctxt(sp);
     base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&accumulator)))
 }
diff --git a/src/libsyntax_ext/concat_idents.rs b/src/libsyntax_ext/concat_idents.rs
index 6391b62..f344706 100644
--- a/src/libsyntax_ext/concat_idents.rs
+++ b/src/libsyntax_ext/concat_idents.rs
@@ -39,7 +39,7 @@
         }
     }
 
-    let ident = ast::Ident::new(Symbol::intern(&res_str), cx.with_legacy_ctxt(sp));
+    let ident = ast::Ident::new(Symbol::intern(&res_str), cx.with_call_site_ctxt(sp));
 
     struct ConcatIdentsResult { ident: ast::Ident }
 
diff --git a/src/libsyntax_ext/deriving/cmp/partial_ord.rs b/src/libsyntax_ext/deriving/cmp/partial_ord.rs
index debdc30..13d63aa 100644
--- a/src/libsyntax_ext/deriving/cmp/partial_ord.rs
+++ b/src/libsyntax_ext/deriving/cmp/partial_ord.rs
@@ -109,7 +109,7 @@
         GtOp => "gt",
         GeOp => "ge",
     };
-    cx.expr_method_call(span, lft, ast::Ident::from_str_and_span(op_str, span), vec![rgt])
+    cx.expr_method_call(span, lft, cx.ident_of(op_str, span), vec![rgt])
 }
 
 pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P<Expr> {
diff --git a/src/libsyntax_ext/deriving/debug.rs b/src/libsyntax_ext/deriving/debug.rs
index 781645a..088b61b 100644
--- a/src/libsyntax_ext/deriving/debug.rs
+++ b/src/libsyntax_ext/deriving/debug.rs
@@ -62,7 +62,7 @@
     // We want to make sure we have the ctxt set so that we can use unstable methods
     let span = cx.with_def_site_ctxt(span);
     let name = cx.expr_lit(span, ast::LitKind::Str(ident.name, ast::StrStyle::Cooked));
-    let builder = Ident::from_str_and_span("debug_trait_builder", span);
+    let builder = cx.ident_of("debug_trait_builder", span);
     let builder_expr = cx.expr_ident(span, builder.clone());
 
     let fmt = substr.nonself_args[0].clone();
@@ -72,7 +72,7 @@
         ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => {
             // tuple struct/"normal" variant
             let expr =
-                cx.expr_method_call(span, fmt, Ident::from_str("debug_tuple"), vec![name]);
+                cx.expr_method_call(span, fmt, cx.ident_of("debug_tuple", span), vec![name]);
             stmts.push(cx.stmt_let(span, true, builder, expr));
 
             for field in fields {
@@ -93,7 +93,7 @@
         ast::VariantData::Struct(..) => {
             // normal struct/struct variant
             let expr =
-                cx.expr_method_call(span, fmt, Ident::from_str("debug_struct"), vec![name]);
+                cx.expr_method_call(span, fmt, cx.ident_of("debug_struct", span), vec![name]);
             stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr));
 
             for field in fields {
@@ -113,7 +113,7 @@
         }
     }
 
-    let expr = cx.expr_method_call(span, builder_expr, Ident::from_str("finish"), vec![]);
+    let expr = cx.expr_method_call(span, builder_expr, cx.ident_of("finish", span), vec![]);
 
     stmts.push(cx.stmt_expr(expr));
     let block = cx.block(span, stmts);
diff --git a/src/libsyntax_ext/deriving/decodable.rs b/src/libsyntax_ext/deriving/decodable.rs
index d3d604b..cde72ab 100644
--- a/src/libsyntax_ext/deriving/decodable.rs
+++ b/src/libsyntax_ext/deriving/decodable.rs
@@ -66,10 +66,14 @@
                           krate: &str)
                           -> P<Expr> {
     let decoder = substr.nonself_args[0].clone();
-    let recurse = vec![cx.ident_of(krate), cx.ident_of("Decodable"), cx.ident_of("decode")];
+    let recurse = vec![
+        cx.ident_of(krate, trait_span),
+        cx.ident_of("Decodable", trait_span),
+        cx.ident_of("decode", trait_span),
+    ];
     let exprdecode = cx.expr_path(cx.path_global(trait_span, recurse));
     // throw an underscore in front to suppress unused variable warnings
-    let blkarg = cx.ident_of("_d");
+    let blkarg = cx.ident_of("_d", trait_span);
     let blkdecoder = cx.expr_ident(trait_span, blkarg);
 
     return match *substr.fields {
@@ -78,7 +82,7 @@
                 Unnamed(ref fields, _) => fields.len(),
                 Named(ref fields) => fields.len(),
             };
-            let read_struct_field = cx.ident_of("read_struct_field");
+            let read_struct_field = cx.ident_of("read_struct_field", trait_span);
 
             let path = cx.path_ident(trait_span, substr.type_ident);
             let result =
@@ -94,17 +98,17 @@
             let result = cx.expr_ok(trait_span, result);
             cx.expr_method_call(trait_span,
                                 decoder,
-                                cx.ident_of("read_struct"),
+                                cx.ident_of("read_struct", trait_span),
                                 vec![cx.expr_str(trait_span, substr.type_ident.name),
                                      cx.expr_usize(trait_span, nfields),
                                      cx.lambda1(trait_span, result, blkarg)])
         }
         StaticEnum(_, ref fields) => {
-            let variant = cx.ident_of("i");
+            let variant = cx.ident_of("i", trait_span);
 
             let mut arms = Vec::with_capacity(fields.len() + 1);
             let mut variants = Vec::with_capacity(fields.len());
-            let rvariant_arg = cx.ident_of("read_enum_variant_arg");
+            let rvariant_arg = cx.ident_of("read_enum_variant_arg", trait_span);
 
             for (i, &(ident, v_span, ref parts)) in fields.iter().enumerate() {
                 variants.push(cx.expr_str(v_span, ident.name));
@@ -132,11 +136,11 @@
             let variant_vec = cx.expr_addr_of(trait_span, variant_vec);
             let result = cx.expr_method_call(trait_span,
                                              blkdecoder,
-                                             cx.ident_of("read_enum_variant"),
+                                             cx.ident_of("read_enum_variant", trait_span),
                                              vec![variant_vec, lambda]);
             cx.expr_method_call(trait_span,
                                 decoder,
-                                cx.ident_of("read_enum"),
+                                cx.ident_of("read_enum", trait_span),
                                 vec![cx.expr_str(trait_span, substr.type_ident.name),
                                      cx.lambda1(trait_span, result, blkarg)])
         }
diff --git a/src/libsyntax_ext/deriving/encodable.rs b/src/libsyntax_ext/deriving/encodable.rs
index 8b18fb2..655d3bb 100644
--- a/src/libsyntax_ext/deriving/encodable.rs
+++ b/src/libsyntax_ext/deriving/encodable.rs
@@ -153,16 +153,16 @@
                           -> P<Expr> {
     let encoder = substr.nonself_args[0].clone();
     // throw an underscore in front to suppress unused variable warnings
-    let blkarg = cx.ident_of("_e");
+    let blkarg = cx.ident_of("_e", trait_span);
     let blkencoder = cx.expr_ident(trait_span, blkarg);
     let fn_path = cx.expr_path(cx.path_global(trait_span,
-                                              vec![cx.ident_of(krate),
-                                                   cx.ident_of("Encodable"),
-                                                   cx.ident_of("encode")]));
+                                              vec![cx.ident_of(krate, trait_span),
+                                                   cx.ident_of("Encodable", trait_span),
+                                                   cx.ident_of("encode", trait_span)]));
 
     return match *substr.fields {
         Struct(_, ref fields) => {
-            let emit_struct_field = cx.ident_of("emit_struct_field");
+            let emit_struct_field = cx.ident_of("emit_struct_field", trait_span);
             let mut stmts = Vec::new();
             for (i, &FieldInfo { name, ref self_, span, .. }) in fields.iter().enumerate() {
                 let name = match name {
@@ -201,7 +201,7 @@
 
             cx.expr_method_call(trait_span,
                                 encoder,
-                                cx.ident_of("emit_struct"),
+                                cx.ident_of("emit_struct", trait_span),
                                 vec![cx.expr_str(trait_span, substr.type_ident.name),
                                      cx.expr_usize(trait_span, fields.len()),
                                      blk])
@@ -214,7 +214,7 @@
             // actually exist.
             let me = cx.stmt_let(trait_span, false, blkarg, encoder);
             let encoder = cx.expr_ident(trait_span, blkarg);
-            let emit_variant_arg = cx.ident_of("emit_enum_variant_arg");
+            let emit_variant_arg = cx.ident_of("emit_enum_variant_arg", trait_span);
             let mut stmts = Vec::new();
             if !fields.is_empty() {
                 let last = fields.len() - 1;
@@ -244,7 +244,7 @@
             let name = cx.expr_str(trait_span, variant.ident.name);
             let call = cx.expr_method_call(trait_span,
                                            blkencoder,
-                                           cx.ident_of("emit_enum_variant"),
+                                           cx.ident_of("emit_enum_variant", trait_span),
                                            vec![name,
                                                 cx.expr_usize(trait_span, idx),
                                                 cx.expr_usize(trait_span, fields.len()),
@@ -252,7 +252,7 @@
             let blk = cx.lambda1(trait_span, call, blkarg);
             let ret = cx.expr_method_call(trait_span,
                                           encoder,
-                                          cx.ident_of("emit_enum"),
+                                          cx.ident_of("emit_enum", trait_span),
                                           vec![cx.expr_str(trait_span ,substr.type_ident.name),
                                                blk]);
             cx.expr_block(cx.block(trait_span, vec![me, cx.stmt_expr(ret)]))
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index c53fa7d..aceee62 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -237,7 +237,7 @@
     /// Whether there is a self argument (outer Option) i.e., whether
     /// this is a static function, and whether it is a pointer (inner
     /// Option)
-    pub explicit_self: Option<Option<PtrTy<'a>>>,
+    pub explicit_self: Option<Option<PtrTy>>,
 
     /// Arguments other than the self argument
     pub args: Vec<(Ty<'a>, &'a str)>,
@@ -843,7 +843,7 @@
                                 -> P<Expr> {
         let substructure = Substructure {
             type_ident,
-            method_ident: cx.ident_of(self.name),
+            method_ident: cx.ident_of(self.name, trait_.span),
             self_args,
             nonself_args,
             fields,
@@ -890,7 +890,7 @@
 
         for (ty, name) in self.args.iter() {
             let ast_ty = ty.to_ty(cx, trait_.span, type_ident, generics);
-            let ident = ast::Ident::from_str_and_span(name, trait_.span);
+            let ident = cx.ident_of(name, trait_.span);
             arg_tys.push((ident, ast_ty));
 
             let arg_expr = cx.expr_ident(trait_.span, ident);
@@ -938,7 +938,7 @@
 
         let ret_type = self.get_ret_ty(cx, trait_, generics, type_ident);
 
-        let method_ident = cx.ident_of(self.name);
+        let method_ident = cx.ident_of(self.name, trait_.span);
         let fn_decl = cx.fn_decl(args, ast::FunctionRetTy::Ty(ret_type));
         let body_block = cx.block_expr(body);
 
@@ -1201,7 +1201,7 @@
             ).collect::<Vec<String>>();
 
         let self_arg_idents = self_arg_names.iter()
-            .map(|name| cx.ident_of(&name[..]))
+            .map(|name| cx.ident_of(name, sp))
             .collect::<Vec<ast::Ident>>();
 
         // The `vi_idents` will be bound, solely in the catch-all, to
@@ -1210,7 +1210,7 @@
         let vi_idents = self_arg_names.iter()
             .map(|name| {
                 let vi_suffix = format!("{}_vi", &name[..]);
-                ast::Ident::from_str_and_span(&vi_suffix[..], trait_.span)
+                cx.ident_of(&vi_suffix[..], trait_.span)
             })
             .collect::<Vec<ast::Ident>>();
 
@@ -1389,7 +1389,7 @@
 
                 let target_ty = cx.ty_ident(
                     sp,
-                    ast::Ident::from_str_and_span(target_type_name, sp),
+                    cx.ident_of(target_type_name, sp),
                 );
                 let variant_disr = cx.expr_cast(sp, variant_value, target_ty);
                 let let_stmt = cx.stmt_let(sp, false, ident, variant_disr);
@@ -1591,7 +1591,7 @@
         let mut ident_exprs = Vec::new();
         for (i, struct_field) in struct_def.fields().iter().enumerate() {
             let sp = struct_field.span.with_ctxt(self.span.ctxt());
-            let ident = ast::Ident::from_str_and_span(&format!("{}_{}", prefix, i), self.span);
+            let ident = cx.ident_of(&format!("{}_{}", prefix, i), self.span);
             paths.push(ident.with_span_pos(sp));
             let val = cx.expr_path(cx.path_ident(sp, ident));
             let val = if use_temporaries {
diff --git a/src/libsyntax_ext/deriving/generic/ty.rs b/src/libsyntax_ext/deriving/generic/ty.rs
index cb1c7b2..b341a07 100644
--- a/src/libsyntax_ext/deriving/generic/ty.rs
+++ b/src/libsyntax_ext/deriving/generic/ty.rs
@@ -13,9 +13,9 @@
 
 /// The types of pointers
 #[derive(Clone)]
-pub enum PtrTy<'a> {
+pub enum PtrTy {
     /// &'lifetime mut
-    Borrowed(Option<&'a str>, ast::Mutability),
+    Borrowed(Option<Ident>, ast::Mutability),
     /// *mut
     #[allow(dead_code)]
     Raw(ast::Mutability),
@@ -26,7 +26,7 @@
 #[derive(Clone)]
 pub struct Path<'a> {
     path: Vec<&'a str>,
-    lifetime: Option<&'a str>,
+    lifetime: Option<Ident>,
     params: Vec<Box<Ty<'a>>>,
     kind: PathKind,
 }
@@ -46,7 +46,7 @@
         Path::new_(vec![path], None, Vec::new(), PathKind::Local)
     }
     pub fn new_<'r>(path: Vec<&'r str>,
-                    lifetime: Option<&'r str>,
+                    lifetime: Option<Ident>,
                     params: Vec<Box<Ty<'r>>>,
                     kind: PathKind)
                     -> Path<'r> {
@@ -72,7 +72,7 @@
                    self_ty: Ident,
                    self_generics: &Generics)
                    -> ast::Path {
-        let mut idents = self.path.iter().map(|s| Ident::from_str_and_span(*s, span)).collect();
+        let mut idents = self.path.iter().map(|s| cx.ident_of(*s, span)).collect();
         let lt = mk_lifetimes(cx, span, &self.lifetime);
         let tys: Vec<P<ast::Ty>> =
             self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect();
@@ -99,7 +99,7 @@
 pub enum Ty<'a> {
     Self_,
     /// &/Box/ Ty
-    Ptr(Box<Ty<'a>>, PtrTy<'a>),
+    Ptr(Box<Ty<'a>>, PtrTy),
     /// mod::mod::Type<[lifetime], [Params...]>, including a plain type
     /// parameter, and things like `i32`
     Literal(Path<'a>),
@@ -107,14 +107,14 @@
     Tuple(Vec<Ty<'a>>),
 }
 
-pub fn borrowed_ptrty<'r>() -> PtrTy<'r> {
+pub fn borrowed_ptrty() -> PtrTy {
     Borrowed(None, ast::Mutability::Immutable)
 }
 pub fn borrowed(ty: Box<Ty<'_>>) -> Ty<'_> {
     Ptr(ty, borrowed_ptrty())
 }
 
-pub fn borrowed_explicit_self<'r>() -> Option<Option<PtrTy<'r>>> {
+pub fn borrowed_explicit_self() -> Option<Option<PtrTy>> {
     Some(Some(borrowed_ptrty()))
 }
 
@@ -126,13 +126,11 @@
     Tuple(Vec::new())
 }
 
-fn mk_lifetime(cx: &ExtCtxt<'_>, span: Span, lt: &Option<&str>) -> Option<ast::Lifetime> {
-    lt.map(|s|
-        cx.lifetime(span, Ident::from_str(s))
-    )
+fn mk_lifetime(cx: &ExtCtxt<'_>, span: Span, lt: &Option<Ident>) -> Option<ast::Lifetime> {
+    lt.map(|ident| cx.lifetime(span, ident))
 }
 
-fn mk_lifetimes(cx: &ExtCtxt<'_>, span: Span, lt: &Option<&str>) -> Vec<ast::Lifetime> {
+fn mk_lifetimes(cx: &ExtCtxt<'_>, span: Span, lt: &Option<Ident>) -> Vec<ast::Lifetime> {
     mk_lifetime(cx, span, lt).into_iter().collect()
 }
 
@@ -209,7 +207,7 @@
             cx.trait_bound(path)
         })
         .collect();
-    cx.typaram(span, ast::Ident::from_str_and_span(name, span), attrs.to_owned(), bounds, None)
+    cx.typaram(span, cx.ident_of(name, span), attrs.to_owned(), bounds, None)
 }
 
 fn mk_generics(params: Vec<ast::GenericParam>, span: Span) -> Generics {
@@ -265,7 +263,7 @@
 
 pub fn get_explicit_self(cx: &ExtCtxt<'_>,
                          span: Span,
-                         self_ptr: &Option<PtrTy<'_>>)
+                         self_ptr: &Option<PtrTy>)
                          -> (P<Expr>, ast::ExplicitSelf) {
     // this constructs a fresh `self` path
     let self_path = cx.expr_self(span);
@@ -276,7 +274,7 @@
                 respan(span,
                        match *ptr {
                            Borrowed(ref lt, mutbl) => {
-                               let lt = lt.map(|s| cx.lifetime(span, Ident::from_str(s)));
+                               let lt = lt.map(|s| cx.lifetime(span, s));
                                SelfKind::Region(lt, mutbl)
                            }
                            Raw(_) => {
diff --git a/src/libsyntax_ext/env.rs b/src/libsyntax_ext/env.rs
index 179b7fe..70e1fbe 100644
--- a/src/libsyntax_ext/env.rs
+++ b/src/libsyntax_ext/env.rs
@@ -20,16 +20,16 @@
         Some(v) => v,
     };
 
-    let sp = cx.with_legacy_ctxt(sp);
+    let sp = cx.with_def_site_ctxt(sp);
     let e = match env::var(&*var.as_str()) {
         Err(..) => {
-            let lt = cx.lifetime(sp, Ident::with_dummy_span(kw::StaticLifetime));
+            let lt = cx.lifetime(sp, Ident::new(kw::StaticLifetime, sp));
             cx.expr_path(cx.path_all(sp,
                                      true,
                                      cx.std_path(&[sym::option, sym::Option, sym::None]),
                                      vec![GenericArg::Type(cx.ty_rptr(sp,
                                                      cx.ty_ident(sp,
-                                                                 Ident::with_dummy_span(sym::str)),
+                                                                 Ident::new(sym::str, sp)),
                                                      Some(lt),
                                                      ast::Mutability::Immutable))],
                                      vec![]))
diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs
index 5bfbdc9..46c7cbb 100644
--- a/src/libsyntax_ext/format.rs
+++ b/src/libsyntax_ext/format.rs
@@ -486,7 +486,7 @@
         let sp = self.macsp;
         let count = |c, arg| {
             let mut path = Context::rtpath(self.ecx, "Count");
-            path.push(self.ecx.ident_of(c));
+            path.push(self.ecx.ident_of(c, sp));
             match arg {
                 Some(arg) => self.ecx.expr_call_global(sp, path, vec![arg]),
                 None => self.ecx.expr_path(self.ecx.path_global(sp, path)),
@@ -534,7 +534,7 @@
                 let pos = {
                     let pos = |c, arg| {
                         let mut path = Context::rtpath(self.ecx, "Position");
-                        path.push(self.ecx.ident_of(c));
+                        path.push(self.ecx.ident_of(c, sp));
                         match arg {
                             Some(i) => {
                                 let arg = self.ecx.expr_usize(sp, i);
@@ -603,7 +603,7 @@
                 let fill = self.ecx.expr_lit(sp, ast::LitKind::Char(fill));
                 let align = |name| {
                     let mut p = Context::rtpath(self.ecx, "Alignment");
-                    p.push(self.ecx.ident_of(name));
+                    p.push(self.ecx.ident_of(name, sp));
                     self.ecx.path_global(sp, p)
                 };
                 let align = match arg.format.align {
@@ -621,11 +621,11 @@
                     sp,
                     path,
                     vec![
-                        self.ecx.field_imm(sp, self.ecx.ident_of("fill"), fill),
-                        self.ecx.field_imm(sp, self.ecx.ident_of("align"), align),
-                        self.ecx.field_imm(sp, self.ecx.ident_of("flags"), flags),
-                        self.ecx.field_imm(sp, self.ecx.ident_of("precision"), prec),
-                        self.ecx.field_imm(sp, self.ecx.ident_of("width"), width),
+                        self.ecx.field_imm(sp, self.ecx.ident_of("fill", sp), fill),
+                        self.ecx.field_imm(sp, self.ecx.ident_of("align", sp), align),
+                        self.ecx.field_imm(sp, self.ecx.ident_of("flags", sp), flags),
+                        self.ecx.field_imm(sp, self.ecx.ident_of("precision", sp), prec),
+                        self.ecx.field_imm(sp, self.ecx.ident_of("width", sp), width),
                     ],
                 );
 
@@ -634,8 +634,8 @@
                     sp,
                                           path,
                     vec![
-                        self.ecx.field_imm(sp, self.ecx.ident_of("position"), pos),
-                        self.ecx.field_imm(sp, self.ecx.ident_of("format"), fmt),
+                        self.ecx.field_imm(sp, self.ecx.ident_of("position", sp), pos),
+                        self.ecx.field_imm(sp, self.ecx.ident_of("format", sp), fmt),
                     ],
                 ))
             }
@@ -653,7 +653,7 @@
         let mut heads = Vec::with_capacity(self.args.len());
 
         let names_pos: Vec<_> = (0..self.args.len())
-            .map(|i| ast::Ident::from_str_and_span(&format!("arg{}", i), self.macsp))
+            .map(|i| self.ecx.ident_of(&format!("arg{}", i), self.macsp))
             .collect();
 
         // First, build up the static array which will become our precompiled
diff --git a/src/libsyntax_ext/global_allocator.rs b/src/libsyntax_ext/global_allocator.rs
index f4af169..19a87e6 100644
--- a/src/libsyntax_ext/global_allocator.rs
+++ b/src/libsyntax_ext/global_allocator.rs
@@ -28,7 +28,7 @@
     };
 
     // Generate a bunch of new items using the AllocFnFactory
-    let span = ecx.with_legacy_ctxt(item.span);
+    let span = ecx.with_def_site_ctxt(item.span);
     let f = AllocFnFactory {
         span,
         kind: AllocatorKind::Global,
@@ -43,7 +43,7 @@
     let const_ty = ecx.ty(span, TyKind::Tup(Vec::new()));
     let const_body = ecx.expr_block(ecx.block(span, stmts));
     let const_item =
-        ecx.item_const(span, Ident::with_dummy_span(kw::Underscore), const_ty, const_body);
+        ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body);
 
     // Return the original item and the new methods.
     vec![Annotatable::Item(item), Annotatable::Item(const_item)]
@@ -61,7 +61,7 @@
         let mut abi_args = Vec::new();
         let mut i = 0;
         let ref mut mk = || {
-            let name = Ident::from_str(&format!("arg{}", i));
+            let name = self.cx.ident_of(&format!("arg{}", i), self.span);
             i += 1;
             name
         };
@@ -83,7 +83,7 @@
         );
         let item = self.cx.item(
             self.span,
-            Ident::from_str(&self.kind.fn_name(method.name)),
+            self.cx.ident_of(&self.kind.fn_name(method.name), self.span),
             self.attrs(),
             kind,
         );
@@ -119,7 +119,7 @@
     ) -> P<Expr> {
         match *ty {
             AllocatorTy::Layout => {
-                let usize = self.cx.path_ident(self.span, Ident::with_dummy_span(sym::usize));
+                let usize = self.cx.path_ident(self.span, Ident::new(sym::usize, self.span));
                 let ty_usize = self.cx.ty_path(usize);
                 let size = ident();
                 let align = ident();
@@ -177,12 +177,12 @@
     }
 
     fn usize(&self) -> P<Ty> {
-        let usize = self.cx.path_ident(self.span, Ident::with_dummy_span(sym::usize));
+        let usize = self.cx.path_ident(self.span, Ident::new(sym::usize, self.span));
         self.cx.ty_path(usize)
     }
 
     fn ptr_u8(&self) -> P<Ty> {
-        let u8 = self.cx.path_ident(self.span, Ident::with_dummy_span(sym::u8));
+        let u8 = self.cx.path_ident(self.span, Ident::new(sym::u8, self.span));
         let ty_u8 = self.cx.ty_path(u8);
         self.cx.ty_ptr(self.span, ty_u8, Mutability::Mutable)
     }
diff --git a/src/libsyntax_ext/global_asm.rs b/src/libsyntax_ext/global_asm.rs
index 6140f0d..c56b3f3 100644
--- a/src/libsyntax_ext/global_asm.rs
+++ b/src/libsyntax_ext/global_asm.rs
@@ -30,7 +30,7 @@
                 id: ast::DUMMY_NODE_ID,
                 node: ast::ItemKind::GlobalAsm(P(global_asm)),
                 vis: respan(sp.shrink_to_lo(), ast::VisibilityKind::Inherited),
-                span: cx.with_legacy_ctxt(sp),
+                span: cx.with_def_site_ctxt(sp),
                 tokens: None,
             })])
         }
diff --git a/src/libsyntax_ext/proc_macro_harness.rs b/src/libsyntax_ext/proc_macro_harness.rs
index 31d32d2..a5dcfb9 100644
--- a/src/libsyntax_ext/proc_macro_harness.rs
+++ b/src/libsyntax_ext/proc_macro_harness.rs
@@ -340,12 +340,12 @@
                         Vec::new(),
                         ast::ItemKind::ExternCrate(None));
 
-    let bridge = Ident::from_str_and_span("bridge", span);
-    let client = Ident::from_str_and_span("client", span);
-    let proc_macro_ty = Ident::from_str_and_span("ProcMacro", span);
-    let custom_derive = Ident::from_str_and_span("custom_derive", span);
-    let attr = Ident::from_str_and_span("attr", span);
-    let bang = Ident::from_str_and_span("bang", span);
+    let bridge = cx.ident_of("bridge", span);
+    let client = cx.ident_of("client", span);
+    let proc_macro_ty = cx.ident_of("ProcMacro", span);
+    let custom_derive = cx.ident_of("custom_derive", span);
+    let attr = cx.ident_of("attr", span);
+    let bang = cx.ident_of("bang", span);
 
     let decls = {
         let local_path = |sp: Span, name| {
@@ -378,7 +378,7 @@
 
     let decls_static = cx.item_static(
         span,
-        Ident::from_str_and_span("_DECLS", span),
+        cx.ident_of("_DECLS", span),
         cx.ty_rptr(span,
             cx.ty(span, ast::TyKind::Slice(
                 cx.ty_path(cx.path(span,
diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs
index be5aca7..0910c00 100644
--- a/src/libsyntax_ext/test.rs
+++ b/src/libsyntax_ext/test.rs
@@ -98,20 +98,20 @@
 
     // creates test::$name
     let test_path = |name| {
-        cx.path(sp, vec![test_id, cx.ident_of(name)])
+        cx.path(sp, vec![test_id, cx.ident_of(name, sp)])
     };
 
     // creates test::ShouldPanic::$name
     let should_panic_path = |name| {
-        cx.path(sp, vec![test_id, cx.ident_of("ShouldPanic"), cx.ident_of(name)])
+        cx.path(sp, vec![test_id, cx.ident_of("ShouldPanic", sp), cx.ident_of(name, sp)])
     };
 
     // creates $name: $expr
-    let field = |name, expr| cx.field_imm(sp, cx.ident_of(name), expr);
+    let field = |name, expr| cx.field_imm(sp, cx.ident_of(name, sp), expr);
 
     let test_fn = if is_bench {
         // A simple ident for a lambda
-        let b = ast::Ident::from_str_and_span("b", attr_sp);
+        let b = cx.ident_of("b", attr_sp);
 
         cx.expr_call(sp, cx.expr_path(test_path("StaticBenchFn")), vec![
             // |b| self::test::assert_test_result(
diff --git a/src/libsyntax_ext/test_harness.rs b/src/libsyntax_ext/test_harness.rs
index b93c11f..56de0c9 100644
--- a/src/libsyntax_ext/test_harness.rs
+++ b/src/libsyntax_ext/test_harness.rs
@@ -250,7 +250,7 @@
 
     // test::test_main_static(...)
     let mut test_runner = cx.test_runner.clone().unwrap_or(
-        ecx.path(sp, vec![test_id, Ident::from_str_and_span("test_main_static", sp)]));
+        ecx.path(sp, vec![test_id, ecx.ident_of("test_main_static", sp)]));
 
     test_runner.span = sp;
 
@@ -288,7 +288,7 @@
     // Honor the reexport_test_harness_main attribute
     let main_id = match cx.reexport_test_harness_main {
         Some(sym) => Ident::new(sym, sp.with_ctxt(SyntaxContext::root())),
-        None => Ident::from_str_and_span("main", sp),
+        None => Ident::new(sym::main, sp),
     };
 
     let main = P(ast::Item {
diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs
index 8142d44..e28d932 100644
--- a/src/libsyntax_pos/hygiene.rs
+++ b/src/libsyntax_pos/hygiene.rs
@@ -709,6 +709,13 @@
         }
     }
 
+    pub fn descr_expected(self) -> &'static str {
+        match self {
+            MacroKind::Attr => "attribute",
+            _ => self.descr(),
+        }
+    }
+
     pub fn article(self) -> &'static str {
         match self {
             MacroKind::Attr => "an",
diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs
index 9a296f1..ca177eb 100644
--- a/src/libsyntax_pos/lib.rs
+++ b/src/libsyntax_pos/lib.rs
@@ -526,13 +526,6 @@
         self.with_ctxt_from_mark(expn_id, Transparency::Transparent)
     }
 
-    /// Span with a context reproducing `macro_rules` hygiene (hygienic locals, unhygienic items).
-    /// FIXME: This should be eventually replaced either with `with_def_site_ctxt` (preferably),
-    /// or with `with_call_site_ctxt` (where necessary).
-    pub fn with_legacy_ctxt(&self, expn_id: ExpnId) -> Span {
-        self.with_ctxt_from_mark(expn_id, Transparency::SemiTransparent)
-    }
-
     /// Produces a span with the same location as `self` and context produced by a macro with the
     /// given ID and transparency, assuming that macro was defined directly and not produced by
     /// some other macro (which is the case for built-in and procedural macros).
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index ab32d44..597ae83 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -765,7 +765,7 @@
         Ident::with_dummy_span(string.as_symbol())
     }
 
-    /// Maps a string to an identifier with an empty span.
+    /// Maps a string to an identifier with a dummy span.
     pub fn from_str(string: &str) -> Ident {
         Ident::with_dummy_span(Symbol::intern(string))
     }
diff --git a/src/test/ui/issues/issue-44415.rs b/src/test/compile-fail/issue-44415.rs
similarity index 100%
rename from src/test/ui/issues/issue-44415.rs
rename to src/test/compile-fail/issue-44415.rs
diff --git a/src/test/debuginfo/function-arg-initialization.rs b/src/test/debuginfo/function-arg-initialization.rs
index fef6253..8c86d2c 100644
--- a/src/test/debuginfo/function-arg-initialization.rs
+++ b/src/test/debuginfo/function-arg-initialization.rs
@@ -242,12 +242,12 @@
 
 fn binding(a: i64, b: u64, c: f64) {
     let x = 0; // #break
-    println!("")
+    println!()
 }
 
 fn assignment(mut a: u64, b: u64, c: f64) {
     a = b; // #break
-    println!("")
+    println!()
 }
 
 fn function_call(x: u64, y: u64, z: f64) {
diff --git a/src/test/ui/allocator/hygiene.rs b/src/test/ui/allocator/hygiene.rs
new file mode 100644
index 0000000..9bd8406
--- /dev/null
+++ b/src/test/ui/allocator/hygiene.rs
@@ -0,0 +1,31 @@
+// run-pass
+// no-prefer-dynamic
+// aux-build:custom.rs
+// aux-build:helper.rs
+
+#![allow(nonstandard_style)]
+
+extern crate custom;
+extern crate helper;
+
+use custom::A;
+use std::sync::atomic::{AtomicUsize, Ordering};
+
+#[allow(dead_code)]
+struct u8;
+#[allow(dead_code)]
+struct usize;
+#[allow(dead_code)]
+static arg0: () = ();
+
+#[global_allocator]
+pub static GLOBAL: A = A(AtomicUsize::new(0));
+
+fn main() {
+    let n = GLOBAL.0.load(Ordering::SeqCst);
+    let s = Box::new(0);
+    helper::work_with(&s);
+    assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 1);
+    drop(s);
+    assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2);
+}
diff --git a/src/test/ui/async-await/drop-order/drop-order-for-temporary-in-tail-return-expr.rs b/src/test/ui/async-await/drop-order/drop-order-for-temporary-in-tail-return-expr.rs
new file mode 100644
index 0000000..e40acff
--- /dev/null
+++ b/src/test/ui/async-await/drop-order/drop-order-for-temporary-in-tail-return-expr.rs
@@ -0,0 +1,95 @@
+// aux-build:arc_wake.rs
+// edition:2018
+// run-pass
+
+#![allow(unused_variables)]
+
+// Test the drop order for parameters relative to local variables and
+// temporaries created in the tail return expression of the function
+// body. In particular, check that this drop order is the same between
+// a `async fn` and an ordinary `fn`. See #64512.
+
+extern crate arc_wake;
+
+use arc_wake::ArcWake;
+use std::cell::RefCell;
+use std::future::Future;
+use std::sync::Arc;
+use std::rc::Rc;
+use std::task::Context;
+
+struct EmptyWaker;
+
+impl ArcWake for EmptyWaker {
+    fn wake(self: Arc<Self>) {}
+}
+
+#[derive(Debug, Eq, PartialEq)]
+enum DropOrder {
+    Function,
+    Val(&'static str),
+}
+
+type DropOrderListPtr = Rc<RefCell<Vec<DropOrder>>>;
+
+struct D(&'static str, DropOrderListPtr);
+
+impl Drop for D {
+    fn drop(&mut self) {
+        self.1.borrow_mut().push(DropOrder::Val(self.0));
+    }
+}
+
+/// Check drop order of temporary "temp" as compared to `x`, `y`, and `z`.
+///
+/// Expected order:
+/// - `z`
+/// - temp
+/// - `y`
+/// - `x`
+async fn foo_async(x: D, _y: D) {
+    let l = x.1.clone();
+    let z = D("z", l.clone());
+    l.borrow_mut().push(DropOrder::Function);
+    helper_async(&D("temp", l)).await
+}
+
+async fn helper_async(v: &D) { }
+
+fn foo_sync(x: D, _y: D) {
+    let l = x.1.clone();
+    let z = D("z", l.clone());
+    l.borrow_mut().push(DropOrder::Function);
+    helper_sync(&D("temp", l))
+}
+
+fn helper_sync(v: &D) { }
+
+fn assert_drop_order_after_poll<Fut: Future<Output = ()>>(
+    f: impl FnOnce(DropOrderListPtr) -> Fut,
+    g: impl FnOnce(DropOrderListPtr),
+) {
+    let empty = Arc::new(EmptyWaker);
+    let waker = ArcWake::into_waker(empty);
+    let mut cx = Context::from_waker(&waker);
+
+    let actual_order = Rc::new(RefCell::new(Vec::new()));
+    let mut fut = Box::pin(f(actual_order.clone()));
+    let r = fut.as_mut().poll(&mut cx);
+
+    assert!(match r {
+        std::task::Poll::Ready(()) => true,
+        _ => false,
+    });
+
+    let expected_order = Rc::new(RefCell::new(Vec::new()));
+    g(expected_order.clone());
+
+    assert_eq!(*actual_order.borrow(), *expected_order.borrow());
+}
+
+fn main() {
+    // Free functions (see doc comment on function for what it tests).
+    assert_drop_order_after_poll(|l| foo_async(D("x", l.clone()), D("_y", l.clone())),
+                                 |l| foo_sync(D("x", l.clone()), D("_y", l.clone())));
+}
diff --git a/src/test/ui/async-await/issue-64391.rs b/src/test/ui/async-await/issue-64391.rs
new file mode 100644
index 0000000..c6faad3
--- /dev/null
+++ b/src/test/ui/async-await/issue-64391.rs
@@ -0,0 +1,14 @@
+// Regression test for Issue #64391. The goal here is that this
+// function compiles. In the past, due to incorrect drop order for
+// temporaries in the tail expression, we failed to compile this
+// example. The drop order itself is directly tested in
+// `drop-order/drop-order-for-temporary-in-tail-return-expr.rs`.
+//
+// check-pass
+// edition:2018
+
+async fn add(x: u32, y: u32) -> u32 {
+    async { x + y }.await
+}
+
+fn main() { }
diff --git a/src/test/ui/attributes/obsolete-attr.rs b/src/test/ui/attributes/obsolete-attr.rs
index cf6dd33..42f90ed 100644
--- a/src/test/ui/attributes/obsolete-attr.rs
+++ b/src/test/ui/attributes/obsolete-attr.rs
@@ -1,9 +1,9 @@
 // Obsolete attributes fall back to unstable custom attributes.
 
 #[ab_isize="stdcall"] extern {}
-//~^ ERROR cannot find attribute macro `ab_isize` in this scope
+//~^ ERROR cannot find attribute `ab_isize` in this scope
 
 #[fixed_stack_segment] fn f() {}
-//~^ ERROR cannot find attribute macro `fixed_stack_segment` in this scope
+//~^ ERROR cannot find attribute `fixed_stack_segment` in this scope
 
 fn main() {}
diff --git a/src/test/ui/attributes/obsolete-attr.stderr b/src/test/ui/attributes/obsolete-attr.stderr
index 9c6909f..2d7c257 100644
--- a/src/test/ui/attributes/obsolete-attr.stderr
+++ b/src/test/ui/attributes/obsolete-attr.stderr
@@ -1,10 +1,10 @@
-error: cannot find attribute macro `fixed_stack_segment` in this scope
+error: cannot find attribute `fixed_stack_segment` in this scope
   --> $DIR/obsolete-attr.rs:6:3
    |
 LL | #[fixed_stack_segment] fn f() {}
    |   ^^^^^^^^^^^^^^^^^^^
 
-error: cannot find attribute macro `ab_isize` in this scope
+error: cannot find attribute `ab_isize` in this scope
   --> $DIR/obsolete-attr.rs:3:3
    |
 LL | #[ab_isize="stdcall"] extern {}
diff --git a/src/test/ui/attributes/unknown-attr.rs b/src/test/ui/attributes/unknown-attr.rs
index 544a6e2..70fef04 100644
--- a/src/test/ui/attributes/unknown-attr.rs
+++ b/src/test/ui/attributes/unknown-attr.rs
@@ -3,10 +3,10 @@
 #![feature(custom_inner_attributes)]
 
 #![mutable_doc]
-//~^ ERROR cannot find attribute macro `mutable_doc` in this scope
+//~^ ERROR cannot find attribute `mutable_doc` in this scope
 
 #[dance] mod a {}
-//~^ ERROR cannot find attribute macro `dance` in this scope
+//~^ ERROR cannot find attribute `dance` in this scope
 
 #[dance] fn main() {}
-//~^ ERROR cannot find attribute macro `dance` in this scope
+//~^ ERROR cannot find attribute `dance` in this scope
diff --git a/src/test/ui/attributes/unknown-attr.stderr b/src/test/ui/attributes/unknown-attr.stderr
index 4d46387..85c227d 100644
--- a/src/test/ui/attributes/unknown-attr.stderr
+++ b/src/test/ui/attributes/unknown-attr.stderr
@@ -1,16 +1,16 @@
-error: cannot find attribute macro `mutable_doc` in this scope
+error: cannot find attribute `mutable_doc` in this scope
   --> $DIR/unknown-attr.rs:5:4
    |
 LL | #![mutable_doc]
    |    ^^^^^^^^^^^
 
-error: cannot find attribute macro `dance` in this scope
+error: cannot find attribute `dance` in this scope
   --> $DIR/unknown-attr.rs:8:3
    |
 LL | #[dance] mod a {}
    |   ^^^^^
 
-error: cannot find attribute macro `dance` in this scope
+error: cannot find attribute `dance` in this scope
   --> $DIR/unknown-attr.rs:11:3
    |
 LL | #[dance] fn main() {}
diff --git a/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr b/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr
index 4947d6e..ab8398e 100644
--- a/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr
+++ b/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr
@@ -37,11 +37,11 @@
   --> $DIR/variadic-ffi-4.rs:20:5
    |
 LL | pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
-   |                                               -------                   ------- has type `core::ffi::VaListImpl<'1>`
+   |                                               -------                   ------- has type `core::ffi::VaListImpl<'2>`
    |                                               |
-   |                                               has type `&mut core::ffi::VaListImpl<'2>`
+   |                                               has type `&mut core::ffi::VaListImpl<'1>`
 LL |     *ap0 = ap1;
-   |     ^^^^ assignment requires that `'1` must outlive `'2`
+   |     ^^^^ assignment requires that `'2` must outlive `'1`
 
 error: lifetime may not live long enough
   --> $DIR/variadic-ffi-4.rs:25:5
@@ -57,11 +57,11 @@
   --> $DIR/variadic-ffi-4.rs:25:5
    |
 LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
-   |                                               ---                   ------- has type `core::ffi::VaListImpl<'1>`
+   |                                               ---                   ------- has type `core::ffi::VaListImpl<'2>`
    |                                               |
-   |                                               has type `&mut core::ffi::VaListImpl<'2>`
+   |                                               has type `&mut core::ffi::VaListImpl<'1>`
 LL |     ap0 = &mut ap1;
-   |     ^^^^^^^^^^^^^^ assignment requires that `'1` must outlive `'2`
+   |     ^^^^^^^^^^^^^^ assignment requires that `'2` must outlive `'1`
 
 error[E0384]: cannot assign to immutable argument `ap0`
   --> $DIR/variadic-ffi-4.rs:25:5
@@ -99,11 +99,11 @@
   --> $DIR/variadic-ffi-4.rs:33:12
    |
 LL | pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
-   |                                               -------                   ------- has type `core::ffi::VaListImpl<'1>`
+   |                                               -------                   ------- has type `core::ffi::VaListImpl<'2>`
    |                                               |
-   |                                               has type `&mut core::ffi::VaListImpl<'2>`
+   |                                               has type `&mut core::ffi::VaListImpl<'1>`
 LL |     *ap0 = ap1.clone();
-   |            ^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
+   |            ^^^^^^^^^^^ argument requires that `'2` must outlive `'1`
 
 error: aborting due to 11 previous errors
 
diff --git a/src/test/ui/coherence/conflicting-impl-with-err.rs b/src/test/ui/coherence/conflicting-impl-with-err.rs
new file mode 100644
index 0000000..3e0234b
--- /dev/null
+++ b/src/test/ui/coherence/conflicting-impl-with-err.rs
@@ -0,0 +1,16 @@
+struct ErrorKind;
+struct Error(ErrorKind);
+
+impl From<nope::Thing> for Error { //~ ERROR failed to resolve
+    fn from(_: nope::Thing) -> Self { //~ ERROR failed to resolve
+        unimplemented!()
+    }
+}
+
+impl From<ErrorKind> for Error {
+    fn from(_: ErrorKind) -> Self {
+        unimplemented!()
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/conflicting-impl-with-err.stderr b/src/test/ui/coherence/conflicting-impl-with-err.stderr
new file mode 100644
index 0000000..a8a5730
--- /dev/null
+++ b/src/test/ui/coherence/conflicting-impl-with-err.stderr
@@ -0,0 +1,15 @@
+error[E0433]: failed to resolve: use of undeclared type or module `nope`
+  --> $DIR/conflicting-impl-with-err.rs:4:11
+   |
+LL | impl From<nope::Thing> for Error {
+   |           ^^^^ use of undeclared type or module `nope`
+
+error[E0433]: failed to resolve: use of undeclared type or module `nope`
+  --> $DIR/conflicting-impl-with-err.rs:5:16
+   |
+LL |     fn from(_: nope::Thing) -> Self {
+   |                ^^^^ use of undeclared type or module `nope`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/collections-const-new.rs b/src/test/ui/collections-const-new.rs
index e01b0df..a93f9a1 100644
--- a/src/test/ui/collections-const-new.rs
+++ b/src/test/ui/collections-const-new.rs
@@ -1,15 +1,11 @@
-// run-pass
+// check-pass
 
-#![allow(dead_code)]
 // Test several functions can be used for constants
 // 1. Vec::new()
 // 2. String::new()
 
-#![feature(const_vec_new)]
-#![feature(const_string_new)]
-
 const MY_VEC: Vec<usize> = Vec::new();
 
 const MY_STRING: String = String::new();
 
-pub fn main() {}
+fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-6.rs b/src/test/ui/conditional-compilation/cfg-arg-invalid-6.rs
new file mode 100644
index 0000000..9fa726f
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-6.rs
@@ -0,0 +1,3 @@
+// compile-flags: --cfg a{
+// error-pattern: invalid `--cfg` argument: `a{` (expected `key` or `key="value"`)
+fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-6.stderr b/src/test/ui/conditional-compilation/cfg-arg-invalid-6.stderr
new file mode 100644
index 0000000..7d2087b
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-6.stderr
@@ -0,0 +1,2 @@
+error: invalid `--cfg` argument: `a{` (expected `key` or `key="value"`)
+
diff --git a/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.rs b/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.rs
index 22dbac7..45b757e 100644
--- a/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.rs
+++ b/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.rs
@@ -1,7 +1,7 @@
 macro_rules! foo {
     () => {
         #[cfg_attr(all(), unknown)]
-        //~^ ERROR cannot find attribute macro `unknown` in this scope
+        //~^ ERROR cannot find attribute `unknown` in this scope
         fn foo() {}
     }
 }
diff --git a/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr b/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr
index c7c52a2..ef434ec 100644
--- a/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr
+++ b/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr
@@ -1,4 +1,4 @@
-error: cannot find attribute macro `unknown` in this scope
+error: cannot find attribute `unknown` in this scope
   --> $DIR/cfg-attr-unknown-attribute-macro-expansion.rs:3:27
    |
 LL |         #[cfg_attr(all(), unknown)]
diff --git a/src/test/ui/conditional-compilation/cfg-generic-params.rs b/src/test/ui/conditional-compilation/cfg-generic-params.rs
index faf0195..53aa355 100644
--- a/src/test/ui/conditional-compilation/cfg-generic-params.rs
+++ b/src/test/ui/conditional-compilation/cfg-generic-params.rs
@@ -17,22 +17,22 @@
 
 fn f_lt_no<#[cfg_attr(no, unknown)] 'a>() {} // OK
 fn f_lt_yes<#[cfg_attr(yes, unknown)] 'a>() {}
-//~^ ERROR cannot find attribute macro `unknown` in this scope
+//~^ ERROR cannot find attribute `unknown` in this scope
 fn f_ty_no<#[cfg_attr(no, unknown)] T>() {} // OK
 fn f_ty_yes<#[cfg_attr(yes, unknown)] T>() {}
-//~^ ERROR cannot find attribute macro `unknown` in this scope
+//~^ ERROR cannot find attribute `unknown` in this scope
 
 type FnNo = for<#[cfg_attr(no, unknown)] 'a> fn(); // OK
 type FnYes = for<#[cfg_attr(yes, unknown)] 'a> fn();
-//~^ ERROR cannot find attribute macro `unknown` in this scope
+//~^ ERROR cannot find attribute `unknown` in this scope
 
 type PolyNo = dyn for<#[cfg_attr(no, unknown)] 'a> Copy; // OK
 type PolyYes = dyn for<#[cfg_attr(yes, unknown)] 'a> Copy;
-//~^ ERROR cannot find attribute macro `unknown` in this scope
+//~^ ERROR cannot find attribute `unknown` in this scope
 
 struct WhereNo where for<#[cfg_attr(no, unknown)] 'a> u8: Copy; // OK
 struct WhereYes where for<#[cfg_attr(yes, unknown)] 'a> u8: Copy;
-//~^ ERROR cannot find attribute macro `unknown` in this scope
+//~^ ERROR cannot find attribute `unknown` in this scope
 
 fn main() {
     f_lt::<'static>();
diff --git a/src/test/ui/conditional-compilation/cfg-generic-params.stderr b/src/test/ui/conditional-compilation/cfg-generic-params.stderr
index f6e5732..d9e29c8 100644
--- a/src/test/ui/conditional-compilation/cfg-generic-params.stderr
+++ b/src/test/ui/conditional-compilation/cfg-generic-params.stderr
@@ -16,31 +16,31 @@
 LL | struct WhereBad where for<#[cfg(no)] 'a, #[cfg(yes)] T> u8: Copy;
    |                                                      ^
 
-error: cannot find attribute macro `unknown` in this scope
+error: cannot find attribute `unknown` in this scope
   --> $DIR/cfg-generic-params.rs:34:43
    |
 LL | struct WhereYes where for<#[cfg_attr(yes, unknown)] 'a> u8: Copy;
    |                                           ^^^^^^^
 
-error: cannot find attribute macro `unknown` in this scope
+error: cannot find attribute `unknown` in this scope
   --> $DIR/cfg-generic-params.rs:30:40
    |
 LL | type PolyYes = dyn for<#[cfg_attr(yes, unknown)] 'a> Copy;
    |                                        ^^^^^^^
 
-error: cannot find attribute macro `unknown` in this scope
+error: cannot find attribute `unknown` in this scope
   --> $DIR/cfg-generic-params.rs:26:34
    |
 LL | type FnYes = for<#[cfg_attr(yes, unknown)] 'a> fn();
    |                                  ^^^^^^^
 
-error: cannot find attribute macro `unknown` in this scope
+error: cannot find attribute `unknown` in this scope
   --> $DIR/cfg-generic-params.rs:22:29
    |
 LL | fn f_ty_yes<#[cfg_attr(yes, unknown)] T>() {}
    |                             ^^^^^^^
 
-error: cannot find attribute macro `unknown` in this scope
+error: cannot find attribute `unknown` in this scope
   --> $DIR/cfg-generic-params.rs:19:29
    |
 LL | fn f_lt_yes<#[cfg_attr(yes, unknown)] 'a>() {}
diff --git a/src/test/ui/consts/const-size_of-cycle.stderr b/src/test/ui/consts/const-size_of-cycle.stderr
index fdba359..1ae39e7 100644
--- a/src/test/ui/consts/const-size_of-cycle.stderr
+++ b/src/test/ui/consts/const-size_of-cycle.stderr
@@ -14,6 +14,11 @@
    |
 LL |     intrinsics::size_of::<T>()
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires const-evaluating + checking `std::intrinsics::size_of`...
+  --> $SRC_DIR/libcore/intrinsics.rs:LL:COL
+   |
+LL |     pub fn size_of<T>() -> usize;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: ...which requires computing layout of `Foo`...
    = note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All, def_id: None }, value: [u8; _] }`...
    = note: ...which again requires const-evaluating + checking `Foo::bytes::{{constant}}#0`, completing the cycle
diff --git a/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs
index 5fb9253..8b17f68 100644
--- a/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs
+++ b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs
@@ -14,8 +14,9 @@
 impl Foo<u32> for () {
     const X: u32 = 42;
 }
+
 impl Foo<Vec<u32>> for String {
-    const X: Vec<u32> = Vec::new(); //~ ERROR not yet stable as a const fn
+    const X: Vec<u32> = Vec::new();
 }
 
 impl Bar<u32, ()> for () {}
diff --git a/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr
index c56ebf6..5bc7b70 100644
--- a/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr
+++ b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr
@@ -4,13 +4,5 @@
 LL |     const F: u32 = (U::X, 42).1;
    |                    ^^^^^^^^^^ constants cannot evaluate destructors
 
-error: `std::vec::Vec::<T>::new` is not yet stable as a const fn
-  --> $DIR/feature-gate-unleash_the_miri_inside_of_you.rs:18:25
-   |
-LL |     const X: Vec<u32> = Vec::new();
-   |                         ^^^^^^^^^^
-   |
-   = help: add `#![feature(const_vec_new)]` to the crate attributes to enable
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
diff --git a/src/test/ui/consts/miri_unleashed/mutable_const.rs b/src/test/ui/consts/miri_unleashed/mutable_const.rs
new file mode 100644
index 0000000..b476e04
--- /dev/null
+++ b/src/test/ui/consts/miri_unleashed/mutable_const.rs
@@ -0,0 +1,20 @@
+// compile-flags: -Zunleash-the-miri-inside-of-you
+
+#![feature(const_raw_ptr_deref)]
+#![deny(const_err)]
+
+use std::cell::UnsafeCell;
+
+// make sure we do not just intern this as mutable
+const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
+
+const MUTATING_BEHIND_RAW: () = {
+    // Test that `MUTABLE_BEHIND_RAW` is actually immutable, by doing this at const time.
+    unsafe {
+        *MUTABLE_BEHIND_RAW = 99 //~ WARN skipping const checks
+        //~^ ERROR any use of this value will cause an error
+        //~^^ tried to modify constant memory
+    }
+};
+
+fn main() {}
diff --git a/src/test/ui/consts/miri_unleashed/mutable_const.stderr b/src/test/ui/consts/miri_unleashed/mutable_const.stderr
new file mode 100644
index 0000000..507d4823
--- /dev/null
+++ b/src/test/ui/consts/miri_unleashed/mutable_const.stderr
@@ -0,0 +1,27 @@
+warning: skipping const checks
+  --> $DIR/mutable_const.rs:14:9
+   |
+LL |         *MUTABLE_BEHIND_RAW = 99
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: any use of this value will cause an error
+  --> $DIR/mutable_const.rs:14:9
+   |
+LL | / const MUTATING_BEHIND_RAW: () = {
+LL | |     // Test that `MUTABLE_BEHIND_RAW` is actually immutable, by doing this at const time.
+LL | |     unsafe {
+LL | |         *MUTABLE_BEHIND_RAW = 99
+   | |         ^^^^^^^^^^^^^^^^^^^^^^^^ tried to modify constant memory
+...  |
+LL | |     }
+LL | | };
+   | |__-
+   |
+note: lint level defined here
+  --> $DIR/mutable_const.rs:4:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/miri_unleashed/mutable_references_ice.stderr b/src/test/ui/consts/miri_unleashed/mutable_references_ice.stderr
index 82569e2..28cf353 100644
--- a/src/test/ui/consts/miri_unleashed/mutable_references_ice.stderr
+++ b/src/test/ui/consts/miri_unleashed/mutable_references_ice.stderr
@@ -6,7 +6,7 @@
 
 thread 'rustc' panicked at 'assertion failed: `(left != right)`
   left: `Const`,
- right: `Const`: UnsafeCells are not allowed behind references in constants. This should have been prevented statically by const qualification. If this were allowed one would be able to change a constant at one use site and other use sites may arbitrarily decide to change, too.', src/librustc_mir/interpret/intern.rs:LL:CC
+ right: `Const`: UnsafeCells are not allowed behind references in constants. This should have been prevented statically by const qualification. If this were allowed one would be able to change a constant at one use site and other use sites could observe that mutation.', src/librustc_mir/interpret/intern.rs:LL:CC
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
 
 error: internal compiler error: unexpected panic
diff --git a/src/test/ui/custom_attribute.rs b/src/test/ui/custom_attribute.rs
index 13c873c..4957184 100644
--- a/src/test/ui/custom_attribute.rs
+++ b/src/test/ui/custom_attribute.rs
@@ -1,9 +1,9 @@
 #![feature(stmt_expr_attributes)]
 
-#[foo] //~ ERROR cannot find attribute macro `foo` in this scope
+#[foo] //~ ERROR cannot find attribute `foo` in this scope
 fn main() {
-    #[foo] //~ ERROR cannot find attribute macro `foo` in this scope
+    #[foo] //~ ERROR cannot find attribute `foo` in this scope
     let x = ();
-    #[foo] //~ ERROR cannot find attribute macro `foo` in this scope
+    #[foo] //~ ERROR cannot find attribute `foo` in this scope
     x
 }
diff --git a/src/test/ui/custom_attribute.stderr b/src/test/ui/custom_attribute.stderr
index b4f9f3f..4023892 100644
--- a/src/test/ui/custom_attribute.stderr
+++ b/src/test/ui/custom_attribute.stderr
@@ -1,16 +1,16 @@
-error: cannot find attribute macro `foo` in this scope
+error: cannot find attribute `foo` in this scope
   --> $DIR/custom_attribute.rs:3:3
    |
 LL | #[foo]
    |   ^^^
 
-error: cannot find attribute macro `foo` in this scope
+error: cannot find attribute `foo` in this scope
   --> $DIR/custom_attribute.rs:5:7
    |
 LL |     #[foo]
    |       ^^^
 
-error: cannot find attribute macro `foo` in this scope
+error: cannot find attribute `foo` in this scope
   --> $DIR/custom_attribute.rs:7:7
    |
 LL |     #[foo]
diff --git a/src/test/ui/drop/dropck_legal_cycles.rs b/src/test/ui/drop/dropck_legal_cycles.rs
index a4f4c26..fb13fd7 100644
--- a/src/test/ui/drop/dropck_legal_cycles.rs
+++ b/src/test/ui/drop/dropck_legal_cycles.rs
@@ -143,7 +143,7 @@
     v[0].descend_into_self(&mut c);
     assert!(!c.saw_prev_marked); // <-- different from below, b/c acyclic above
 
-    if PRINT { println!(""); }
+    if PRINT { println!(); }
 
     // Cycle 1: { v[0] -> v[1], v[1] -> v[0] };
     // does not exercise `v` itself
@@ -158,7 +158,7 @@
     v[0].descend_into_self(&mut c);
     assert!(c.saw_prev_marked);
 
-    if PRINT { println!(""); }
+    if PRINT { println!(); }
 
     // Cycle 2: { v[0] -> v, v[1] -> v }
     let v: V = Named::new("v");
@@ -171,7 +171,7 @@
     v.descend_into_self(&mut c);
     assert!(c.saw_prev_marked);
 
-    if PRINT { println!(""); }
+    if PRINT { println!(); }
 
     // Cycle 3: { hk0 -> hv0, hv0 -> hk0, hk1 -> hv1, hv1 -> hk1 };
     // does not exercise `h` itself
@@ -193,7 +193,7 @@
         assert!(c.saw_prev_marked);
     }
 
-    if PRINT { println!(""); }
+    if PRINT { println!(); }
 
     // Cycle 4: { h -> (hmk0,hmv0,hmk1,hmv1), {hmk0,hmv0,hmk1,hmv1} -> h }
 
@@ -216,7 +216,7 @@
         // break;
     }
 
-    if PRINT { println!(""); }
+    if PRINT { println!(); }
 
     // Cycle 5: { vd[0] -> vd[1], vd[1] -> vd[0] };
     // does not exercise vd itself
@@ -232,7 +232,7 @@
     vd[0].descend_into_self(&mut c);
     assert!(c.saw_prev_marked);
 
-    if PRINT { println!(""); }
+    if PRINT { println!(); }
 
     // Cycle 6: { vd -> (vd0, vd1), {vd0, vd1} -> vd }
     let mut vd: VecDeque<VD> = VecDeque::new();
@@ -247,7 +247,7 @@
     vd[0].descend_into_self(&mut c);
     assert!(c.saw_prev_marked);
 
-    if PRINT { println!(""); }
+    if PRINT { println!(); }
 
     // Cycle 7: { vm -> (vm0, vm1), {vm0, vm1} -> vm }
     let mut vm: HashMap<usize, VM> = HashMap::new();
@@ -262,7 +262,7 @@
     vm[&0].descend_into_self(&mut c);
     assert!(c.saw_prev_marked);
 
-    if PRINT { println!(""); }
+    if PRINT { println!(); }
 
     // Cycle 8: { ll -> (ll0, ll1), {ll0, ll1} -> ll }
     let mut ll: LinkedList<LL> = LinkedList::new();
@@ -282,7 +282,7 @@
         // break;
     }
 
-    if PRINT { println!(""); }
+    if PRINT { println!(); }
 
     // Cycle 9: { bh -> (bh0, bh1), {bh0, bh1} -> bh }
     let mut bh: BinaryHeap<BH> = BinaryHeap::new();
@@ -302,7 +302,7 @@
         // break;
     }
 
-    if PRINT { println!(""); }
+    if PRINT { println!(); }
 
     // Cycle 10: { btm -> (btk0, btv1), {bt0, bt1} -> btm }
     let mut btm: BTreeMap<BTM, BTM> = BTreeMap::new();
@@ -323,7 +323,7 @@
         // break;
     }
 
-    if PRINT { println!(""); }
+    if PRINT { println!(); }
 
     // Cycle 10: { bts -> (bts0, bts1), {bts0, bts1} -> btm }
     let mut bts: BTreeSet<BTS> = BTreeSet::new();
@@ -343,7 +343,7 @@
         // break;
     }
 
-    if PRINT { println!(""); }
+    if PRINT { println!(); }
 
     // Cycle 11: { rc0 -> (rc1, rc2), rc1 -> (), rc2 -> rc0 }
     let (rc0, rc1, rc2): (RCRC, RCRC, RCRC);
@@ -361,7 +361,7 @@
     rc0.descend_into_self(&mut c);
     assert!(c.saw_prev_marked);
 
-    if PRINT { println!(""); }
+    if PRINT { println!(); }
 
     // We want to take the previous Rc case and generalize it to Arc.
     //
@@ -395,7 +395,7 @@
     arc0.descend_into_self(&mut c);
     assert!(c.saw_prev_marked);
 
-    if PRINT { println!(""); }
+    if PRINT { println!(); }
 
     // Cycle 13: { arc0 -> (arc1, arc2), arc1 -> (), arc2 -> arc0 }, rwlocks
     let (arc0, arc1, arc2): (ARCRW, ARCRW, ARCRW);
@@ -413,7 +413,7 @@
     arc0.descend_into_self(&mut c);
     assert!(c.saw_prev_marked);
 
-    if PRINT { println!(""); }
+    if PRINT { println!(); }
 
     // Cycle 14: { arc0 -> (arc1, arc2), arc1 -> (), arc2 -> arc0 }, mutexs
     let (arc0, arc1, arc2): (ARCM, ARCM, ARCM);
diff --git a/src/test/ui/empty/empty-macro-use.stderr b/src/test/ui/empty/empty-macro-use.stderr
index 1630041..8e3e068 100644
--- a/src/test/ui/empty/empty-macro-use.stderr
+++ b/src/test/ui/empty/empty-macro-use.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `macro_two!` in this scope
+error: cannot find macro `macro_two` in this scope
   --> $DIR/empty-macro-use.rs:7:5
    |
 LL |     macro_two!();
diff --git a/src/test/ui/ext-nonexistent.stderr b/src/test/ui/ext-nonexistent.stderr
index 3fbbb49..f3aa83f 100644
--- a/src/test/ui/ext-nonexistent.stderr
+++ b/src/test/ui/ext-nonexistent.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `iamnotanextensionthatexists!` in this scope
+error: cannot find macro `iamnotanextensionthatexists` in this scope
   --> $DIR/ext-nonexistent.rs:2:13
    |
 LL | fn main() { iamnotanextensionthatexists!(""); }
diff --git a/src/test/ui/feature-gates/feature-gate-custom_attribute.rs b/src/test/ui/feature-gates/feature-gate-custom_attribute.rs
index d34936b..936cab2 100644
--- a/src/test/ui/feature-gates/feature-gate-custom_attribute.rs
+++ b/src/test/ui/feature-gates/feature-gate-custom_attribute.rs
@@ -1,18 +1,18 @@
 // Check that literals in attributes parse just fine.
 
-#[fake_attr] //~ ERROR cannot find attribute macro `fake_attr` in this scope
-#[fake_attr(100)] //~ ERROR cannot find attribute macro `fake_attr` in this scope
-#[fake_attr(1, 2, 3)] //~ ERROR cannot find attribute macro `fake_attr` in this scope
-#[fake_attr("hello")] //~ ERROR cannot find attribute macro `fake_attr` in this scope
-#[fake_attr(name = "hello")] //~ ERROR cannot find attribute macro `fake_attr` in this scope
-#[fake_attr(1, "hi", key = 12, true, false)] //~ ERROR cannot find attribute macro `fake_attr` in th
-#[fake_attr(key = "hello", val = 10)] //~ ERROR cannot find attribute macro `fake_attr` in this scop
-#[fake_attr(key("hello"), val(10))] //~ ERROR cannot find attribute macro `fake_attr` in this scope
-#[fake_attr(enabled = true, disabled = false)] //~ ERROR cannot find attribute macro `fake_attr` in
-#[fake_attr(true)] //~ ERROR cannot find attribute macro `fake_attr` in this scope
-#[fake_attr(pi = 3.14159)] //~ ERROR cannot find attribute macro `fake_attr` in this scope
-#[fake_attr(b"hi")] //~ ERROR cannot find attribute macro `fake_attr` in this scope
-#[fake_doc(r"doc")] //~ ERROR cannot find attribute macro `fake_doc` in this scope
+#[fake_attr] //~ ERROR cannot find attribute `fake_attr` in this scope
+#[fake_attr(100)] //~ ERROR cannot find attribute `fake_attr` in this scope
+#[fake_attr(1, 2, 3)] //~ ERROR cannot find attribute `fake_attr` in this scope
+#[fake_attr("hello")] //~ ERROR cannot find attribute `fake_attr` in this scope
+#[fake_attr(name = "hello")] //~ ERROR cannot find attribute `fake_attr` in this scope
+#[fake_attr(1, "hi", key = 12, true, false)] //~ ERROR cannot find attribute `fake_attr` in th
+#[fake_attr(key = "hello", val = 10)] //~ ERROR cannot find attribute `fake_attr` in this scop
+#[fake_attr(key("hello"), val(10))] //~ ERROR cannot find attribute `fake_attr` in this scope
+#[fake_attr(enabled = true, disabled = false)] //~ ERROR cannot find attribute `fake_attr` in
+#[fake_attr(true)] //~ ERROR cannot find attribute `fake_attr` in this scope
+#[fake_attr(pi = 3.14159)] //~ ERROR cannot find attribute `fake_attr` in this scope
+#[fake_attr(b"hi")] //~ ERROR cannot find attribute `fake_attr` in this scope
+#[fake_doc(r"doc")] //~ ERROR cannot find attribute `fake_doc` in this scope
 struct Q {}
 
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-custom_attribute.stderr b/src/test/ui/feature-gates/feature-gate-custom_attribute.stderr
index efdc2d1..b7c45ec 100644
--- a/src/test/ui/feature-gates/feature-gate-custom_attribute.stderr
+++ b/src/test/ui/feature-gates/feature-gate-custom_attribute.stderr
@@ -1,76 +1,76 @@
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
   --> $DIR/feature-gate-custom_attribute.rs:3:3
    |
 LL | #[fake_attr]
    |   ^^^^^^^^^
 
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
   --> $DIR/feature-gate-custom_attribute.rs:4:3
    |
 LL | #[fake_attr(100)]
    |   ^^^^^^^^^
 
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
   --> $DIR/feature-gate-custom_attribute.rs:5:3
    |
 LL | #[fake_attr(1, 2, 3)]
    |   ^^^^^^^^^
 
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
   --> $DIR/feature-gate-custom_attribute.rs:6:3
    |
 LL | #[fake_attr("hello")]
    |   ^^^^^^^^^
 
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
   --> $DIR/feature-gate-custom_attribute.rs:7:3
    |
 LL | #[fake_attr(name = "hello")]
    |   ^^^^^^^^^
 
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
   --> $DIR/feature-gate-custom_attribute.rs:8:3
    |
 LL | #[fake_attr(1, "hi", key = 12, true, false)]
    |   ^^^^^^^^^
 
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
   --> $DIR/feature-gate-custom_attribute.rs:9:3
    |
 LL | #[fake_attr(key = "hello", val = 10)]
    |   ^^^^^^^^^
 
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
   --> $DIR/feature-gate-custom_attribute.rs:10:3
    |
 LL | #[fake_attr(key("hello"), val(10))]
    |   ^^^^^^^^^
 
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
   --> $DIR/feature-gate-custom_attribute.rs:11:3
    |
 LL | #[fake_attr(enabled = true, disabled = false)]
    |   ^^^^^^^^^
 
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
   --> $DIR/feature-gate-custom_attribute.rs:12:3
    |
 LL | #[fake_attr(true)]
    |   ^^^^^^^^^
 
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
   --> $DIR/feature-gate-custom_attribute.rs:13:3
    |
 LL | #[fake_attr(pi = 3.14159)]
    |   ^^^^^^^^^
 
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
   --> $DIR/feature-gate-custom_attribute.rs:14:3
    |
 LL | #[fake_attr(b"hi")]
    |   ^^^^^^^^^
 
-error: cannot find attribute macro `fake_doc` in this scope
+error: cannot find attribute `fake_doc` in this scope
   --> $DIR/feature-gate-custom_attribute.rs:15:3
    |
 LL | #[fake_doc(r"doc")]
diff --git a/src/test/ui/feature-gates/feature-gate-custom_attribute2.rs b/src/test/ui/feature-gates/feature-gate-custom_attribute2.rs
index 51b5bf5..e4c8014 100644
--- a/src/test/ui/feature-gates/feature-gate-custom_attribute2.rs
+++ b/src/test/ui/feature-gates/feature-gate-custom_attribute2.rs
@@ -4,54 +4,54 @@
 // gate-test-custom_attribute
 
 struct StLt<#[lt_struct] 'a>(&'a u32);
-//~^ ERROR cannot find attribute macro `lt_struct` in this scope
+//~^ ERROR cannot find attribute `lt_struct` in this scope
 struct StTy<#[ty_struct] I>(I);
-//~^ ERROR cannot find attribute macro `ty_struct` in this scope
+//~^ ERROR cannot find attribute `ty_struct` in this scope
 
 enum EnLt<#[lt_enum] 'b> { A(&'b u32), B }
-//~^ ERROR cannot find attribute macro `lt_enum` in this scope
+//~^ ERROR cannot find attribute `lt_enum` in this scope
 enum EnTy<#[ty_enum] J> { A(J), B }
-//~^ ERROR cannot find attribute macro `ty_enum` in this scope
+//~^ ERROR cannot find attribute `ty_enum` in this scope
 
 trait TrLt<#[lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; }
-//~^ ERROR cannot find attribute macro `lt_trait` in this scope
+//~^ ERROR cannot find attribute `lt_trait` in this scope
 trait TrTy<#[ty_trait] K> { fn foo(&self, _: K); }
-//~^ ERROR cannot find attribute macro `ty_trait` in this scope
+//~^ ERROR cannot find attribute `ty_trait` in this scope
 
 type TyLt<#[lt_type] 'd> = &'d u32;
-//~^ ERROR cannot find attribute macro `lt_type` in this scope
+//~^ ERROR cannot find attribute `lt_type` in this scope
 type TyTy<#[ty_type] L> = (L, );
-//~^ ERROR cannot find attribute macro `ty_type` in this scope
+//~^ ERROR cannot find attribute `ty_type` in this scope
 
 impl<#[lt_inherent] 'e> StLt<'e> { }
-//~^ ERROR cannot find attribute macro `lt_inherent` in this scope
+//~^ ERROR cannot find attribute `lt_inherent` in this scope
 impl<#[ty_inherent] M> StTy<M> { }
-//~^ ERROR cannot find attribute macro `ty_inherent` in this scope
+//~^ ERROR cannot find attribute `ty_inherent` in this scope
 
 impl<#[lt_impl_for] 'f> TrLt<'f> for StLt<'f> {
-    //~^ ERROR cannot find attribute macro `lt_impl_for` in this scope
+    //~^ ERROR cannot find attribute `lt_impl_for` in this scope
     fn foo(&self, _: &'f [u32]) -> &'f u32 { loop { } }
 }
 impl<#[ty_impl_for] N> TrTy<N> for StTy<N> {
-    //~^ ERROR cannot find attribute macro `ty_impl_for` in this scope
+    //~^ ERROR cannot find attribute `ty_impl_for` in this scope
     fn foo(&self, _: N) { }
 }
 
 fn f_lt<#[lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } }
-//~^ ERROR cannot find attribute macro `lt_fn` in this scope
+//~^ ERROR cannot find attribute `lt_fn` in this scope
 fn f_ty<#[ty_fn] O>(_: O) { }
-//~^ ERROR cannot find attribute macro `ty_fn` in this scope
+//~^ ERROR cannot find attribute `ty_fn` in this scope
 
 impl<I> StTy<I> {
     fn m_lt<#[lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } }
-    //~^ ERROR cannot find attribute macro `lt_meth` in this scope
+    //~^ ERROR cannot find attribute `lt_meth` in this scope
     fn m_ty<#[ty_meth] P>(_: P) { }
-    //~^ ERROR cannot find attribute macro `ty_meth` in this scope
+    //~^ ERROR cannot find attribute `ty_meth` in this scope
 }
 
 fn hof_lt<Q>(_: Q)
     where Q: for <#[lt_hof] 'i> Fn(&'i [u32]) -> &'i u32
-    //~^ ERROR cannot find attribute macro `lt_hof` in this scope
+    //~^ ERROR cannot find attribute `lt_hof` in this scope
 {
 }
 
diff --git a/src/test/ui/feature-gates/feature-gate-custom_attribute2.stderr b/src/test/ui/feature-gates/feature-gate-custom_attribute2.stderr
index 9250616..bc89cad 100644
--- a/src/test/ui/feature-gates/feature-gate-custom_attribute2.stderr
+++ b/src/test/ui/feature-gates/feature-gate-custom_attribute2.stderr
@@ -1,100 +1,100 @@
-error: cannot find attribute macro `lt_hof` in this scope
+error: cannot find attribute `lt_hof` in this scope
   --> $DIR/feature-gate-custom_attribute2.rs:53:21
    |
 LL |     where Q: for <#[lt_hof] 'i> Fn(&'i [u32]) -> &'i u32
    |                     ^^^^^^
 
-error: cannot find attribute macro `ty_meth` in this scope
+error: cannot find attribute `ty_meth` in this scope
   --> $DIR/feature-gate-custom_attribute2.rs:48:15
    |
 LL |     fn m_ty<#[ty_meth] P>(_: P) { }
    |               ^^^^^^^
 
-error: cannot find attribute macro `lt_meth` in this scope
+error: cannot find attribute `lt_meth` in this scope
   --> $DIR/feature-gate-custom_attribute2.rs:46:15
    |
 LL |     fn m_lt<#[lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } }
    |               ^^^^^^^
 
-error: cannot find attribute macro `ty_fn` in this scope
+error: cannot find attribute `ty_fn` in this scope
   --> $DIR/feature-gate-custom_attribute2.rs:42:11
    |
 LL | fn f_ty<#[ty_fn] O>(_: O) { }
    |           ^^^^^
 
-error: cannot find attribute macro `lt_fn` in this scope
+error: cannot find attribute `lt_fn` in this scope
   --> $DIR/feature-gate-custom_attribute2.rs:40:11
    |
 LL | fn f_lt<#[lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } }
    |           ^^^^^
 
-error: cannot find attribute macro `ty_impl_for` in this scope
+error: cannot find attribute `ty_impl_for` in this scope
   --> $DIR/feature-gate-custom_attribute2.rs:35:8
    |
 LL | impl<#[ty_impl_for] N> TrTy<N> for StTy<N> {
    |        ^^^^^^^^^^^
 
-error: cannot find attribute macro `lt_impl_for` in this scope
+error: cannot find attribute `lt_impl_for` in this scope
   --> $DIR/feature-gate-custom_attribute2.rs:31:8
    |
 LL | impl<#[lt_impl_for] 'f> TrLt<'f> for StLt<'f> {
    |        ^^^^^^^^^^^
 
-error: cannot find attribute macro `ty_inherent` in this scope
+error: cannot find attribute `ty_inherent` in this scope
   --> $DIR/feature-gate-custom_attribute2.rs:28:8
    |
 LL | impl<#[ty_inherent] M> StTy<M> { }
    |        ^^^^^^^^^^^
 
-error: cannot find attribute macro `lt_inherent` in this scope
+error: cannot find attribute `lt_inherent` in this scope
   --> $DIR/feature-gate-custom_attribute2.rs:26:8
    |
 LL | impl<#[lt_inherent] 'e> StLt<'e> { }
    |        ^^^^^^^^^^^
 
-error: cannot find attribute macro `ty_type` in this scope
+error: cannot find attribute `ty_type` in this scope
   --> $DIR/feature-gate-custom_attribute2.rs:23:13
    |
 LL | type TyTy<#[ty_type] L> = (L, );
    |             ^^^^^^^
 
-error: cannot find attribute macro `lt_type` in this scope
+error: cannot find attribute `lt_type` in this scope
   --> $DIR/feature-gate-custom_attribute2.rs:21:13
    |
 LL | type TyLt<#[lt_type] 'd> = &'d u32;
    |             ^^^^^^^
 
-error: cannot find attribute macro `ty_trait` in this scope
+error: cannot find attribute `ty_trait` in this scope
   --> $DIR/feature-gate-custom_attribute2.rs:18:14
    |
 LL | trait TrTy<#[ty_trait] K> { fn foo(&self, _: K); }
    |              ^^^^^^^^
 
-error: cannot find attribute macro `lt_trait` in this scope
+error: cannot find attribute `lt_trait` in this scope
   --> $DIR/feature-gate-custom_attribute2.rs:16:14
    |
 LL | trait TrLt<#[lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; }
    |              ^^^^^^^^
 
-error: cannot find attribute macro `ty_enum` in this scope
+error: cannot find attribute `ty_enum` in this scope
   --> $DIR/feature-gate-custom_attribute2.rs:13:13
    |
 LL | enum EnTy<#[ty_enum] J> { A(J), B }
    |             ^^^^^^^
 
-error: cannot find attribute macro `lt_enum` in this scope
+error: cannot find attribute `lt_enum` in this scope
   --> $DIR/feature-gate-custom_attribute2.rs:11:13
    |
 LL | enum EnLt<#[lt_enum] 'b> { A(&'b u32), B }
    |             ^^^^^^^
 
-error: cannot find attribute macro `ty_struct` in this scope
+error: cannot find attribute `ty_struct` in this scope
   --> $DIR/feature-gate-custom_attribute2.rs:8:15
    |
 LL | struct StTy<#[ty_struct] I>(I);
    |               ^^^^^^^^^
 
-error: cannot find attribute macro `lt_struct` in this scope
+error: cannot find attribute `lt_struct` in this scope
   --> $DIR/feature-gate-custom_attribute2.rs:6:15
    |
 LL | struct StLt<#[lt_struct] 'a>(&'a u32);
diff --git a/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs b/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs
index 4044fd2..c985298 100644
--- a/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs
+++ b/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs
@@ -19,5 +19,5 @@
 //~^ ERROR the `#[rustc_dummy]` attribute is just used for rustc unit tests
 #[rustc_unknown]
 //~^ ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler
-//~| ERROR cannot find attribute macro `rustc_unknown` in this scope
+//~| ERROR cannot find attribute `rustc_unknown` in this scope
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr b/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr
index c106302..d6fdab2 100644
--- a/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr
+++ b/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr
@@ -37,7 +37,7 @@
    = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
 
-error: cannot find attribute macro `rustc_unknown` in this scope
+error: cannot find attribute `rustc_unknown` in this scope
   --> $DIR/feature-gate-rustc-attrs.rs:20:3
    |
 LL | #[rustc_unknown]
diff --git a/src/test/ui/for/for-c-in-str.rs b/src/test/ui/for/for-c-in-str.rs
index 43b1a04..0fbc796 100644
--- a/src/test/ui/for/for-c-in-str.rs
+++ b/src/test/ui/for/for-c-in-str.rs
@@ -6,6 +6,6 @@
     //~| NOTE `&str` is not an iterator
     //~| HELP the trait `std::iter::Iterator` is not implemented for `&str`
     //~| NOTE required by `std::iter::IntoIterator::into_iter`
-        println!("");
+        println!();
     }
 }
diff --git a/src/test/ui/generator/auto-trait-regions.stderr b/src/test/ui/generator/auto-trait-regions.stderr
index 92f92e2..dab4d34 100644
--- a/src/test/ui/generator/auto-trait-regions.stderr
+++ b/src/test/ui/generator/auto-trait-regions.stderr
@@ -1,20 +1,26 @@
 error: implementation of `Foo` is not general enough
   --> $DIR/auto-trait-regions.rs:30:5
    |
+LL | auto trait Foo {}
+   | ----------------- trait `Foo` defined here
+...
 LL |     assert_foo(gen);
-   |     ^^^^^^^^^^
+   |     ^^^^^^^^^^ implementation of `Foo` is not general enough
    |
-   = note: `Foo` would have to be implemented for the type `&'0 OnlyFooIfStaticRef`, for any lifetime `'0`
-   = note: but `Foo` is actually implemented for the type `&'1 OnlyFooIfStaticRef`, for some specific lifetime `'1`
+   = note: `Foo` would have to be implemented for the type `&'0 OnlyFooIfStaticRef`, for any lifetime `'0`...
+   = note: ...but `Foo` is actually implemented for the type `&'1 OnlyFooIfStaticRef`, for some specific lifetime `'1`
 
 error: implementation of `Foo` is not general enough
   --> $DIR/auto-trait-regions.rs:48:5
    |
+LL | auto trait Foo {}
+   | ----------------- trait `Foo` defined here
+...
 LL |     assert_foo(gen);
-   |     ^^^^^^^^^^
+   |     ^^^^^^^^^^ implementation of `Foo` is not general enough
    |
-   = note: `Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1`
-   = note: but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2`
+   = note: `Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1`...
+   = note: ...but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/hrtb/due-to-where-clause.rs b/src/test/ui/hrtb/due-to-where-clause.rs
new file mode 100644
index 0000000..04e2ddd
--- /dev/null
+++ b/src/test/ui/hrtb/due-to-where-clause.rs
@@ -0,0 +1,16 @@
+// ignore-compare-mode-nll
+// ^ This code works in nll mode.
+
+fn main() {
+    test::<FooS>(&mut 42); //~ ERROR implementation of `Foo` is not general enough
+}
+
+trait Foo<'a> {}
+
+struct FooS<'a> {
+    data: &'a mut u32,
+}
+
+impl<'a, 'b: 'a> Foo<'b> for FooS<'a> {}
+
+fn test<'a, F>(data: &'a mut u32) where F: for<'b> Foo<'b> {}
diff --git a/src/test/ui/hrtb/due-to-where-clause.stderr b/src/test/ui/hrtb/due-to-where-clause.stderr
new file mode 100644
index 0000000..e698584
--- /dev/null
+++ b/src/test/ui/hrtb/due-to-where-clause.stderr
@@ -0,0 +1,17 @@
+error: implementation of `Foo` is not general enough
+  --> $DIR/due-to-where-clause.rs:5:5
+   |
+LL |     test::<FooS>(&mut 42);
+   |     ^^^^^^^^^^^^ doesn't satisfy where-clause
+...
+LL | trait Foo<'a> {}
+   | ---------------- trait `Foo` defined here
+...
+LL | fn test<'a, F>(data: &'a mut u32) where F: for<'b> Foo<'b> {}
+   | ------------------------------------------------------------- due to a where-clause on `test`...
+   |
+   = note: ...`FooS<'_>` must implement `Foo<'0>`, for any lifetime `'0`...
+   = note: ...but `FooS<'_>` actually implements `Foo<'1>`, for some specific lifetime `'1`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr b/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr
index 77a5491..003f326 100644
--- a/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr
+++ b/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr
@@ -1,11 +1,14 @@
 error: implementation of `Deserialize` is not general enough
   --> $DIR/hrtb-cache-issue-54302.rs:19:5
    |
+LL | trait Deserialize<'de> {}
+   | ------------------------- trait `Deserialize` defined here
+...
 LL |     assert_deserialize_owned::<&'static str>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Deserialize` is not general enough
    |
-   = note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0`
-   = note: but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1`
+   = note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0`...
+   = note: ...but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/hrtb/issue-30786.migrate.stderr b/src/test/ui/hrtb/issue-30786.migrate.stderr
index e7deca7..c0e3fd3 100644
--- a/src/test/ui/hrtb/issue-30786.migrate.stderr
+++ b/src/test/ui/hrtb/issue-30786.migrate.stderr
@@ -1,11 +1,17 @@
 error: implementation of `Stream` is not general enough
   --> $DIR/issue-30786.rs:108:22
    |
-LL |     let map = source.map(|x: &_| x);
-   |                      ^^^
+LL | / pub trait Stream {
+LL | |     type Item;
+LL | |     fn next(self) -> Option<Self::Item>;
+LL | | }
+   | |_- trait `Stream` defined here
+...
+LL |       let map = source.map(|x: &_| x);
+   |                        ^^^ implementation of `Stream` is not general enough
    |
-   = note: `Stream` would have to be implemented for the type `&'0 mut Map<Repeat, [closure@$DIR/issue-30786.rs:108:26: 108:35]>`, for any lifetime `'0`
-   = note: but `Stream` is actually implemented for the type `&'1 mut Map<Repeat, [closure@$DIR/issue-30786.rs:108:26: 108:35]>`, for some specific lifetime `'1`
+   = note: `Stream` would have to be implemented for the type `&'0 mut Map<Repeat, [closure@$DIR/issue-30786.rs:108:26: 108:35]>`, for any lifetime `'0`...
+   = note: ...but `Stream` is actually implemented for the type `&'1 mut Map<Repeat, [closure@$DIR/issue-30786.rs:108:26: 108:35]>`, for some specific lifetime `'1`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/hrtb/issue-30786.nll.stderr b/src/test/ui/hrtb/issue-30786.nll.stderr
index 8614d86..1cfd93e 100644
--- a/src/test/ui/hrtb/issue-30786.nll.stderr
+++ b/src/test/ui/hrtb/issue-30786.nll.stderr
@@ -1,11 +1,11 @@
 error: higher-ranked subtype error
-  --> $DIR/issue-30786.rs:112:18
+  --> $DIR/issue-30786.rs:113:18
    |
 LL |     let filter = map.filter(|x: &_| true);
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: higher-ranked subtype error
-  --> $DIR/issue-30786.rs:114:17
+  --> $DIR/issue-30786.rs:115:17
    |
 LL |     let count = filter.count(); // Assert that we still have a valid stream.
    |                 ^^^^^^^^^^^^^^
diff --git a/src/test/ui/hrtb/issue-30786.rs b/src/test/ui/hrtb/issue-30786.rs
index b9920a1..c42297c 100644
--- a/src/test/ui/hrtb/issue-30786.rs
+++ b/src/test/ui/hrtb/issue-30786.rs
@@ -16,7 +16,7 @@
 
 //[nll]compile-flags: -Z borrowck=mir
 
-pub trait Stream {
+pub trait Stream { //[migrate]~ NOTE trait `Stream` defined here
     type Item;
     fn next(self) -> Option<Self::Item>;
 }
@@ -109,6 +109,7 @@
     //[migrate]~^ ERROR implementation of `Stream` is not general enough
     //[migrate]~| NOTE  `Stream` would have to be implemented for the type `&'0 mut Map
     //[migrate]~| NOTE  but `Stream` is actually implemented for the type `&'1
+    //[migrate]~| NOTE  implementation of `Stream` is not general enough
     let filter = map.filter(|x: &_| true);
     //[nll]~^ ERROR higher-ranked subtype error
     let count = filter.count(); // Assert that we still have a valid stream.
diff --git a/src/test/ui/hygiene/no_implicit_prelude-2018.rs b/src/test/ui/hygiene/no_implicit_prelude-2018.rs
index 3ad7435..83ca281 100644
--- a/src/test/ui/hygiene/no_implicit_prelude-2018.rs
+++ b/src/test/ui/hygiene/no_implicit_prelude-2018.rs
@@ -4,7 +4,7 @@
 mod bar {
     fn f() {
         ::std::print!(""); // OK
-        print!(); //~ ERROR cannot find macro `print!` in this scope
+        print!(); //~ ERROR cannot find macro `print` in this scope
     }
 }
 
diff --git a/src/test/ui/hygiene/no_implicit_prelude-2018.stderr b/src/test/ui/hygiene/no_implicit_prelude-2018.stderr
index 0fdb18d..f31b752 100644
--- a/src/test/ui/hygiene/no_implicit_prelude-2018.stderr
+++ b/src/test/ui/hygiene/no_implicit_prelude-2018.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `print!` in this scope
+error: cannot find macro `print` in this scope
   --> $DIR/no_implicit_prelude-2018.rs:7:9
    |
 LL |         print!();
diff --git a/src/test/ui/hygiene/no_implicit_prelude.rs b/src/test/ui/hygiene/no_implicit_prelude.rs
index 890c830..204e7b2 100644
--- a/src/test/ui/hygiene/no_implicit_prelude.rs
+++ b/src/test/ui/hygiene/no_implicit_prelude.rs
@@ -13,7 +13,7 @@
     }
     fn f() {
         ::foo::m!();
-        assert_eq!(0, 0); //~ ERROR cannot find macro `panic!` in this scope
+        assert_eq!(0, 0); //~ ERROR cannot find macro `panic` in this scope
     }
 }
 
diff --git a/src/test/ui/hygiene/no_implicit_prelude.stderr b/src/test/ui/hygiene/no_implicit_prelude.stderr
index 8fa55d0..bc0ce74 100644
--- a/src/test/ui/hygiene/no_implicit_prelude.stderr
+++ b/src/test/ui/hygiene/no_implicit_prelude.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `panic!` in this scope
+error: cannot find macro `panic` in this scope
   --> $DIR/no_implicit_prelude.rs:16:9
    |
 LL |         assert_eq!(0, 0);
diff --git a/src/test/ui/issues/issue-11692-1.rs b/src/test/ui/issues/issue-11692-1.rs
index 70b712c..b6f3bb8 100644
--- a/src/test/ui/issues/issue-11692-1.rs
+++ b/src/test/ui/issues/issue-11692-1.rs
@@ -1,3 +1,3 @@
 fn main() {
-    print!(testo!()); //~ ERROR cannot find macro `testo!` in this scope
+    print!(testo!()); //~ ERROR cannot find macro `testo` in this scope
 }
diff --git a/src/test/ui/issues/issue-11692-1.stderr b/src/test/ui/issues/issue-11692-1.stderr
index bfd1647..3864634 100644
--- a/src/test/ui/issues/issue-11692-1.stderr
+++ b/src/test/ui/issues/issue-11692-1.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `testo!` in this scope
+error: cannot find macro `testo` in this scope
   --> $DIR/issue-11692-1.rs:2:12
    |
 LL |     print!(testo!());
diff --git a/src/test/ui/issues/issue-11692-2.rs b/src/test/ui/issues/issue-11692-2.rs
index 61be284..5957ed3 100644
--- a/src/test/ui/issues/issue-11692-2.rs
+++ b/src/test/ui/issues/issue-11692-2.rs
@@ -1,3 +1,3 @@
 fn main() {
-    concat!(test!()); //~ ERROR cannot find macro `test!` in this scope
+    concat!(test!()); //~ ERROR cannot find macro `test` in this scope
 }
diff --git a/src/test/ui/issues/issue-11692-2.stderr b/src/test/ui/issues/issue-11692-2.stderr
index 740c355..f021943 100644
--- a/src/test/ui/issues/issue-11692-2.stderr
+++ b/src/test/ui/issues/issue-11692-2.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `test!` in this scope
+error: cannot find macro `test` in this scope
   --> $DIR/issue-11692-2.rs:2:13
    |
 LL |     concat!(test!());
diff --git a/src/test/ui/issues/issue-19734.rs b/src/test/ui/issues/issue-19734.rs
index b730e19..fe4a327 100644
--- a/src/test/ui/issues/issue-19734.rs
+++ b/src/test/ui/issues/issue-19734.rs
@@ -4,5 +4,5 @@
 
 impl Type {
     undef!();
-    //~^ ERROR cannot find macro `undef!` in this scope
+    //~^ ERROR cannot find macro `undef` in this scope
 }
diff --git a/src/test/ui/issues/issue-19734.stderr b/src/test/ui/issues/issue-19734.stderr
index fc1a7d0..8175797 100644
--- a/src/test/ui/issues/issue-19734.stderr
+++ b/src/test/ui/issues/issue-19734.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `undef!` in this scope
+error: cannot find macro `undef` in this scope
   --> $DIR/issue-19734.rs:6:5
    |
 LL |     undef!();
diff --git a/src/test/ui/issues/issue-32655.rs b/src/test/ui/issues/issue-32655.rs
index fad7bf5..f52e092 100644
--- a/src/test/ui/issues/issue-32655.rs
+++ b/src/test/ui/issues/issue-32655.rs
@@ -1,6 +1,6 @@
 macro_rules! foo (
     () => (
-        #[derive_Clone] //~ ERROR cannot find attribute macro `derive_Clone` in this scope
+        #[derive_Clone] //~ ERROR cannot find attribute `derive_Clone` in this scope
         struct T;
     );
 );
@@ -12,7 +12,7 @@
 foo!();
 
 bar!(
-    #[derive_Clone] //~ ERROR cannot find attribute macro `derive_Clone` in this scope
+    #[derive_Clone] //~ ERROR cannot find attribute `derive_Clone` in this scope
     struct S;
 );
 
diff --git a/src/test/ui/issues/issue-32655.stderr b/src/test/ui/issues/issue-32655.stderr
index e13bed0..ca085b2 100644
--- a/src/test/ui/issues/issue-32655.stderr
+++ b/src/test/ui/issues/issue-32655.stderr
@@ -1,4 +1,4 @@
-error: cannot find attribute macro `derive_Clone` in this scope
+error: cannot find attribute `derive_Clone` in this scope
   --> $DIR/issue-32655.rs:3:11
    |
 LL |         #[derive_Clone]
@@ -7,7 +7,7 @@
 LL | foo!();
    | ------- in this macro invocation
 
-error: cannot find attribute macro `derive_Clone` in this scope
+error: cannot find attribute `derive_Clone` in this scope
   --> $DIR/issue-32655.rs:15:7
    |
 LL |     #[derive_Clone]
diff --git a/src/test/ui/issues/issue-40845.rs b/src/test/ui/issues/issue-40845.rs
index c9102f4..a4ede6a 100644
--- a/src/test/ui/issues/issue-40845.rs
+++ b/src/test/ui/issues/issue-40845.rs
@@ -1,6 +1,6 @@
-trait T { m!(); } //~ ERROR cannot find macro `m!` in this scope
+trait T { m!(); } //~ ERROR cannot find macro `m` in this scope
 
 struct S;
-impl S { m!(); } //~ ERROR cannot find macro `m!` in this scope
+impl S { m!(); } //~ ERROR cannot find macro `m` in this scope
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-40845.stderr b/src/test/ui/issues/issue-40845.stderr
index a8be38e..2744330 100644
--- a/src/test/ui/issues/issue-40845.stderr
+++ b/src/test/ui/issues/issue-40845.stderr
@@ -1,10 +1,10 @@
-error: cannot find macro `m!` in this scope
+error: cannot find macro `m` in this scope
   --> $DIR/issue-40845.rs:4:10
    |
 LL | impl S { m!(); }
    |          ^
 
-error: cannot find macro `m!` in this scope
+error: cannot find macro `m` in this scope
   --> $DIR/issue-40845.rs:1:11
    |
 LL | trait T { m!(); }
diff --git a/src/test/ui/issues/issue-44415.stderr b/src/test/ui/issues/issue-44415.stderr
deleted file mode 100644
index 8008e53..0000000
--- a/src/test/ui/issues/issue-44415.stderr
+++ /dev/null
@@ -1,28 +0,0 @@
-error[E0391]: cycle detected when const-evaluating + checking `Foo::bytes::{{constant}}#0`
-  --> $DIR/issue-44415.rs:6:17
-   |
-LL |     bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
-   |                 ^^^^^^
-   |
-note: ...which requires const-evaluating + checking `Foo::bytes::{{constant}}#0`...
-  --> $DIR/issue-44415.rs:6:17
-   |
-LL |     bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
-   |                 ^^^^^^
-note: ...which requires const-evaluating `Foo::bytes::{{constant}}#0`...
-  --> $DIR/issue-44415.rs:6:26
-   |
-LL |     bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which requires computing layout of `Foo`...
-   = note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All, def_id: None }, value: [u8; _] }`...
-   = note: ...which again requires const-evaluating + checking `Foo::bytes::{{constant}}#0`, completing the cycle
-note: cycle used when processing `Foo`
-  --> $DIR/issue-44415.rs:5:1
-   |
-LL | struct Foo {
-   | ^^^^^^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/issues/issue-49074.rs b/src/test/ui/issues/issue-49074.rs
index 38074d5..752bb34 100644
--- a/src/test/ui/issues/issue-49074.rs
+++ b/src/test/ui/issues/issue-49074.rs
@@ -1,7 +1,7 @@
 // Check that unknown attribute error is shown even if there are unresolved macros.
 
 #[marco_use] // typo
-//~^ ERROR cannot find attribute macro `marco_use` in this scope
+//~^ ERROR cannot find attribute `marco_use` in this scope
 mod foo {
     macro_rules! bar {
         () => ();
@@ -9,5 +9,5 @@
 }
 
 fn main() {
-   bar!(); //~ ERROR cannot find macro `bar!` in this scope
+   bar!(); //~ ERROR cannot find macro `bar` in this scope
 }
diff --git a/src/test/ui/issues/issue-49074.stderr b/src/test/ui/issues/issue-49074.stderr
index e0d3bb3..bbfeb4e 100644
--- a/src/test/ui/issues/issue-49074.stderr
+++ b/src/test/ui/issues/issue-49074.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `bar!` in this scope
+error: cannot find macro `bar` in this scope
   --> $DIR/issue-49074.rs:12:4
    |
 LL |    bar!();
@@ -6,7 +6,7 @@
    |
    = help: have you added the `#[macro_use]` on the module/import?
 
-error: cannot find attribute macro `marco_use` in this scope
+error: cannot find attribute `marco_use` in this scope
   --> $DIR/issue-49074.rs:3:3
    |
 LL | #[marco_use] // typo
diff --git a/src/test/ui/issues/issue-54302-cases.stderr b/src/test/ui/issues/issue-54302-cases.stderr
index 9863761..3ed2779 100644
--- a/src/test/ui/issues/issue-54302-cases.stderr
+++ b/src/test/ui/issues/issue-54302-cases.stderr
@@ -1,38 +1,58 @@
 error: implementation of `Foo` is not general enough
   --> $DIR/issue-54302-cases.rs:63:5
    |
-LL |     <u32 as RefFoo<u32>>::ref_foo(a)
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | / trait Foo<'x, T> {
+LL | |     fn foo(self) -> &'x T;
+LL | | }
+   | |_- trait `Foo` defined here
+...
+LL |       <u32 as RefFoo<u32>>::ref_foo(a)
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
    |
-   = note: `Foo<'static, u32>` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`
-   = note: but `Foo<'_, u32>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1`
+   = note: `Foo<'static, u32>` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`...
+   = note: ...but `Foo<'_, u32>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1`
 
 error: implementation of `Foo` is not general enough
   --> $DIR/issue-54302-cases.rs:69:5
    |
-LL |     <i32 as RefFoo<i32>>::ref_foo(a)
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | / trait Foo<'x, T> {
+LL | |     fn foo(self) -> &'x T;
+LL | | }
+   | |_- trait `Foo` defined here
+...
+LL |       <i32 as RefFoo<i32>>::ref_foo(a)
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
    |
-   = note: `Foo<'static, i32>` would have to be implemented for the type `&'0 i32`, for any lifetime `'0`
-   = note: but `Foo<'_, i32>` is actually implemented for the type `&'1 i32`, for some specific lifetime `'1`
+   = note: `Foo<'static, i32>` would have to be implemented for the type `&'0 i32`, for any lifetime `'0`...
+   = note: ...but `Foo<'_, i32>` is actually implemented for the type `&'1 i32`, for some specific lifetime `'1`
 
 error: implementation of `Foo` is not general enough
   --> $DIR/issue-54302-cases.rs:75:5
    |
-LL |     <u64 as RefFoo<u64>>::ref_foo(a)
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | / trait Foo<'x, T> {
+LL | |     fn foo(self) -> &'x T;
+LL | | }
+   | |_- trait `Foo` defined here
+...
+LL |       <u64 as RefFoo<u64>>::ref_foo(a)
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
    |
-   = note: `Foo<'static, u64>` would have to be implemented for the type `&'0 u64`, for any lifetime `'0`
-   = note: but `Foo<'_, u64>` is actually implemented for the type `&'1 u64`, for some specific lifetime `'1`
+   = note: `Foo<'static, u64>` would have to be implemented for the type `&'0 u64`, for any lifetime `'0`...
+   = note: ...but `Foo<'_, u64>` is actually implemented for the type `&'1 u64`, for some specific lifetime `'1`
 
 error: implementation of `Foo` is not general enough
   --> $DIR/issue-54302-cases.rs:81:5
    |
-LL |     <i64 as RefFoo<i64>>::ref_foo(a)
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | / trait Foo<'x, T> {
+LL | |     fn foo(self) -> &'x T;
+LL | | }
+   | |_- trait `Foo` defined here
+...
+LL |       <i64 as RefFoo<i64>>::ref_foo(a)
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
    |
-   = note: `Foo<'static, i64>` would have to be implemented for the type `&'0 i64`, for any lifetime `'0`
-   = note: but `Foo<'_, i64>` is actually implemented for the type `&'1 i64`, for some specific lifetime `'1`
+   = note: `Foo<'static, i64>` would have to be implemented for the type `&'0 i64`, for any lifetime `'0`...
+   = note: ...but `Foo<'_, i64>` is actually implemented for the type `&'1 i64`, for some specific lifetime `'1`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/issues/issue-54302.stderr b/src/test/ui/issues/issue-54302.stderr
index c6d0805..1b3f57b 100644
--- a/src/test/ui/issues/issue-54302.stderr
+++ b/src/test/ui/issues/issue-54302.stderr
@@ -1,11 +1,14 @@
 error: implementation of `Deserialize` is not general enough
   --> $DIR/issue-54302.rs:13:5
    |
+LL | trait Deserialize<'de> {}
+   | ------------------------- trait `Deserialize` defined here
+...
 LL |     assert_deserialize_owned::<&'static str>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Deserialize` is not general enough
    |
-   = note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0`
-   = note: but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1`
+   = note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0`...
+   = note: ...but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-55731.stderr b/src/test/ui/issues/issue-55731.stderr
index f25e18e..f44c842 100644
--- a/src/test/ui/issues/issue-55731.stderr
+++ b/src/test/ui/issues/issue-55731.stderr
@@ -1,11 +1,16 @@
 error: implementation of `DistributedIteratorMulti` is not general enough
   --> $DIR/issue-55731.rs:48:5
    |
-LL |     multi(Map {
-   |     ^^^^^
+LL | / trait DistributedIteratorMulti<Source> {
+LL | |     type Item;
+LL | | }
+   | |_- trait `DistributedIteratorMulti` defined here
+...
+LL |       multi(Map {
+   |       ^^^^^ implementation of `DistributedIteratorMulti` is not general enough
    |
-   = note: `DistributedIteratorMulti<&'0 ()>` would have to be implemented for the type `Cloned<&()>`, for any lifetime `'0`
-   = note: but `DistributedIteratorMulti<&'1 ()>` is actually implemented for the type `Cloned<&'1 ()>`, for some specific lifetime `'1`
+   = note: `DistributedIteratorMulti<&'0 ()>` would have to be implemented for the type `Cloned<&()>`, for any lifetime `'0`...
+   = note: ...but `DistributedIteratorMulti<&'1 ()>` is actually implemented for the type `Cloned<&'1 ()>`, for some specific lifetime `'1`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/json-short.stderr b/src/test/ui/json-short.stderr
index 86cb2f0..0a1fb56 100644
--- a/src/test/ui/json-short.stderr
+++ b/src/test/ui/json-short.stderr
@@ -15,5 +15,5 @@
 "}
 {"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error
 "}
-{"message":"For more information about this error, try `rustc --explain E0601`.","code":null,"level":"","spans":[],"children":[],"rendered":"For more information about this error, try `rustc --explain E0601`.
+{"message":"For more information about this error, try `rustc --explain E0601`.","code":null,"level":"failure-note","spans":[],"children":[],"rendered":"For more information about this error, try `rustc --explain E0601`.
 "}
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.nll.stderr
index 779e2eb..2ed4d6d 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.nll.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.nll.stderr
@@ -12,11 +12,11 @@
   --> $DIR/ex3-both-anon-regions-3.rs:2:5
    |
 LL | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
-   |                         -                    - let's call the lifetime of this reference `'1`
+   |                         -                    - let's call the lifetime of this reference `'3`
    |                         |
-   |                         let's call the lifetime of this reference `'2`
+   |                         let's call the lifetime of this reference `'4`
 LL |     z.push((x,y));
-   |     ^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
+   |     ^^^^^^^^^^^^^ argument requires that `'3` must outlive `'4`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/lint/issue-54538-unused-parens-lint.rs b/src/test/ui/lint/issue-54538-unused-parens-lint.rs
index 1d8cce5..7dcbdd0 100644
--- a/src/test/ui/lint/issue-54538-unused-parens-lint.rs
+++ b/src/test/ui/lint/issue-54538-unused-parens-lint.rs
@@ -1,4 +1,4 @@
-#![feature(box_patterns)]
+#![feature(box_patterns, stmt_expr_attributes)]
 
 #![feature(or_patterns)]
 //~^ WARN the feature `or_patterns` is incomplete
@@ -17,6 +17,10 @@
     let _ = |(a): u8| 0; //~ ERROR unnecessary parentheses around pattern
 }
 
+fn _no_lint_attr() {
+    let _x = #[allow(dead_code)] (1 + 2);
+}
+
 // Don't lint in these cases (#64106).
 fn or_patterns_no_lint() {
     match Box::new(0) {
diff --git a/src/test/ui/lint/issue-54538-unused-parens-lint.stderr b/src/test/ui/lint/issue-54538-unused-parens-lint.stderr
index 7d5e286..675dd4f 100644
--- a/src/test/ui/lint/issue-54538-unused-parens-lint.stderr
+++ b/src/test/ui/lint/issue-54538-unused-parens-lint.stderr
@@ -49,109 +49,109 @@
    |              ^^^ help: remove these parentheses
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:41:12
+  --> $DIR/issue-54538-unused-parens-lint.rs:45:12
    |
 LL |     if let (0 | 1) = 0 {}
    |            ^^^^^^^ help: remove these parentheses
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:42:13
+  --> $DIR/issue-54538-unused-parens-lint.rs:46:13
    |
 LL |     if let ((0 | 1),) = (0,) {}
    |             ^^^^^^^ help: remove these parentheses
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:43:13
+  --> $DIR/issue-54538-unused-parens-lint.rs:47:13
    |
 LL |     if let [(0 | 1)] = [0] {}
    |             ^^^^^^^ help: remove these parentheses
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:44:16
+  --> $DIR/issue-54538-unused-parens-lint.rs:48:16
    |
 LL |     if let 0 | (1 | 2) = 0 {}
    |                ^^^^^^^ help: remove these parentheses
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:46:15
+  --> $DIR/issue-54538-unused-parens-lint.rs:50:15
    |
 LL |     if let TS((0 | 1)) = TS(0) {}
    |               ^^^^^^^ help: remove these parentheses
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:48:20
+  --> $DIR/issue-54538-unused-parens-lint.rs:52:20
    |
 LL |     if let NS { f: (0 | 1) } = (NS { f: 0 }) {}
    |                    ^^^^^^^ help: remove these parentheses
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:58:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:62:9
    |
 LL |         (_) => {}
    |         ^^^ help: remove these parentheses
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:59:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:63:9
    |
 LL |         (y) => {}
    |         ^^^ help: remove these parentheses
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:60:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:64:9
    |
 LL |         (ref r) => {}
    |         ^^^^^^^ help: remove these parentheses
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:61:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:65:9
    |
 LL |         (e @ 1...2) => {}
    |         ^^^^^^^^^^^ help: remove these parentheses
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:67:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:71:9
    |
 LL |         (e @ &(1...2)) => {}
    |         ^^^^^^^^^^^^^^ help: remove these parentheses
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:68:10
+  --> $DIR/issue-54538-unused-parens-lint.rs:72:10
    |
 LL |         &(_) => {}
    |          ^^^ help: remove these parentheses
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:79:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:83:9
    |
 LL |         (_) => {}
    |         ^^^ help: remove these parentheses
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:80:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:84:9
    |
 LL |         (y) => {}
    |         ^^^ help: remove these parentheses
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:81:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:85:9
    |
 LL |         (ref r) => {}
    |         ^^^^^^^ help: remove these parentheses
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:82:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:86:9
    |
 LL |         (e @ 1..=2) => {}
    |         ^^^^^^^^^^^ help: remove these parentheses
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:88:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:92:9
    |
 LL |         (e @ &(1..=2)) => {}
    |         ^^^^^^^^^^^^^^ help: remove these parentheses
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:89:10
+  --> $DIR/issue-54538-unused-parens-lint.rs:93:10
    |
 LL |         &(_) => {}
    |          ^^^ help: remove these parentheses
diff --git a/src/test/ui/lint/use_suggestion_json.stderr b/src/test/ui/lint/use_suggestion_json.stderr
index c7c53ab..678c888 100644
--- a/src/test/ui/lint/use_suggestion_json.stderr
+++ b/src/test/ui/lint/use_suggestion_json.stderr
@@ -412,7 +412,7 @@
 {
   "message": "For more information about this error, try `rustc --explain E0412`.",
   "code": null,
-  "level": "",
+  "level": "failure-note",
   "spans": [],
   "children": [],
   "rendered": "\u001b[0m\u001b[1mFor more information about this error, try `rustc --explain E0412`.\u001b[0m
diff --git a/src/test/ui/macros/macro-expansion-tests.stderr b/src/test/ui/macros/macro-expansion-tests.stderr
index 4ad9ade..8b3f7ca 100644
--- a/src/test/ui/macros/macro-expansion-tests.stderr
+++ b/src/test/ui/macros/macro-expansion-tests.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `m!` in this scope
+error: cannot find macro `m` in this scope
   --> $DIR/macro-expansion-tests.rs:7:21
    |
 LL |     fn g() -> i32 { m!() }
@@ -6,7 +6,7 @@
    |
    = help: have you added the `#[macro_use]` on the module/import?
 
-error: cannot find macro `m!` in this scope
+error: cannot find macro `m` in this scope
   --> $DIR/macro-expansion-tests.rs:15:21
    |
 LL |     fn g() -> i32 { m!() }
diff --git a/src/test/ui/macros/macro-name-typo.stderr b/src/test/ui/macros/macro-name-typo.stderr
index 967f4f3..ce2e198 100644
--- a/src/test/ui/macros/macro-name-typo.stderr
+++ b/src/test/ui/macros/macro-name-typo.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `printlx!` in this scope
+error: cannot find macro `printlx` in this scope
   --> $DIR/macro-name-typo.rs:2:5
    |
 LL |     printlx!("oh noes!");
diff --git a/src/test/ui/macros/macro-path-prelude-fail-3.rs b/src/test/ui/macros/macro-path-prelude-fail-3.rs
index 597053d..68eb350 100644
--- a/src/test/ui/macros/macro-path-prelude-fail-3.rs
+++ b/src/test/ui/macros/macro-path-prelude-fail-3.rs
@@ -1,3 +1,3 @@
 fn main() {
-    inline!(); //~ ERROR cannot find macro `inline!` in this scope
+    inline!(); //~ ERROR cannot find macro `inline` in this scope
 }
diff --git a/src/test/ui/macros/macro-path-prelude-fail-3.stderr b/src/test/ui/macros/macro-path-prelude-fail-3.stderr
index 96b8a24..ec00760 100644
--- a/src/test/ui/macros/macro-path-prelude-fail-3.stderr
+++ b/src/test/ui/macros/macro-path-prelude-fail-3.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `inline!` in this scope
+error: cannot find macro `inline` in this scope
   --> $DIR/macro-path-prelude-fail-3.rs:2:5
    |
 LL |     inline!();
diff --git a/src/test/ui/macros/macro-reexport-removed.rs b/src/test/ui/macros/macro-reexport-removed.rs
index b69a1fa..874c94d 100644
--- a/src/test/ui/macros/macro-reexport-removed.rs
+++ b/src/test/ui/macros/macro-reexport-removed.rs
@@ -2,7 +2,7 @@
 
 #![feature(macro_reexport)] //~ ERROR feature has been removed
 
-#[macro_reexport(macro_one)] //~ ERROR cannot find attribute macro `macro_reexport` in this scope
+#[macro_reexport(macro_one)] //~ ERROR cannot find attribute `macro_reexport` in this scope
 extern crate two_macros;
 
 fn main() {}
diff --git a/src/test/ui/macros/macro-reexport-removed.stderr b/src/test/ui/macros/macro-reexport-removed.stderr
index 25778fb..4bec708 100644
--- a/src/test/ui/macros/macro-reexport-removed.stderr
+++ b/src/test/ui/macros/macro-reexport-removed.stderr
@@ -10,7 +10,7 @@
 LL | #![feature(macro_reexport)]
    |            ^^^^^^^^^^^^^^
 
-error: cannot find attribute macro `macro_reexport` in this scope
+error: cannot find attribute `macro_reexport` in this scope
   --> $DIR/macro-reexport-removed.rs:5:3
    |
 LL | #[macro_reexport(macro_one)]
diff --git a/src/test/ui/macros/macro-use-wrong-name.stderr b/src/test/ui/macros/macro-use-wrong-name.stderr
index 28f727d..8b4e90a 100644
--- a/src/test/ui/macros/macro-use-wrong-name.stderr
+++ b/src/test/ui/macros/macro-use-wrong-name.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `macro_two!` in this scope
+error: cannot find macro `macro_two` in this scope
   --> $DIR/macro-use-wrong-name.rs:7:5
    |
 LL |     macro_two!();
diff --git a/src/test/ui/macros/macro_undefined.stderr b/src/test/ui/macros/macro_undefined.stderr
index 9239b2a..01c8ebe 100644
--- a/src/test/ui/macros/macro_undefined.stderr
+++ b/src/test/ui/macros/macro_undefined.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `k!` in this scope
+error: cannot find macro `k` in this scope
   --> $DIR/macro_undefined.rs:11:5
    |
 LL |     k!();
diff --git a/src/test/ui/missing/missing-macro-use.rs b/src/test/ui/missing/missing-macro-use.rs
index dff4c94..d494c44 100644
--- a/src/test/ui/missing/missing-macro-use.rs
+++ b/src/test/ui/missing/missing-macro-use.rs
@@ -4,5 +4,5 @@
 
 pub fn main() {
     macro_two!();
-    //~^ ERROR cannot find macro `macro_two!` in this scope
+    //~^ ERROR cannot find macro `macro_two` in this scope
 }
diff --git a/src/test/ui/missing/missing-macro-use.stderr b/src/test/ui/missing/missing-macro-use.stderr
index 01a7beb..711e249 100644
--- a/src/test/ui/missing/missing-macro-use.stderr
+++ b/src/test/ui/missing/missing-macro-use.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `macro_two!` in this scope
+error: cannot find macro `macro_two` in this scope
   --> $DIR/missing-macro-use.rs:6:5
    |
 LL |     macro_two!();
diff --git a/src/test/ui/proc-macro/derive-still-gated.rs b/src/test/ui/proc-macro/derive-still-gated.rs
index 4e6f9b0..3f8d6f0 100644
--- a/src/test/ui/proc-macro/derive-still-gated.rs
+++ b/src/test/ui/proc-macro/derive-still-gated.rs
@@ -3,7 +3,7 @@
 #[macro_use]
 extern crate test_macros;
 
-#[derive_Empty] //~ ERROR cannot find attribute macro `derive_Empty` in this scope
+#[derive_Empty] //~ ERROR cannot find attribute `derive_Empty` in this scope
 struct A;
 
 fn main() {}
diff --git a/src/test/ui/proc-macro/derive-still-gated.stderr b/src/test/ui/proc-macro/derive-still-gated.stderr
index 4df1715..99289fd 100644
--- a/src/test/ui/proc-macro/derive-still-gated.stderr
+++ b/src/test/ui/proc-macro/derive-still-gated.stderr
@@ -1,4 +1,4 @@
-error: cannot find attribute macro `derive_Empty` in this scope
+error: cannot find attribute `derive_Empty` in this scope
   --> $DIR/derive-still-gated.rs:6:3
    |
 LL | #[derive_Empty]
diff --git a/src/test/ui/proc-macro/macro-namespace-reserved-2.rs b/src/test/ui/proc-macro/macro-namespace-reserved-2.rs
index 8a26df9..b17c056 100644
--- a/src/test/ui/proc-macro/macro-namespace-reserved-2.rs
+++ b/src/test/ui/proc-macro/macro-namespace-reserved-2.rs
@@ -25,17 +25,17 @@
     my_macro!(); //~ ERROR can't use a procedural macro from the same crate that defines it
 }
 fn check_bang2() {
-    my_macro_attr!(); //~ ERROR cannot find macro `my_macro_attr!` in this scope
+    my_macro_attr!(); //~ ERROR cannot find macro `my_macro_attr` in this scope
     crate::my_macro_attr!(); //~ ERROR can't use a procedural macro from the same crate that defines
                              //~| ERROR expected macro, found attribute macro `crate::my_macro_attr`
 }
 fn check_bang3() {
-    MyTrait!(); //~ ERROR cannot find macro `MyTrait!` in this scope
+    MyTrait!(); //~ ERROR cannot find macro `MyTrait` in this scope
     crate::MyTrait!(); //~ ERROR can't use a procedural macro from the same crate that defines it
                        //~| ERROR expected macro, found derive macro `crate::MyTrait`
 }
 
-#[my_macro] //~ ERROR cannot find attribute macro `my_macro` in this scope
+#[my_macro] //~ ERROR cannot find attribute `my_macro` in this scope
 #[crate::my_macro] //~ ERROR can't use a procedural macro from the same crate that defines it
                    //~| ERROR expected attribute, found macro `crate::my_macro`
 fn check_attr1() {}
diff --git a/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr b/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr
index 0c863e9..c011a70 100644
--- a/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr
+++ b/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr
@@ -88,19 +88,19 @@
 LL | #[derive(crate::my_macro)]
    |          ^^^^^^^^^^^^^^^ not a derive macro
 
-error: cannot find macro `my_macro_attr!` in this scope
+error: cannot find macro `my_macro_attr` in this scope
   --> $DIR/macro-namespace-reserved-2.rs:28:5
    |
 LL |     my_macro_attr!();
    |     ^^^^^^^^^^^^^
 
-error: cannot find macro `MyTrait!` in this scope
+error: cannot find macro `MyTrait` in this scope
   --> $DIR/macro-namespace-reserved-2.rs:33:5
    |
 LL |     MyTrait!();
    |     ^^^^^^^
 
-error: cannot find attribute macro `my_macro` in this scope
+error: cannot find attribute `my_macro` in this scope
   --> $DIR/macro-namespace-reserved-2.rs:38:3
    |
 LL | #[my_macro]
diff --git a/src/test/ui/proc-macro/proc-macro-attributes.rs b/src/test/ui/proc-macro/proc-macro-attributes.rs
index 0421522..6401522 100644
--- a/src/test/ui/proc-macro/proc-macro-attributes.rs
+++ b/src/test/ui/proc-macro/proc-macro-attributes.rs
@@ -4,7 +4,7 @@
 extern crate derive_b;
 
 #[B] //~ ERROR `B` is ambiguous
-#[C] //~ ERROR cannot find attribute macro `C` in this scope
+#[C] //~ ERROR cannot find attribute `C` in this scope
 #[B(D)] //~ ERROR `B` is ambiguous
 #[B(E = "foo")] //~ ERROR `B` is ambiguous
 #[B(arbitrary tokens)] //~ ERROR `B` is ambiguous
diff --git a/src/test/ui/proc-macro/proc-macro-attributes.stderr b/src/test/ui/proc-macro/proc-macro-attributes.stderr
index b068c6b..3ac93a7 100644
--- a/src/test/ui/proc-macro/proc-macro-attributes.stderr
+++ b/src/test/ui/proc-macro/proc-macro-attributes.stderr
@@ -1,4 +1,4 @@
-error: cannot find attribute macro `C` in this scope
+error: cannot find attribute `C` in this scope
   --> $DIR/proc-macro-attributes.rs:7:3
    |
 LL | #[C]
diff --git a/src/test/ui/proc-macro/resolve-error.rs b/src/test/ui/proc-macro/resolve-error.rs
index 088f39c..d2282af 100644
--- a/src/test/ui/proc-macro/resolve-error.rs
+++ b/src/test/ui/proc-macro/resolve-error.rs
@@ -24,11 +24,11 @@
 struct Foo;
 
 // Interpreted as an unstable custom attribute
-#[attr_proc_macra] //~ ERROR cannot find attribute macro `attr_proc_macra` in this scope
+#[attr_proc_macra] //~ ERROR cannot find attribute `attr_proc_macra` in this scope
 struct Bar;
 
 // Interpreted as an unstable custom attribute
-#[FooWithLongNan] //~ ERROR cannot find attribute macro `FooWithLongNan` in this scope
+#[FooWithLongNan] //~ ERROR cannot find attribute `FooWithLongNan` in this scope
 struct Asdf;
 
 #[derive(Dlone)]
diff --git a/src/test/ui/proc-macro/resolve-error.stderr b/src/test/ui/proc-macro/resolve-error.stderr
index 2a5f2b8..3dca5ce 100644
--- a/src/test/ui/proc-macro/resolve-error.stderr
+++ b/src/test/ui/proc-macro/resolve-error.stderr
@@ -1,22 +1,22 @@
-error: cannot find macro `bang_proc_macrp!` in this scope
+error: cannot find macro `bang_proc_macrp` in this scope
   --> $DIR/resolve-error.rs:56:5
    |
 LL |     bang_proc_macrp!();
    |     ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `bang_proc_macro`
 
-error: cannot find macro `Dlona!` in this scope
+error: cannot find macro `Dlona` in this scope
   --> $DIR/resolve-error.rs:53:5
    |
 LL |     Dlona!();
    |     ^^^^^
 
-error: cannot find macro `attr_proc_macra!` in this scope
+error: cannot find macro `attr_proc_macra` in this scope
   --> $DIR/resolve-error.rs:50:5
    |
 LL |     attr_proc_macra!();
    |     ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `attr_proc_mac`
 
-error: cannot find macro `FooWithLongNama!` in this scope
+error: cannot find macro `FooWithLongNama` in this scope
   --> $DIR/resolve-error.rs:47:5
    |
 LL |     FooWithLongNama!();
@@ -40,13 +40,13 @@
 LL | #[derive(Dlone)]
    |          ^^^^^ help: a derive macro with a similar name exists: `Clone`
 
-error: cannot find attribute macro `FooWithLongNan` in this scope
+error: cannot find attribute `FooWithLongNan` in this scope
   --> $DIR/resolve-error.rs:31:3
    |
 LL | #[FooWithLongNan]
    |   ^^^^^^^^^^^^^^
 
-error: cannot find attribute macro `attr_proc_macra` in this scope
+error: cannot find attribute `attr_proc_macra` in this scope
   --> $DIR/resolve-error.rs:27:3
    |
 LL | #[attr_proc_macra]
diff --git a/src/test/ui/reserved/reserved-attr-on-macro.rs b/src/test/ui/reserved/reserved-attr-on-macro.rs
index fddb991..2630db0 100644
--- a/src/test/ui/reserved/reserved-attr-on-macro.rs
+++ b/src/test/ui/reserved/reserved-attr-on-macro.rs
@@ -1,5 +1,5 @@
 #[rustc_attribute_should_be_reserved]
-//~^ ERROR cannot find attribute macro `rustc_attribute_should_be_reserved` in this scope
+//~^ ERROR cannot find attribute `rustc_attribute_should_be_reserved` in this scope
 //~| ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler
 
 macro_rules! foo {
diff --git a/src/test/ui/reserved/reserved-attr-on-macro.stderr b/src/test/ui/reserved/reserved-attr-on-macro.stderr
index 856162b..6859605 100644
--- a/src/test/ui/reserved/reserved-attr-on-macro.stderr
+++ b/src/test/ui/reserved/reserved-attr-on-macro.stderr
@@ -15,7 +15,7 @@
    |
    = note: import resolution is stuck, try simplifying macro imports
 
-error: cannot find attribute macro `rustc_attribute_should_be_reserved` in this scope
+error: cannot find attribute `rustc_attribute_should_be_reserved` in this scope
   --> $DIR/reserved-attr-on-macro.rs:1:3
    |
 LL | #[rustc_attribute_should_be_reserved]
diff --git a/src/test/ui/resolve/visibility-indeterminate.rs b/src/test/ui/resolve/visibility-indeterminate.rs
index 198ea75..0e1142d 100644
--- a/src/test/ui/resolve/visibility-indeterminate.rs
+++ b/src/test/ui/resolve/visibility-indeterminate.rs
@@ -1,6 +1,6 @@
 // edition:2018
 
-foo!(); //~ ERROR cannot find macro `foo!` in this scope
+foo!(); //~ ERROR cannot find macro `foo` in this scope
 
 pub(in ::bar) struct Baz {} //~ ERROR cannot determine resolution for the visibility
 
diff --git a/src/test/ui/resolve/visibility-indeterminate.stderr b/src/test/ui/resolve/visibility-indeterminate.stderr
index 17927a5..b967829 100644
--- a/src/test/ui/resolve/visibility-indeterminate.stderr
+++ b/src/test/ui/resolve/visibility-indeterminate.stderr
@@ -4,7 +4,7 @@
 LL | pub(in ::bar) struct Baz {}
    |        ^^^^^
 
-error: cannot find macro `foo!` in this scope
+error: cannot find macro `foo` in this scope
   --> $DIR/visibility-indeterminate.rs:3:1
    |
 LL | foo!();
diff --git a/src/test/ui/save-analysis/issue-63663.rs b/src/test/ui/save-analysis/issue-63663.rs
new file mode 100644
index 0000000..92e8588
--- /dev/null
+++ b/src/test/ui/save-analysis/issue-63663.rs
@@ -0,0 +1,28 @@
+// check-pass
+// compile-flags: -Zsave-analysis
+
+pub trait Trait {
+    type Assoc;
+}
+
+pub struct A;
+
+trait Generic<T> {}
+impl<T> Generic<T> for () {}
+
+// Don't ICE when resolving type paths in return type `impl Trait`
+fn assoc_in_opaque_type_bounds<U: Trait>() -> impl Generic<U::Assoc> {}
+
+// Check that this doesn't ICE when processing associated const in formal
+// argument and return type of functions defined inside function/method scope.
+pub fn func() {
+    fn _inner1<U: Trait>(_: U::Assoc) {}
+    fn _inner2<U: Trait>() -> U::Assoc { unimplemented!() }
+
+    impl A {
+        fn _inner1<U: Trait>(self, _: U::Assoc) {}
+        fn _inner2<U: Trait>(self) -> U::Assoc { unimplemented!() }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/self/self_type_keyword.rs b/src/test/ui/self/self_type_keyword.rs
index 844f13c..dfb7d65 100644
--- a/src/test/ui/self/self_type_keyword.rs
+++ b/src/test/ui/self/self_type_keyword.rs
@@ -19,7 +19,7 @@
         ref mut Self => (),
         //~^ ERROR expected identifier, found keyword `Self`
         Self!() => (),
-        //~^ ERROR cannot find macro `Self!` in this scope
+        //~^ ERROR cannot find macro `Self` in this scope
         Foo { Self } => (),
         //~^ ERROR expected identifier, found keyword `Self`
     }
diff --git a/src/test/ui/self/self_type_keyword.stderr b/src/test/ui/self/self_type_keyword.stderr
index bb63119..11b3b01 100644
--- a/src/test/ui/self/self_type_keyword.stderr
+++ b/src/test/ui/self/self_type_keyword.stderr
@@ -54,7 +54,7 @@
 LL | struct Bar<'Self>;
    |            ^^^^^
 
-error: cannot find macro `Self!` in this scope
+error: cannot find macro `Self` in this scope
   --> $DIR/self_type_keyword.rs:21:9
    |
 LL |         Self!() => (),
diff --git a/src/test/ui/suggestions/attribute-typos.rs b/src/test/ui/suggestions/attribute-typos.rs
index 74f63f2..7c8231b 100644
--- a/src/test/ui/suggestions/attribute-typos.rs
+++ b/src/test/ui/suggestions/attribute-typos.rs
@@ -1,11 +1,11 @@
-#[deprcated] //~ ERROR cannot find attribute macro `deprcated` in this scope
+#[deprcated] //~ ERROR cannot find attribute `deprcated` in this scope
 fn foo() {}
 
-#[tests] //~ ERROR cannot find attribute macro `tests` in this scope
+#[tests] //~ ERROR cannot find attribute `tests` in this scope
 fn bar() {}
 
 #[rustc_err]
-//~^ ERROR cannot find attribute macro `rustc_err` in this scope
+//~^ ERROR cannot find attribute `rustc_err` in this scope
 //~| ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler
 
 fn main() {}
diff --git a/src/test/ui/suggestions/attribute-typos.stderr b/src/test/ui/suggestions/attribute-typos.stderr
index 6b2f591..e403293 100644
--- a/src/test/ui/suggestions/attribute-typos.stderr
+++ b/src/test/ui/suggestions/attribute-typos.stderr
@@ -7,19 +7,19 @@
    = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
 
-error: cannot find attribute macro `rustc_err` in this scope
+error: cannot find attribute `rustc_err` in this scope
   --> $DIR/attribute-typos.rs:7:3
    |
 LL | #[rustc_err]
    |   ^^^^^^^^^ help: a built-in attribute with a similar name exists: `rustc_error`
 
-error: cannot find attribute macro `tests` in this scope
+error: cannot find attribute `tests` in this scope
   --> $DIR/attribute-typos.rs:4:3
    |
 LL | #[tests]
    |   ^^^^^ help: an attribute macro with a similar name exists: `test`
 
-error: cannot find attribute macro `deprcated` in this scope
+error: cannot find attribute `deprcated` in this scope
   --> $DIR/attribute-typos.rs:1:3
    |
 LL | #[deprcated]
diff --git a/src/test/ui/syntax-extension-minor.rs b/src/test/ui/syntax-extension-minor.rs
index 0206a76..2d6710a 100644
--- a/src/test/ui/syntax-extension-minor.rs
+++ b/src/test/ui/syntax-extension-minor.rs
@@ -1,3 +1,5 @@
+// run-pass
+
 #![feature(concat_idents)]
 
 pub fn main() {
@@ -5,10 +7,8 @@
     let _: concat_idents!(F, oo) = Foo; // Test that `concat_idents!` can be used in type positions
 
     let asdf_fdsa = "<.<".to_string();
-    // this now fails (correctly, I claim) because hygiene prevents
-    // the assembled identifier from being a reference to the binding.
+    // concat_idents should have call-site hygiene.
     assert!(concat_idents!(asd, f_f, dsa) == "<.<".to_string());
-    //~^ ERROR cannot find value `asdf_fdsa` in this scope
 
     assert_eq!(stringify!(use_mention_distinction), "use_mention_distinction");
 }
diff --git a/src/test/ui/syntax-extension-minor.stderr b/src/test/ui/syntax-extension-minor.stderr
deleted file mode 100644
index 2d8056d..0000000
--- a/src/test/ui/syntax-extension-minor.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0425]: cannot find value `asdf_fdsa` in this scope
-  --> $DIR/syntax-extension-minor.rs:10:13
-   |
-LL |     assert!(concat_idents!(asd, f_f, dsa) == "<.<".to_string());
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/tool-attributes/tool-attributes-misplaced-1.rs b/src/test/ui/tool-attributes/tool-attributes-misplaced-1.rs
index c07da43..d5698be 100644
--- a/src/test/ui/tool-attributes/tool-attributes-misplaced-1.rs
+++ b/src/test/ui/tool-attributes/tool-attributes-misplaced-1.rs
@@ -5,13 +5,13 @@
 struct S;
 
 // Interpreted as an unstable custom attribute
-#[rustfmt] //~ ERROR cannot find attribute macro `rustfmt` in this scope
+#[rustfmt] //~ ERROR cannot find attribute `rustfmt` in this scope
 fn check() {}
 
 #[rustfmt::skip] // OK
 fn main() {
     rustfmt; //~ ERROR expected value, found tool module `rustfmt`
-    rustfmt!(); //~ ERROR cannot find macro `rustfmt!` in this scope
+    rustfmt!(); //~ ERROR cannot find macro `rustfmt` in this scope
 
     rustfmt::skip; //~ ERROR expected value, found tool attribute `rustfmt::skip`
 }
diff --git a/src/test/ui/tool-attributes/tool-attributes-misplaced-1.stderr b/src/test/ui/tool-attributes/tool-attributes-misplaced-1.stderr
index 33581a1..6bef793 100644
--- a/src/test/ui/tool-attributes/tool-attributes-misplaced-1.stderr
+++ b/src/test/ui/tool-attributes/tool-attributes-misplaced-1.stderr
@@ -4,13 +4,13 @@
 LL | #[derive(rustfmt)]
    |          ^^^^^^^
 
-error: cannot find attribute macro `rustfmt` in this scope
+error: cannot find attribute `rustfmt` in this scope
   --> $DIR/tool-attributes-misplaced-1.rs:8:3
    |
 LL | #[rustfmt]
    |   ^^^^^^^
 
-error: cannot find macro `rustfmt!` in this scope
+error: cannot find macro `rustfmt` in this scope
   --> $DIR/tool-attributes-misplaced-1.rs:14:5
    |
 LL |     rustfmt!();
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index 9ffa939..eab23f3 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -1,3 +1,9 @@
+//! Build a dist manifest, hash and sign everything.
+//! This gets called by `promote-release`
+//! (https://github.com/rust-lang/rust-central-station/tree/master/promote-release)
+//! via `x.py dist hash-and-sign`; the cmdline arguments are set up
+//! by rustbuild (in `src/bootstrap/dist.rs`).
+
 use toml;
 use serde::Serialize;
 
@@ -270,6 +276,7 @@
     // Do not ask for a passphrase while manually testing
     let mut passphrase = String::new();
     if should_sign {
+        // `x.py` passes the passphrase via stdin.
         t!(io::stdin().read_to_string(&mut passphrase));
     }
 
@@ -362,6 +369,7 @@
         }
     }
 
+    /// Hash all files, compute their signatures, and collect the hashes in `self.digests`.
     fn digest_and_sign(&mut self) {
         for file in t!(self.input.read_dir()).map(|e| t!(e).path()) {
             let filename = file.file_name().unwrap().to_str().unwrap();
@@ -532,19 +540,20 @@
             .as_ref()
             .cloned()
             .map(|version| (version, true))
-            .unwrap_or_default();
+            .unwrap_or_default(); // `is_present` defaults to `false` here.
 
-        // miri needs to build std with xargo, which doesn't allow stable/beta:
-        // <https://github.com/japaric/xargo/pull/204#issuecomment-374888868>
+        // Miri is nightly-only; never ship it for other trains.
         if pkgname == "miri-preview" && self.rust_release != "nightly" {
-            is_present = false; // ignore it
+            is_present = false; // Pretend the component is entirely missing.
         }
 
         let targets = targets.iter().map(|name| {
             if is_present {
+                // The component generally exists, but it might still be missing for this target.
                 let filename = self.filename(pkgname, name);
                 let digest = match self.digests.remove(&filename) {
                     Some(digest) => digest,
+                    // This component does not exist for this target -- skip it.
                     None => return (name.to_string(), Target::unavailable()),
                 };
                 let xz_filename = filename.replace(".tar.gz", ".tar.xz");
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index 467b777..7c51de5 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -253,7 +253,7 @@
     if args.len() == 1 || args[1] == "-h" || args[1] == "--help" {
         let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0);
         println!("{}", opts.usage(&message));
-        println!("");
+        println!();
         panic!()
     }
 
@@ -265,7 +265,7 @@
     if matches.opt_present("h") || matches.opt_present("help") {
         let message = format!("Usage: {} [OPTIONS]  [TESTNAME...]", argv0);
         println!("{}", opts.usage(&message));
-        println!("");
+        println!();
         panic!()
     }
 
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index aff5546..baed27d 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -2593,7 +2593,7 @@
                     "  actual:   {}",
                     codegen_units_to_str(&actual_item.codegen_units)
                 );
-                println!("");
+                println!();
             }
         }
 
@@ -3526,7 +3526,7 @@
                             }
                         }
                     }
-                    println!("");
+                    println!();
                 }
             }
         }
diff --git a/src/tools/miri b/src/tools/miri
index dd94c7c..d881387 160000
--- a/src/tools/miri
+++ b/src/tools/miri
@@ -1 +1 @@
-Subproject commit dd94c7c5a32be2ee0adeeaf9d46f26f14925797c
+Subproject commit d88138723780d11ca2c09560111223dc20b9d5f3
diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py
index 2e2505b..7cf3cc7 100755
--- a/src/tools/publish_toolstate.py
+++ b/src/tools/publish_toolstate.py
@@ -7,6 +7,8 @@
 ## It is set as callback for `src/ci/docker/x86_64-gnu-tools/repo.sh` by the CI scripts
 ## when a new commit lands on `master` (i.e., after it passed all checks on `auto`).
 
+from __future__ import print_function
+
 import sys
 import re
 import os
@@ -20,21 +22,26 @@
     import urllib.request as urllib2
 
 # List of people to ping when the status of a tool or a book changed.
+# These should be collaborators of the rust-lang/rust repository (with at least
+# read privileges on it). CI will fail otherwise.
 MAINTAINERS = {
-    'miri': '@oli-obk @RalfJung @eddyb',
-    'clippy-driver': '@Manishearth @llogiq @mcarton @oli-obk @phansch @flip1995 @yaahc',
-    'rls': '@Xanewok',
-    'rustfmt': '@topecongiro',
-    'book': '@carols10cents @steveklabnik',
-    'nomicon': '@frewsxcv @Gankro',
-    'reference': '@steveklabnik @Havvy @matthewjasper @ehuss',
-    'rust-by-example': '@steveklabnik @marioidival @projektir',
-    'embedded-book': (
-        '@adamgreig @andre-richter @jamesmunns @korken89 '
-        '@ryankurte @thejpster @therealprof'
-    ),
-    'edition-guide': '@ehuss @Centril @steveklabnik',
-    'rustc-guide': '@mark-i-m @spastorino @amanjeev'
+    'miri': {'oli-obk', 'RalfJung', 'eddyb'},
+    'clippy-driver': {
+        'Manishearth', 'llogiq', 'mcarton', 'oli-obk', 'phansch', 'flip1995',
+        'yaahc',
+    },
+    'rls': {'Xanewok'},
+    'rustfmt': {'topecongiro'},
+    'book': {'carols10cents', 'steveklabnik'},
+    'nomicon': {'frewsxcv', 'Gankra'},
+    'reference': {'steveklabnik', 'Havvy', 'matthewjasper', 'ehuss'},
+    'rust-by-example': {'steveklabnik', 'marioidival'},
+    'embedded-book': {
+        'adamgreig', 'andre-richter', 'jamesmunns', 'korken89',
+        'ryankurte', 'thejpster', 'therealprof',
+    },
+    'edition-guide': {'ehuss', 'Centril', 'steveklabnik'},
+    'rustc-guide': {'mark-i-m', 'spastorino', 'amanjeev'},
 }
 
 REPOS = {
@@ -52,6 +59,50 @@
 }
 
 
+def validate_maintainers(repo, github_token):
+    '''Ensure all maintainers are assignable on a GitHub repo'''
+    next_link_re = re.compile(r'<([^>]+)>; rel="next"')
+
+    # Load the list of assignable people in the GitHub repo
+    assignable = []
+    url = 'https://api.github.com/repos/%s/collaborators?per_page=100' % repo
+    while url is not None:
+        response = urllib2.urlopen(urllib2.Request(url, headers={
+            'Authorization': 'token ' + github_token,
+            # Properly load nested teams.
+            'Accept': 'application/vnd.github.hellcat-preview+json',
+        }))
+        assignable.extend(user['login'] for user in json.load(response))
+        # Load the next page if available
+        url = None
+        link_header = response.headers.get('Link')
+        if link_header:
+            matches = next_link_re.match(link_header)
+            if matches is not None:
+                url = matches.group(1)
+
+    errors = False
+    for tool, maintainers in MAINTAINERS.items():
+        for maintainer in maintainers:
+            if maintainer not in assignable:
+                errors = True
+                print(
+                    "error: %s maintainer @%s is not assignable in the %s repo"
+                    % (tool, maintainer, repo),
+                )
+
+    if errors:
+        print()
+        print("  To be assignable, a person needs to be explicitly listed as a")
+        print("  collaborator in the repository settings. The simple way to")
+        print("  fix this is to ask someone with 'admin' privileges on the repo")
+        print("  to add the person or whole team as a collaborator with 'read'")
+        print("  privileges. Those privileges don't grant any extra permissions")
+        print("  so it's safe to apply them.")
+        print()
+        print("The build will fail due to this.")
+        exit(1)
+
 def read_current_status(current_commit, path):
     '''Reads build status of `current_commit` from content of `history/*.tsv`
     '''
@@ -73,13 +124,12 @@
 def issue(
     tool,
     status,
-    maintainers,
+    assignees,
     relevant_pr_number,
     relevant_pr_user,
     pr_reviewer,
 ):
     # Open an issue about the toolstate failure.
-    assignees = [x.strip() for x in maintainers.split('@') if x != '']
     if status == 'test-fail':
         status_description = 'has failing tests'
     else:
@@ -100,7 +150,7 @@
             REPOS.get(tool), relevant_pr_user, pr_reviewer
         )),
         'title': '`{}` no longer builds after {}'.format(tool, relevant_pr_number),
-        'assignees': assignees,
+        'assignees': list(assignees),
         'labels': ['T-compiler', 'I-nominated'],
     })
     print("Creating issue:\n{}".format(request))
@@ -150,22 +200,32 @@
                 old = status[os]
                 new = s.get(tool, old)
                 status[os] = new
-                if new > old: # comparing the strings, but they are ordered appropriately!
+                maintainers = ' '.join('@'+name for name in MAINTAINERS[tool])
+                # comparing the strings, but they are ordered appropriately:
+                # "test-pass" > "test-fail" > "build-fail"
+                if new > old:
                     # things got fixed or at least the status quo improved
                     changed = True
                     message += '🎉 {} on {}: {} → {} (cc {}, @rust-lang/infra).\n' \
-                        .format(tool, os, old, new, MAINTAINERS.get(tool))
+                        .format(tool, os, old, new, maintainers)
                 elif new < old:
                     # tests or builds are failing and were not failing before
                     changed = True
                     title = '💔 {} on {}: {} → {}' \
                         .format(tool, os, old, new)
                     message += '{} (cc {}, @rust-lang/infra).\n' \
-                        .format(title, MAINTAINERS.get(tool))
-                    # Most tools only create issues for build failures.
-                    # Other failures can be spurious.
-                    if new == 'build-fail' or (tool == 'miri' and new == 'test-fail'):
-                        create_issue_for_status = new
+                        .format(title, maintainers)
+                    # See if we need to create an issue.
+                    if tool == 'miri':
+                        # Create issue if tests used to pass before. Don't open a *second*
+                        # issue when we regress from "test-fail" to "build-fail".
+                        if old == 'test-pass':
+                            create_issue_for_status = new
+                    else:
+                        # Create issue if things no longer build.
+                        # (No issue for mere test failures to avoid spurious issues.)
+                        if new == 'build-fail':
+                            create_issue_for_status = new
 
             if create_issue_for_status is not None:
                 try:
@@ -200,6 +260,16 @@
 
 
 if __name__ == '__main__':
+    repo = os.environ.get('TOOLSTATE_VALIDATE_MAINTAINERS_REPO')
+    if repo:
+        github_token = os.environ.get('TOOLSTATE_REPO_ACCESS_TOKEN')
+        if github_token:
+            validate_maintainers(repo, github_token)
+        else:
+            print('skipping toolstate maintainers validation since no GitHub token is present')
+        # When validating maintainers don't run the full script.
+        exit(0)
+
     cur_commit = sys.argv[1]
     cur_datetime = datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')
     cur_commit_msg = sys.argv[2]
diff --git a/src/tools/rls b/src/tools/rls
index 412fb00..d9aa23a 160000
--- a/src/tools/rls
+++ b/src/tools/rls
@@ -1 +1 @@
-Subproject commit 412fb00b37afb6b7f7fa96a35f2315c7e640b916
+Subproject commit d9aa23a43ad29e3a10551a1425ef5d5baef28d70
diff --git a/src/tools/rustc-workspace-hack/Cargo.toml b/src/tools/rustc-workspace-hack/Cargo.toml
index d068e1c..930279c 100644
--- a/src/tools/rustc-workspace-hack/Cargo.toml
+++ b/src/tools/rustc-workspace-hack/Cargo.toml
@@ -62,7 +62,6 @@
 serde = { version = "1.0.82", features = ['derive'] }
 serde_json = { version = "1.0.31", features = ["raw_value"] }
 smallvec = { version = "0.6", features = ['union', 'may_dangle'] }
-byteorder = { version = "1.2.7", features = ["i128"] }
 
 
 [target.'cfg(not(windows))'.dependencies]