Rollup merge of #59190 - greg-kargin:master, r=sanxiyn

consistent naming for Rhs type parameter in libcore/ops

Rename RHS type parameter occurrences RHS->Rhs to make it consistent throughout files and follow naming conventions.
diff --git a/.mailmap b/.mailmap
index 07330862..120d1f1 100644
--- a/.mailmap
+++ b/.mailmap
@@ -29,6 +29,7 @@
 Ariel Ben-Yehuda <arielb1@mail.tau.ac.il> arielb1 <arielb1@mail.tau.ac.il>
 Austin Seipp <mad.one@gmail.com> <as@hacks.yi.org>
 Aydin Kim <ladinjin@hanmail.net> aydin.kim <aydin.kim@samsung.com>
+Bastian Kauschke <bastian_kauschke@hotmail.de>
 Barosl Lee <vcs@barosl.com> Barosl LEE <github@barosl.com>
 Ben Alpert <ben@benalpert.com> <spicyjalapeno@gmail.com>
 Ben Sago <ogham@users.noreply.github.com> Ben S <ogham@bsago.me>
diff --git a/.travis.yml b/.travis.yml
index 7985b6c..7a8772d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -12,20 +12,27 @@
   depth: 2
   submodules: false
 
+env:
+  global:
+    - CI_JOB_NAME=$TRAVIS_JOB_NAME
+
 matrix:
   fast_finish: true
   include:
     # Images used in testing PR and try-build should be run first.
     - env: IMAGE=x86_64-gnu-llvm-6.0 RUST_BACKTRACE=1
+      name: x86_64-gnu-llvm-6.0
       if: type = pull_request OR branch = auto
 
     - env: IMAGE=dist-x86_64-linux DEPLOY=1
+      name: dist-x86_64-linux
       if: branch = try OR branch = auto
 
     # "alternate" deployments, these are "nightlies" but have LLVM assertions
     # turned on, they're deployed to a different location primarily for
     # additional testing.
-    - env: IMAGE=dist-x86_64-linux DEPLOY_ALT=1 CI_JOB_NAME=dist-x86_64-linux-alt
+    - env: IMAGE=dist-x86_64-linux DEPLOY_ALT=1
+      name: dist-x86_64-linux-alt
       if: branch = try OR branch = auto
 
     - env: >
@@ -37,9 +44,9 @@
         MACOSX_DEPLOYMENT_TARGET=10.7
         NO_LLVM_ASSERTIONS=1
         NO_DEBUG_ASSERTIONS=1
-        CI_JOB_NAME=dist-x86_64-apple-alt
       os: osx
       osx_image: xcode9.3-moar
+      name: dist-x86_64-apple-alt
       if: branch = auto
 
     # macOS builders. These are placed near the beginning because they are very
@@ -60,9 +67,9 @@
         MACOSX_STD_DEPLOYMENT_TARGET=10.7
         NO_LLVM_ASSERTIONS=1
         NO_DEBUG_ASSERTIONS=1
-        CI_JOB_NAME=x86_64-apple
       os: osx
       osx_image: xcode9.3-moar
+      name: x86_64-apple
       if: branch = auto
 
     - env: >
@@ -74,9 +81,9 @@
         MACOSX_STD_DEPLOYMENT_TARGET=10.7
         NO_LLVM_ASSERTIONS=1
         NO_DEBUG_ASSERTIONS=1
-        CI_JOB_NAME=i686-apple
       os: osx
       osx_image: xcode9.3-moar
+      name: i686-apple
       if: branch = auto
 
     # OSX builders producing releases. These do not run the full test suite and
@@ -95,9 +102,9 @@
         NO_LLVM_ASSERTIONS=1
         NO_DEBUG_ASSERTIONS=1
         DIST_REQUIRE_ALL_TOOLS=1
-        CI_JOB_NAME=dist-i686-apple
       os: osx
       osx_image: xcode9.3-moar
+      name: dist-i686-apple
       if: branch = auto
 
     - env: >
@@ -110,81 +117,116 @@
         NO_LLVM_ASSERTIONS=1
         NO_DEBUG_ASSERTIONS=1
         DIST_REQUIRE_ALL_TOOLS=1
-        CI_JOB_NAME=dist-x86_64-apple
       os: osx
       osx_image: xcode9.3-moar
+      name: dist-x86_64-apple
       if: branch = auto
 
     # Linux builders, remaining docker images
     - env: IMAGE=arm-android
+      name: arm-android
       if: branch = auto
     - env: IMAGE=armhf-gnu
+      name: armhf-gnu
       if: branch = auto
     - env: IMAGE=dist-various-1 DEPLOY=1
+      name: dist-various-1
       if: branch = auto
     - env: IMAGE=dist-various-2 DEPLOY=1
+      name: dist-various-2
       if: branch = auto
     - env: IMAGE=dist-aarch64-linux DEPLOY=1
+      name: dist-aarch64-linux
       if: branch = auto
     - env: IMAGE=dist-android DEPLOY=1
+      name: dist-android
       if: branch = auto
     - env: IMAGE=dist-arm-linux DEPLOY=1
+      name: dist-arm-linux
       if: branch = auto
     - env: IMAGE=dist-armhf-linux DEPLOY=1
+      name: dist-armhf-linux
       if: branch = auto
     - env: IMAGE=dist-armv7-linux DEPLOY=1
+      name: dist-armv7-linux
       if: branch = auto
     - env: IMAGE=dist-i586-gnu-i586-i686-musl DEPLOY=1
+      name: dist-i586-gnu-i586-i686-musl
       if: branch = auto
     - env: IMAGE=dist-i686-freebsd DEPLOY=1
+      name: dist-i686-freebsd
       if: branch = auto
     - env: IMAGE=dist-i686-linux DEPLOY=1
+      name: dist-i686-linux
       if: branch = auto
     - env: IMAGE=dist-mips-linux DEPLOY=1
+      name: dist-mips-linux
       if: branch = auto
     - env: IMAGE=dist-mips64-linux DEPLOY=1
+      name: dist-mips64-linux
       if: branch = auto
     - env: IMAGE=dist-mips64el-linux DEPLOY=1
+      name: dist-mips64el-linux
       if: branch = auto
     - env: IMAGE=dist-mipsel-linux DEPLOY=1
+      name: dist-mipsel-linux
       if: branch = auto
     - env: IMAGE=dist-powerpc-linux DEPLOY=1
+      name: dist-powerpc-linux
       if: branch = auto
     - env: IMAGE=dist-powerpc64-linux DEPLOY=1
+      name: dist-powerpc64-linux
       if: branch = auto
     - env: IMAGE=dist-powerpc64le-linux DEPLOY=1
+      name: dist-powerpc64le-linux
       if: branch = auto
     - env: IMAGE=dist-s390x-linux DEPLOY=1
+      name: dist-s390x-linux
       if: branch = auto
     - env: IMAGE=dist-x86_64-freebsd DEPLOY=1
+      name: dist-x86_64-freebsd
       if: branch = auto
     - env: IMAGE=dist-x86_64-musl DEPLOY=1
+      name: dist-x86_64-musl
       if: branch = auto
     - env: IMAGE=dist-x86_64-netbsd DEPLOY=1
+      name: dist-x86_64-netbsd
       if: branch = auto
     - env: IMAGE=asmjs
+      name: asmjs
       if: branch = auto
     - env: IMAGE=i686-gnu
+      name: i686-gnu
       if: branch = auto
     - env: IMAGE=i686-gnu-nopt
+      name: i686-gnu-nopt
       if: branch = auto
     - env: IMAGE=test-various
+      name: test-various
       if: branch = auto
     - env: IMAGE=x86_64-gnu
+      name: x86_64-gnu
       if: branch = auto
     - env: IMAGE=x86_64-gnu-full-bootstrap
+      name: x86_64-gnu-full-bootstrap
       if: branch = auto
     - env: IMAGE=x86_64-gnu-aux
+      name: x86_64-gnu-aux
       if: branch = auto
     - env: IMAGE=x86_64-gnu-tools
+      name: x86_64-gnu-tools
       if: branch = auto OR (type = pull_request AND commit_message =~ /(?i:^update.*\b(rls|rustfmt|clippy|miri|cargo)\b)/)
     - env: IMAGE=x86_64-gnu-debug
+      name: x86_64-gnu-debug
       if: branch = auto
     - env: IMAGE=x86_64-gnu-nopt
+      name: x86_64-gnu-nopt
       if: branch = auto
     - env: IMAGE=x86_64-gnu-distcheck
+      name: x86_64-gnu-distcheck
       if: branch = auto
     - env: IMAGE=mingw-check
+      name: mingw-check
       if: type = pull_request OR branch = auto
 
     - stage: publish toolstate
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index e785f03..fa40893 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -15,7 +15,7 @@
 * [Helpful Links and Information](#helpful-links-and-information)
 
 If you have questions, please make a post on [internals.rust-lang.org][internals] or
-hop on [#rust-internals][pound-rust-internals].
+hop on the [Rust Discord server][rust-discord], [Rust Zulip server][rust-zulip] or [#rust-internals][pound-rust-internals].
 
 As a reminder, all contributors are expected to follow our [Code of Conduct][coc].
 
@@ -27,14 +27,17 @@
 
 [pound-rust-internals]: https://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust-internals
 [internals]: https://internals.rust-lang.org
+[rust-discord]: http://discord.gg/rust-lang
+[rust-zulip]: https://rust-lang.zulipchat.com
 [coc]: https://www.rust-lang.org/conduct.html
+[rustc-guide]: https://rust-lang.github.io/rustc-guide/
 [walkthrough]: https://rust-lang.github.io/rustc-guide/walkthrough.html
 
 ## Feature Requests
 [feature-requests]: #feature-requests
 
 To request a change to the way the Rust language works, please head over
-to the [RFCs repository](https://github.com/rust-lang/rfcs) and view the 
+to the [RFCs repository](https://github.com/rust-lang/rfcs) and view the
 [README](https://github.com/rust-lang/rfcs/blob/master/README.md)
 for instructions.
 
@@ -129,28 +132,40 @@
 before every push to make sure you never forget to make this check.
 
 All pull requests are reviewed by another person. We have a bot,
-@rust-highfive, that will automatically assign a random person to review your
+[@rust-highfive][rust-highfive], that will automatically assign a random person to review your
 request.
 
 If you want to request that a specific person reviews your pull request,
-you can add an `r?` to the message. For example, Steve usually reviews
+you can add an `r?` to the message. For example, [Steve][steveklabnik] usually reviews
 documentation changes. So if you were to make a documentation change, add
 
     r? @steveklabnik
 
-to the end of the message, and @rust-highfive will assign @steveklabnik instead
+to the end of the message, and @rust-highfive will assign [@steveklabnik][steveklabnik] instead
 of a random person. This is entirely optional.
 
 After someone has reviewed your pull request, they will leave an annotation
 on the pull request with an `r+`. It will look something like this:
 
-    @bors: r+ 38fe8d2
+    @bors r+
 
-This tells @bors, our lovable integration bot, that your pull request has
-been approved. The PR then enters the [merge queue][merge-queue], where @bors
+This tells [@bors][bors], our lovable integration bot, that your pull request has
+been approved. The PR then enters the [merge queue][merge-queue], where [@bors][bors]
 will run all the tests on every platform we support. If it all works out,
-@bors will merge your code into `master` and close the pull request.
+[@bors][bors] will merge your code into `master` and close the pull request.
 
+Depending on the scale of the change, you may see a slightly different form of `r+`:
+
+    @bors r+ rollup
+
+The additional `rollup` tells [@bors][bors] that this change is eligible for to be
+"rolled up". Changes that are rolled up are tested and merged at the same time, to
+speed the process up. Typically only small changes that are expected not to conflict
+with one another are rolled up.
+
+[rust-highfive]: https://github.com/rust-highfive
+[steveklabnik]: https://github.com/steveklabnik
+[bors]: https://github.com/bors
 [merge-queue]: https://buildbot2.rust-lang.org/homu/queue/rust
 
 Speaking of tests, Rust has a comprehensive test suite. More information about
@@ -190,7 +205,7 @@
 [breaking-tools-built-with-the-compiler]: #breaking-tools-built-with-the-compiler
 
 Rust's build system builds a number of tools that make use of the
-internals of the compiler. This includes 
+internals of the compiler. This includes
 [Clippy](https://github.com/rust-lang/rust-clippy),
 [RLS](https://github.com/rust-lang/rls) and
 [rustfmt](https://github.com/rust-lang/rustfmt). If these tools
@@ -292,18 +307,8 @@
 
 Documentation improvements are very welcome. The source of `doc.rust-lang.org`
 is located in `src/doc` in the tree, and standard API documentation is generated
-from the source code itself.
-
-Documentation pull requests function in the same way as other pull requests,
-though you may see a slightly different form of `r+`:
-
-    @bors: r+ 38fe8d2 rollup
-
-That additional `rollup` tells @bors that this change is eligible for a 'rollup'.
-To save @bors some work, and to get small changes through more quickly, when
-@bors attempts to merge a commit that's rollup-eligible, it will also merge
-the other rollup-eligible patches too, and they'll get tested and merged at
-the same time.
+from the source code itself. Documentation pull requests function in the same way
+as other pull requests.
 
 To find documentation-related issues, sort by the [T-doc label][tdoc].
 
@@ -428,7 +433,8 @@
 * Although out of date, [Tom Lee's great blog article][tlgba] is very helpful
 * [rustaceans.org][ro] is helpful, but mostly dedicated to IRC
 * The [Rust Compiler Testing Docs][rctd]
-* For @bors, [this cheat sheet][cheatsheet] is helpful (Remember to replace `@homu` with `@bors` in the commands that you use.)
+* For [@bors][bors], [this cheat sheet][cheatsheet] is helpful
+(though you'll need to replace `@homu` with `@bors` in any commands)
 * **Google!** ([search only in Rust Documentation][gsearchdocs] to find types, traits, etc. quickly)
 * Don't be afraid to ask! The Rust community is friendly and helpful.
 
diff --git a/Cargo.lock b/Cargo.lock
index 27f7f59..ec1cda9 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -83,7 +83,7 @@
 version = "0.2.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -95,7 +95,7 @@
 dependencies = [
  "backtrace-sys 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -107,7 +107,7 @@
 dependencies = [
  "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
  "compiler_builtins 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-std-workspace-core 1.0.0",
 ]
 
@@ -162,7 +162,7 @@
  "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -259,7 +259,7 @@
  "jobserver 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "libgit2-sys 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -458,7 +458,7 @@
 version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -479,7 +479,7 @@
  "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -499,7 +499,7 @@
  "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -530,7 +530,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -657,7 +657,7 @@
 dependencies = [
  "curl-sys 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -671,7 +671,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "libnghttp2-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -729,7 +729,7 @@
 version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -738,7 +738,7 @@
 version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "redox_users 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -749,7 +749,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "compiler_builtins 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-std-workspace-core 1.0.0",
 ]
 
@@ -858,7 +858,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -873,7 +873,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "miniz-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "miniz_oxide_c_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -915,7 +915,7 @@
 version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -988,7 +988,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "libgit2-sys 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1163,7 +1163,7 @@
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1200,7 +1200,7 @@
 dependencies = [
  "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
  "fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1208,7 +1208,7 @@
 version = "0.1.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1256,7 +1256,7 @@
 
 [[package]]
 name = "libc"
-version = "0.2.46"
+version = "0.2.50"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "rustc-std-workspace-core 1.0.0",
@@ -1269,7 +1269,7 @@
 dependencies = [
  "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
  "curl-sys 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "libssh2-sys 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1282,7 +1282,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1291,7 +1291,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1299,12 +1299,21 @@
 ]
 
 [[package]]
+name = "libtest"
+version = "0.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc_term 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "libz-sys"
 version = "1.0.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1370,7 +1379,7 @@
 dependencies = [
  "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1471,7 +1480,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1480,7 +1489,7 @@
 version = "0.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1503,7 +1512,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1521,7 +1530,7 @@
 dependencies = [
  "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
  "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "miniz_oxide 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1535,7 +1544,7 @@
  "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1560,7 +1569,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1607,7 +1616,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1653,7 +1662,7 @@
 version = "1.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1680,7 +1689,7 @@
  "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1703,7 +1712,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-src 111.1.0+1.1.1a (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1741,7 +1750,7 @@
 dependencies = [
  "compiler_builtins 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1751,21 +1760,12 @@
  "alloc 0.0.0",
  "compiler_builtins 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "unwind 0.0.0",
 ]
 
 [[package]]
 name = "parking_lot"
-version = "0.6.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "lock_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "parking_lot_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "parking_lot"
 version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -1775,21 +1775,10 @@
 
 [[package]]
 name = "parking_lot_core"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "parking_lot_core"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2018,7 +2007,7 @@
 
 [[package]]
 name = "racer"
-version = "2.1.19"
+version = "2.1.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2029,7 +2018,7 @@
  "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-span 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2038,7 +2027,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2049,7 +2038,7 @@
 dependencies = [
  "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -2061,7 +2050,7 @@
 dependencies = [
  "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2077,7 +2066,7 @@
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2099,7 +2088,7 @@
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2124,7 +2113,7 @@
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2143,7 +2132,7 @@
 dependencies = [
  "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -2230,7 +2219,7 @@
 
 [[package]]
 name = "rls"
-version = "1.34.0"
+version = "1.35.0"
 dependencies = [
  "cargo 0.36.0",
  "cargo_metadata 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2250,7 +2239,7 @@
  "lsp-types 0.55.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ordslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "racer 2.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "racer 2.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2263,7 +2252,7 @@
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-workspace-hack 1.0.0",
  "rustc_tools_util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustfmt-nightly 1.0.3",
+ "rustfmt-nightly 1.1.0",
  "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2376,20 +2365,20 @@
 
 [[package]]
 name = "rustc-ap-arena"
-version = "373.0.0"
+version = "407.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rustc-ap-rustc_data_structures 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-ap-graphviz"
-version = "373.0.0"
+version = "407.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "rustc-ap-rustc_cratesio_shim"
-version = "373.0.0"
+version = "407.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2399,16 +2388,18 @@
 
 [[package]]
 name = "rustc-ap-rustc_data_structures"
-version = "373.0.0"
+version = "407.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "jobserver 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-graphviz 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_cratesio_shim 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-graphviz 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_cratesio_shim 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2418,34 +2409,34 @@
 
 [[package]]
 name = "rustc-ap-rustc_errors"
-version = "373.0.0"
+version = "407.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_cratesio_shim 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_data_structures 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax_pos 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_cratesio_shim 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-ap-rustc_target"
-version = "373.0.0"
+version = "407.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_cratesio_shim 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_data_structures 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_cratesio_shim 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-ap-serialize"
-version = "373.0.0"
+version = "407.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2453,30 +2444,30 @@
 
 [[package]]
 name = "rustc-ap-syntax"
-version = "373.0.0"
+version = "407.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_data_structures 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_errors 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_target 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax_pos 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_errors 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_target 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-ap-syntax_pos"
-version = "373.0.0"
+version = "407.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-arena 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_data_structures 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-arena 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2524,7 +2515,7 @@
 dependencies = [
  "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2621,7 +2612,7 @@
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
  "jobserver 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2650,7 +2641,6 @@
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_data_structures 0.0.0",
- "rustc_incremental 0.0.0",
  "rustc_metadata 0.0.0",
  "rustc_mir 0.0.0",
  "rustc_target 0.0.0",
@@ -2959,6 +2949,11 @@
 ]
 
 [[package]]
+name = "rustc_term"
+version = "0.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "rustc_tools_util"
 version = "0.1.1"
 
@@ -3052,7 +3047,7 @@
 
 [[package]]
 name = "rustfmt-nightly"
-version = "1.0.3"
+version = "1.1.0"
 dependencies = [
  "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "bytecount 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3067,9 +3062,9 @@
  "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_target 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax_pos 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_target 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-workspace-hack 1.0.0",
  "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3116,11 +3111,6 @@
 
 [[package]]
 name = "scoped-tls"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "scoped-tls"
 version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
@@ -3218,7 +3208,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "arc-swap 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -3245,7 +3235,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -3266,7 +3256,7 @@
  "core 0.0.0",
  "dlmalloc 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "fortanix-sgx-abi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "panic_abort 0.0.0",
  "panic_unwind 0.0.0",
  "profiler_builtins 0.0.0",
@@ -3417,7 +3407,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "xattr 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -3428,7 +3418,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3447,10 +3437,6 @@
 
 [[package]]
 name = "term"
-version = "0.0.0"
-
-[[package]]
-name = "term"
 version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -3480,7 +3466,7 @@
 version = "1.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -3489,9 +3475,8 @@
 name = "test"
 version = "0.0.0"
 dependencies = [
- "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libtest 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "proc_macro 0.0.0",
- "term 0.0.0",
 ]
 
 [[package]]
@@ -3500,7 +3485,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -3534,7 +3519,7 @@
 version = "0.1.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -3615,7 +3600,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
  "mio-named-pipes 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3647,7 +3632,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
  "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "signal-hook 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3718,7 +3703,7 @@
  "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
  "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3834,7 +3819,7 @@
 dependencies = [
  "compiler_builtins 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -3901,7 +3886,7 @@
 version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -3974,7 +3959,7 @@
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -4109,10 +4094,11 @@
 "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
 "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1"
 "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
-"checksum libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)" = "023a4cd09b2ff695f9734c1934145a315594b7986398496841c7031a5a1bbdbd"
+"checksum libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "aab692d7759f5cd8c859e169db98ae5b52c924add2af5fbbca11d12fefb567c1"
 "checksum libgit2-sys 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)" = "48441cb35dc255da8ae72825689a95368bf510659ae1ad55dc4aa88cb1789bf1"
 "checksum libnghttp2-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d75d7966bda4730b722d1eab8e668df445368a24394bae9fc1e8dc0ab3dbe4f4"
 "checksum libssh2-sys 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "126a1f4078368b163bfdee65fbab072af08a1b374a5551b21e87ade27b1fbf9d"
+"checksum libtest 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a51ac59582b915cdfc426dada72c6d9eba95818a6b481ca340f5c7152166837"
 "checksum libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe"
 "checksum lock_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "949826a5ccf18c1b3a7c3d57692778d21768b79e46eb9dd07bfc4c2160036c54"
 "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
@@ -4156,9 +4142,7 @@
 "checksum ordslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dd20eec3dbe4376829cb7d80ae6ac45e0a766831dca50202ff2d40db46a8a024"
 "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
 "checksum packed_simd 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "25d36de864f7218ec5633572a800109bbe5a1cc8d9d95a967f3daf93ea7e6ddc"
-"checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5"
 "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337"
-"checksum parking_lot_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "06a2b6aae052309c2fd2161ef58f5067bc17bb758377a0de9d4b279d603fdd8a"
 "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9"
 "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
 "checksum pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0fce5d8b5cc33983fc74f78ad552b5522ab41442c4ca91606e4236eb4b5ceefc"
@@ -4185,7 +4169,7 @@
 "checksum quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45"
 "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
 "checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c"
-"checksum racer 2.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "d634483bed41bb116122b84ffe0ef8740345c2ceb2784ce86c33499700eb13a7"
+"checksum racer 2.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "37c88638777cc178684cf648ca0e1dad56646ce105b8593dfe665c436300adc3"
 "checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd"
 "checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c"
 "checksum rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae9d223d52ae411a33cf7e54ec6034ec165df296ccd23533d671a28252b6f66a"
@@ -4211,20 +4195,21 @@
 "checksum rls-data 0.18.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5f80b84551b32e26affaf7f12374913b5061730c0dcd185d9e8fa5a15e36e65c"
 "checksum rls-span 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "33d66f1d6c6ccd5c98029f162544131698f6ebb61d8c697681cac409dcd08805"
 "checksum rls-vfs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "72d56425bd5aa86d9d4372b76f0381d3b4bda9c0220e71956c9fcc929f45c1f1"
-"checksum rustc-ap-arena 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8be999235b541fc8eb54901b66e899a06076709ac5f53d6b2c5c59d29ad54780"
-"checksum rustc-ap-graphviz 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "532b5df15ca1a19a42815e37e521a20a7632b86b36868d1447932f8476f8f789"
-"checksum rustc-ap-rustc_cratesio_shim 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c388afe1ef810013c878bdf9073ab1ae28dc49e9325863b351afb10acf4cc46e"
-"checksum rustc-ap-rustc_data_structures 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63a8f08b9fb6d607afb842ee7206273d09d69c9201bfc1c479a726093251a24e"
-"checksum rustc-ap-rustc_errors 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6dc0df7bf31588ea67e6386f6ad19f6b9a37ba7d5726ecad1cacce22e231bd98"
-"checksum rustc-ap-rustc_target 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8fb4623a6f6c65b928cbe8d9c52b38cf57ba1722677645dc53fb1bdadfd0e127"
-"checksum rustc-ap-serialize 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0c290b148c9e4e08bbcb8a313393e257c1103cedf6a038aefc9f957c8a77c755"
-"checksum rustc-ap-syntax 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "526fdc5bdbaaeae3b2a9ba42e5f5f7f29cda6ce8971b607a2955b1cb4ca339b5"
-"checksum rustc-ap-syntax_pos 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8e4f88a1213562373cee9de5a1d77bbf16dd706030304af041c9733492fcc952"
+"checksum rustc-ap-arena 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5aab2fb5e5becf1c9183f6c63b8714817a3e780a20b4fe6b3920751c98a18225"
+"checksum rustc-ap-graphviz 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0235ff613d4f96176ea56748010b5d8e978605cc47856ba9bb5372f4f38e9c03"
+"checksum rustc-ap-rustc_cratesio_shim 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63e04a90b0dd8597da83633961698c61a2948f50c9d4b9a71e8afafc0ba0f158"
+"checksum rustc-ap-rustc_data_structures 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c03988d65fc5130787df32e8ea91738f78a8ed62b7a5bdd77f10e5cceb531d8e"
+"checksum rustc-ap-rustc_errors 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b33b9dc34f9fa50bf7e6fd14f2f3c1adc69833acf43c10f3e9795bd4d613712"
+"checksum rustc-ap-rustc_target 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e6de75caef2c7acba11994614266d60238653657677934817ab368d169333cba"
+"checksum rustc-ap-serialize 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf09c60aaee892b0fd107544cfe607d8d463e7f33da34aa823566b8fd2b17f53"
+"checksum rustc-ap-syntax 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "69f38cc120ff317678bbda8c4f58c1bbc1de64b615383ab01480482dde5e95a1"
+"checksum rustc-ap-syntax_pos 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "20a0a201141c5c416b1924b079eeefc7b013e34ece0740ce4997f358b3684a7f"
 "checksum rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "82ae957aa1b3055d8e086486723c0ccd3d7b8fa190ae8fa2e35543b6171c810e"
 "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8"
 "checksum rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d98c51d9cbbe810c8b6693236d3412d8cd60513ff27a3e1b6af483dca0af544"
 "checksum rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "526e7b6d2707a5b9bec3927d424ad70fa3cfc68e0ac1b75e46cdbbc95adc5108"
 "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
+"checksum rustc_term 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9c69abe7f181d2ea8d2f7b44a4aa86f4b4a567444bcfcf51ed45ede957fbf064"
 "checksum rustc_tools_util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c5a95edfa0c893236ae4778bb7c4752760e4c0d245e19b5eff33c5aa5eb9dc"
 "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
 "checksum rustfix 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "af7c21531a91512a4a51b490be6ba1c8eff34fdda0dc5bf87dc28d86748aac56"
@@ -4232,7 +4217,6 @@
 "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7"
 "checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267"
 "checksum schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "0e1a231dc10abf6749cfa5d7767f25888d484201accbd919b66ab5413c502d56"
-"checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28"
 "checksum scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
 "checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
 "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
diff --git a/RELEASES.md b/RELEASES.md
index 4cda02c..a49e072 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -110,8 +110,11 @@
   methods instead.
 - The `Error::cause` method has been deprecated in favor of `Error::source` which supports
   downcasting.
+- [Libtest no longer creates a new thread for each test when
+  `--test-threads=1`.  It also runs the tests in deterministic order][56243]
 
 [55982]: https://github.com/rust-lang/rust/pull/55982/
+[56243]: https://github.com/rust-lang/rust/pull/56243
 [56303]: https://github.com/rust-lang/rust/pull/56303/
 [56351]: https://github.com/rust-lang/rust/pull/56351/
 [56362]: https://github.com/rust-lang/rust/pull/56362
diff --git a/appveyor.yml b/appveyor.yml
index d70ad54..ab0a29d 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,4 +1,7 @@
 environment:
+  # This is required for at least an AArch64 compiler in one image, and is also
+  # going to soon be required for compiling LLVM.
+  APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 Preview
 
   # By default schannel checks revocation of certificates unlike some other SSL
   # backends, but we've historically had problems on CI where a revocation
@@ -7,34 +10,34 @@
 
   matrix:
   # 32/64 bit MSVC tests
-  - MSYS_BITS: 64
+  - CI_JOB_NAME: x86_64-msvc
+    MSYS_BITS: 64
     RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler
     SCRIPT: python x.py test
-    CI_JOB_NAME: x86_64-msvc
-  - MSYS_BITS: 32
+  - CI_JOB_NAME: i686-msvc-1
+    MSYS_BITS: 32
     RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc
     SCRIPT: make appveyor-subset-1
-    CI_JOB_NAME: i686-msvc-1
-  - MSYS_BITS: 32
+  - CI_JOB_NAME: i686-msvc-2
+    MSYS_BITS: 32
     RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc
     SCRIPT: make appveyor-subset-2
-    CI_JOB_NAME: i686-msvc-2
 
   # MSVC aux tests
-  - MSYS_BITS: 64
+  - CI_JOB_NAME: x86_64-msvc-aux
+    MSYS_BITS: 64
     RUST_CHECK_TARGET: check-aux EXCLUDE_CARGO=1
     RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc
-    CI_JOB_NAME: x86_64-msvc-aux
-  - MSYS_BITS: 64
+  - CI_JOB_NAME: x86_64-msvc-cargo
+    MSYS_BITS: 64
     SCRIPT: python x.py test src/tools/cargotest src/tools/cargo
     RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc
-    CI_JOB_NAME: x86_64-msvc-cargo
 
   # MSVC tools tests
-  - MSYS_BITS: 64
+  - CI_JOB_NAME: x86_64-msvc-tools
+    MSYS_BITS: 64
     SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstates.json windows
     RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstates.json --enable-test-miri
-    CI_JOB_NAME: x86_64-msvc-tools
 
   # 32/64-bit MinGW builds.
   #
@@ -49,30 +52,31 @@
   # bucket, but they cleraly didn't originate there! The downloads originally
   # came from the mingw-w64 SourceForge download site. Unfortunately
   # SourceForge is notoriously flaky, so we mirror it on our own infrastructure.
-  - MSYS_BITS: 32
+  - CI_JOB_NAME: i686-mingw-1
+    MSYS_BITS: 32
     RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu
     SCRIPT: make appveyor-subset-1
     MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror
     MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z
     MINGW_DIR: mingw32
-    CI_JOB_NAME: i686-mingw-1
-  - MSYS_BITS: 32
+  - CI_JOB_NAME: i686-mingw-2
+    MSYS_BITS: 32
     RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu
     SCRIPT: make appveyor-subset-2
     MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror
     MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z
     MINGW_DIR: mingw32
-    CI_JOB_NAME: i686-mingw-2
-  - MSYS_BITS: 64
+  - CI_JOB_NAME: x86_64-mingw
+    MSYS_BITS: 64
     SCRIPT: python x.py test
     RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu
     MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror
     MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z
     MINGW_DIR: mingw64
-    CI_JOB_NAME: x86_64-mingw
 
   # 32/64 bit MSVC and GNU deployment
-  - RUST_CONFIGURE_ARGS: >
+  - CI_JOB_NAME: dist-x86_64-msvc
+    RUST_CONFIGURE_ARGS: >
       --build=x86_64-pc-windows-msvc
       --target=x86_64-pc-windows-msvc,aarch64-pc-windows-msvc
       --enable-full-tools
@@ -80,9 +84,8 @@
     SCRIPT: python x.py dist
     DIST_REQUIRE_ALL_TOOLS: 1
     DEPLOY: 1
-    CI_JOB_NAME: dist-x86_64-msvc
-    APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 Preview
-  - RUST_CONFIGURE_ARGS: >
+  - CI_JOB_NAME: dist-i686-msvc
+    RUST_CONFIGURE_ARGS: >
       --build=i686-pc-windows-msvc
       --target=i586-pc-windows-msvc
       --enable-full-tools
@@ -90,8 +93,8 @@
     SCRIPT: python x.py dist
     DIST_REQUIRE_ALL_TOOLS: 1
     DEPLOY: 1
-    CI_JOB_NAME: dist-i686-msvc
-  - MSYS_BITS: 32
+  - CI_JOB_NAME: dist-i686-mingw
+    MSYS_BITS: 32
     RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-full-tools
     SCRIPT: python x.py dist
     MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror
@@ -99,8 +102,8 @@
     MINGW_DIR: mingw32
     DIST_REQUIRE_ALL_TOOLS: 1
     DEPLOY: 1
-    CI_JOB_NAME: dist-i686-mingw
-  - MSYS_BITS: 64
+  - CI_JOB_NAME: dist-x86_64-mingw
+    MSYS_BITS: 64
     SCRIPT: python x.py dist
     RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-full-tools
     MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror
@@ -108,14 +111,13 @@
     MINGW_DIR: mingw64
     DIST_REQUIRE_ALL_TOOLS: 1
     DEPLOY: 1
-    CI_JOB_NAME: dist-x86_64-mingw
 
   # "alternate" deployment, see .travis.yml for more info
-  - MSYS_BITS: 64
+  - CI_JOB_NAME: dist-x86_64-msvc-alt
+    MSYS_BITS: 64
     RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler
     SCRIPT: python x.py dist
     DEPLOY_ALT: 1
-    CI_JOB_NAME: dist-x86_64-msvc-alt
 
 matrix:
   fast_finish: true
diff --git a/config.toml.example b/config.toml.example
index 9afbd93..8c1049f 100644
--- a/config.toml.example
+++ b/config.toml.example
@@ -14,10 +14,6 @@
 # =============================================================================
 [llvm]
 
-# Indicates whether rustc will support compilation with LLVM
-# note: rustc does not compile without LLVM at the moment
-#enabled = true
-
 # Indicates whether the LLVM build is a Release or Debug build
 #optimize = true
 
diff --git a/src/bootstrap/bin/rustdoc.rs b/src/bootstrap/bin/rustdoc.rs
index 36beec3..085f243 100644
--- a/src/bootstrap/bin/rustdoc.rs
+++ b/src/bootstrap/bin/rustdoc.rs
@@ -35,7 +35,7 @@
         .arg("--cfg")
         .arg("dox")
         .arg("--sysroot")
-        .arg(sysroot)
+        .arg(&sysroot)
         .env(bootstrap::util::dylib_path_var(),
              env::join_paths(&dylib_path).unwrap());
 
@@ -72,7 +72,13 @@
     }
 
     if verbose > 1 {
-        eprintln!("rustdoc command: {:?}", cmd);
+        eprintln!(
+            "rustdoc command: {:?}={:?} {:?}",
+            bootstrap::util::dylib_path_var(),
+            env::join_paths(&dylib_path).unwrap(),
+            cmd,
+        );
+        eprintln!("sysroot: {:?}", sysroot);
         eprintln!("libdir: {:?}", libdir);
     }
 
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index ffd23e7..f93f3e7 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -374,6 +374,7 @@
                 test::MirOpt,
                 test::Codegen,
                 test::CodegenUnits,
+                test::Assembly,
                 test::Incremental,
                 test::Debuginfo,
                 test::UiFullDeps,
@@ -408,11 +409,11 @@
                 test::RustdocJSStd,
                 test::RustdocJSNotStd,
                 test::RustdocTheme,
+                test::RustdocUi,
                 // Run bootstrap close to the end as it's unlikely to fail
                 test::Bootstrap,
                 // Run run-make last, since these won't pass without make on Windows
                 test::RunMake,
-                test::RustdocUi
             ),
             Kind::Bench => describe!(test::Crate, test::CrateLibrustc),
             Kind::Doc => describe!(
@@ -669,20 +670,19 @@
             .map(|entry| entry.path())
     }
 
-    pub fn rustdoc(&self, host: Interned<String>) -> PathBuf {
-        self.ensure(tool::Rustdoc { host })
+    pub fn rustdoc(&self, compiler: Compiler) -> PathBuf {
+        self.ensure(tool::Rustdoc { compiler })
     }
 
-    pub fn rustdoc_cmd(&self, host: Interned<String>) -> Command {
+    pub fn rustdoc_cmd(&self, compiler: Compiler) -> Command {
         let mut cmd = Command::new(&self.out.join("bootstrap/debug/rustdoc"));
-        let compiler = self.compiler(self.top_stage, host);
         cmd.env("RUSTC_STAGE", compiler.stage.to_string())
             .env("RUSTC_SYSROOT", self.sysroot(compiler))
             // Note that this is *not* the sysroot_libdir because rustdoc must be linked
             // equivalently to rustc.
             .env("RUSTDOC_LIBDIR", self.rustc_libdir(compiler))
             .env("CFG_RELEASE_CHANNEL", &self.config.channel)
-            .env("RUSTDOC_REAL", self.rustdoc(host))
+            .env("RUSTDOC_REAL", self.rustdoc(compiler))
             .env("RUSTDOC_CRATE_VERSION", self.rust_version())
             .env("RUSTC_BOOTSTRAP", "1");
 
@@ -690,7 +690,7 @@
         cmd.env_remove("MAKEFLAGS");
         cmd.env_remove("MFLAGS");
 
-        if let Some(linker) = self.linker(host) {
+        if let Some(linker) = self.linker(compiler.host) {
             cmd.env("RUSTC_TARGET_LINKER", linker);
         }
         cmd
@@ -752,7 +752,7 @@
                 // This is the intended out directory for compiler documentation.
                 my_out = self.compiler_doc_out(target);
             }
-            let rustdoc = self.rustdoc(compiler.host);
+            let rustdoc = self.rustdoc(compiler);
             self.clear_if_dirty(&my_out, &rustdoc);
         } else if cmd != "test" {
             match mode {
@@ -909,7 +909,7 @@
             .env(
                 "RUSTDOC_REAL",
                 if cmd == "doc" || cmd == "rustdoc" || (cmd == "test" && want_rustdoc) {
-                    self.rustdoc(compiler.host)
+                    self.rustdoc(compiler)
                 } else {
                     PathBuf::from("/path/to/nowhere/rustdoc/not/required")
                 },
@@ -996,10 +996,7 @@
         // For other crates, however, we know that we've already got a standard
         // library up and running, so we can use the normal compiler to compile
         // build scripts in that situation.
-        //
-        // If LLVM support is disabled we need to use the snapshot compiler to compile
-        // build scripts, as the new compiler doesn't support executables.
-        if mode == Mode::Std || !self.config.llvm_enabled {
+        if mode == Mode::Std {
             cargo
                 .env("RUSTC_SNAPSHOT", &self.initial_rustc)
                 .env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_snapshot_libdir());
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index d209588..6162c7e 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -64,7 +64,6 @@
     pub backtrace_on_ice: bool,
 
     // llvm codegen options
-    pub llvm_enabled: bool,
     pub llvm_assertions: bool,
     pub llvm_optimize: bool,
     pub llvm_thin_lto: bool,
@@ -244,7 +243,6 @@
 #[derive(Deserialize, Default)]
 #[serde(deny_unknown_fields, rename_all = "kebab-case")]
 struct Llvm {
-    enabled: Option<bool>,
     ccache: Option<StringOrBool>,
     ninja: Option<bool>,
     assertions: Option<bool>,
@@ -360,7 +358,6 @@
 
     pub fn default_opts() -> Config {
         let mut config = Config::default();
-        config.llvm_enabled = true;
         config.llvm_optimize = true;
         config.llvm_version_check = true;
         config.backtrace = true;
@@ -512,7 +509,6 @@
                 Some(StringOrBool::Bool(false)) | None => {}
             }
             set(&mut config.ninja, llvm.ninja);
-            set(&mut config.llvm_enabled, llvm.enabled);
             llvm_assertions = llvm.assertions;
             set(&mut config.llvm_optimize, llvm.optimize);
             set(&mut config.llvm_thin_lto, llvm.thin_lto);
@@ -671,6 +667,11 @@
     pub fn very_verbose(&self) -> bool {
         self.verbose > 1
     }
+
+    pub fn llvm_enabled(&self) -> bool {
+        self.rust_codegen_backends.contains(&INTERNER.intern_str("llvm"))
+        || self.rust_codegen_backends.contains(&INTERNER.intern_str("emscripten"))
+    }
 }
 
 fn set<T>(field: &mut T, val: Option<T>) {
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 2c40dd6..d982330 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -479,7 +479,7 @@
             t!(fs::create_dir_all(image.join("bin")));
             builder.cp_r(&src.join("bin"), &image.join("bin"));
 
-            builder.install(&builder.rustdoc(compiler.host), &image.join("bin"), 0o755);
+            builder.install(&builder.rustdoc(compiler), &image.join("bin"), 0o755);
 
             // Copy runtime DLLs needed by the compiler
             if libdir != "bin" {
@@ -899,7 +899,6 @@
             "src/libstd",
             "src/libunwind",
             "src/libtest",
-            "src/libterm",
             "src/libprofiler_builtins",
             "src/stdsimd",
             "src/libproc_macro",
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index e0ad042..ae32928 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -335,7 +335,7 @@
     let footer = builder.src.join("src/doc/footer.inc");
     let version_info = out.join("version_info.html");
 
-    let mut cmd = builder.rustdoc_cmd(compiler.host);
+    let mut cmd = builder.rustdoc_cmd(compiler);
 
     let out = out.join("book");
 
@@ -415,7 +415,7 @@
             }
 
             let html = out.join(filename).with_extension("html");
-            let rustdoc = builder.rustdoc(compiler.host);
+            let rustdoc = builder.rustdoc(compiler);
             if up_to_date(&path, &html) &&
                up_to_date(&footer, &html) &&
                up_to_date(&favicon, &html) &&
@@ -425,7 +425,7 @@
                 continue
             }
 
-            let mut cmd = builder.rustdoc_cmd(compiler.host);
+            let mut cmd = builder.rustdoc_cmd(compiler);
             cmd.arg("--html-after-content").arg(&footer)
                .arg("--html-before-content").arg(&version_info)
                .arg("--html-in-header").arg(&favicon)
@@ -824,7 +824,7 @@
         builder.ensure(Rustc { stage, target });
 
         // Build rustdoc.
-        builder.ensure(tool::Rustdoc { host: compiler.host });
+        builder.ensure(tool::Rustdoc { compiler: compiler });
 
         // Symlink compiler docs to the output directory of rustdoc documentation.
         let out_dir = builder.stage_out(compiler, Mode::ToolRustc)
@@ -883,7 +883,11 @@
         builder.info(&format!("Documenting error index ({})", target));
         let out = builder.doc_out(target);
         t!(fs::create_dir_all(&out));
-        let mut index = builder.tool_cmd(Tool::ErrorIndex);
+        let compiler = builder.compiler(2, builder.config.build);
+        let mut index = tool::ErrorIndex::command(
+            builder,
+            compiler,
+        );
         index.arg("html");
         index.arg(out.join("error-index.html"));
 
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 9317a40..976b30a 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -241,6 +241,8 @@
     clippy_info: channel::GitInfo,
     miri_info: channel::GitInfo,
     rustfmt_info: channel::GitInfo,
+    in_tree_llvm_info: channel::GitInfo,
+    emscripten_llvm_info: channel::GitInfo,
     local_rebuild: bool,
     fail_fast: bool,
     doc_tests: DocTests,
@@ -363,6 +365,8 @@
         let clippy_info = channel::GitInfo::new(&config, &src.join("src/tools/clippy"));
         let miri_info = channel::GitInfo::new(&config, &src.join("src/tools/miri"));
         let rustfmt_info = channel::GitInfo::new(&config, &src.join("src/tools/rustfmt"));
+        let in_tree_llvm_info = channel::GitInfo::new(&config, &src.join("src/llvm-project"));
+        let emscripten_llvm_info = channel::GitInfo::new(&config, &src.join("src/llvm-emscripten"));
 
         let mut build = Build {
             initial_rustc: config.initial_rustc.clone(),
@@ -386,6 +390,8 @@
             clippy_info,
             miri_info,
             rustfmt_info,
+            in_tree_llvm_info,
+            emscripten_llvm_info,
             cc: HashMap::new(),
             cxx: HashMap::new(),
             ar: HashMap::new(),
diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in
index 1c27cf3..07be27c 100644
--- a/src/bootstrap/mk/Makefile.in
+++ b/src/bootstrap/mk/Makefile.in
@@ -48,7 +48,6 @@
 	$(Q)$(BOOTSTRAP) test $(BOOTSTRAP_ARGS)
 check-aux:
 	$(Q)$(BOOTSTRAP) test \
-		src/test/pretty \
 		src/test/run-pass/pretty \
 		src/test/run-fail/pretty \
 		src/test/run-pass-valgrind/pretty \
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index d78670c..3babbc9 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -18,6 +18,7 @@
 use cmake;
 use cc;
 
+use crate::channel;
 use crate::util::{self, exe};
 use build_helper::up_to_date;
 use crate::builder::{Builder, RunConfig, ShouldRun, Step};
@@ -231,7 +232,26 @@
         }
 
         if let Some(ref suffix) = builder.config.llvm_version_suffix {
-            cfg.define("LLVM_VERSION_SUFFIX", suffix);
+            // Allow version-suffix="" to not define a version suffix at all.
+            if !suffix.is_empty() {
+                cfg.define("LLVM_VERSION_SUFFIX", suffix);
+            }
+        } else {
+            let mut default_suffix = format!(
+                "-rust-{}-{}",
+                channel::CFG_RELEASE_NUM,
+                builder.config.channel,
+            );
+            let llvm_info = if self.emscripten {
+                &builder.emscripten_llvm_info
+            } else {
+                &builder.in_tree_llvm_info
+            };
+            if let Some(sha) = llvm_info.sha_short() {
+                default_suffix.push_str("-");
+                default_suffix.push_str(sha);
+            }
+            cfg.define("LLVM_VERSION_SUFFIX", default_suffix);
         }
 
         if let Some(ref linker) = builder.config.llvm_use_linker {
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index b7323b2..bbe1872 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -177,7 +177,7 @@
             cmd.arg(&builder.initial_cargo)
                 .arg(&out_dir)
                 .env("RUSTC", builder.rustc(compiler))
-                .env("RUSTDOC", builder.rustdoc(compiler.host)),
+                .env("RUSTDOC", builder.rustdoc(compiler)),
         );
     }
 }
@@ -414,7 +414,6 @@
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub struct CompiletestTest {
-    stage: u32,
     host: Interned<String>,
 }
 
@@ -427,16 +426,14 @@
 
     fn make_run(run: RunConfig<'_>) {
         run.builder.ensure(CompiletestTest {
-            stage: run.builder.top_stage,
             host: run.target,
         });
     }
 
     /// Runs `cargo test` for compiletest.
     fn run(self, builder: &Builder<'_>) {
-        let stage = self.stage;
         let host = self.host;
-        let compiler = builder.compiler(stage, host);
+        let compiler = builder.compiler(0, host);
 
         let mut cargo = tool::prepare_tool_cargo(builder,
                                                  compiler,
@@ -563,7 +560,7 @@
                 builder.sysroot_libdir(self.compiler, self.compiler.host),
             )
             .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
-            .env("RUSTDOC_REAL", builder.rustdoc(self.compiler.host))
+            .env("RUSTDOC_REAL", builder.rustdoc(self.compiler))
             .env("RUSTDOC_CRATE_VERSION", builder.rust_version())
             .env("RUSTC_BOOTSTRAP", "1");
         if let Some(linker) = builder.linker(self.compiler.host) {
@@ -897,12 +894,10 @@
     suite: "rustdoc"
 });
 
-test!(Pretty {
+host_test!(Pretty {
     path: "src/test/pretty",
     mode: "pretty",
-    suite: "pretty",
-    default: false,
-    host: true
+    suite: "pretty"
 });
 test!(RunPassPretty {
     path: "src/test/run-pass/pretty",
@@ -938,6 +933,12 @@
     suite: "run-make-fulldeps"
 });
 
+default_test!(Assembly {
+    path: "src/test/assembly",
+    mode: "assembly",
+    suite: "assembly"
+});
+
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 struct Compiletest {
     compiler: Compiler,
@@ -993,11 +994,7 @@
             });
         }
 
-        if suite.ends_with("fulldeps") ||
-            // FIXME: Does pretty need librustc compiled? Note that there are
-            // fulldeps test suites with mode = pretty as well.
-            mode == "pretty"
-        {
+        if suite.ends_with("fulldeps") {
             builder.ensure(compile::Rustc { compiler, target });
         }
 
@@ -1042,7 +1039,7 @@
             || mode == "js-doc-test"
         {
             cmd.arg("--rustdoc-path")
-                .arg(builder.rustdoc(compiler.host));
+                .arg(builder.rustdoc(compiler));
         }
 
         cmd.arg("--src-base")
@@ -1200,7 +1197,7 @@
             cmd.arg("--quiet");
         }
 
-        if builder.config.llvm_enabled {
+        if builder.config.llvm_enabled() {
             let llvm_config = builder.ensure(native::Llvm {
                 target: builder.config.build,
                 emscripten: false,
@@ -1233,12 +1230,6 @@
                 }
             }
         }
-        if suite == "run-make-fulldeps" && !builder.config.llvm_enabled {
-            builder.info(
-                "Ignoring run-make test suite as they generally don't work without LLVM"
-            );
-            return;
-        }
 
         if suite != "run-make-fulldeps" {
             cmd.arg("--cc")
@@ -1470,7 +1461,10 @@
         t!(fs::create_dir_all(&dir));
         let output = dir.join("error-index.md");
 
-        let mut tool = builder.tool_cmd(Tool::ErrorIndex);
+        let mut tool = tool::ErrorIndex::command(
+            builder,
+            builder.compiler(compiler.stage, builder.config.build),
+        );
         tool.arg("markdown")
             .arg(&output)
             .env("CFG_BUILD", &builder.config.build)
@@ -1495,7 +1489,7 @@
     }
 
     builder.info(&format!("doc tests for: {}", markdown.display()));
-    let mut cmd = builder.rustdoc_cmd(compiler.host);
+    let mut cmd = builder.rustdoc_cmd(compiler);
     builder.add_rust_test_threads(&mut cmd);
     cmd.arg("--test");
     cmd.arg(markdown);
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index 9dbcacf..35e0e24 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -251,9 +251,9 @@
     cargo
 }
 
-macro_rules! tool {
+macro_rules! bootstrap_tool {
     ($(
-        $name:ident, $path:expr, $tool_name:expr, $mode:expr
+        $name:ident, $path:expr, $tool_name:expr
         $(,llvm_tools = $llvm:expr)*
         $(,is_external_tool = $external:expr)*
         ;
@@ -267,10 +267,7 @@
 
         impl Tool {
             pub fn get_mode(&self) -> Mode {
-                let mode = match self {
-                    $(Tool::$name => $mode,)+
-                };
-                mode
+                Mode::ToolBootstrap
             }
 
             /// Whether this tool requires LLVM to run
@@ -283,27 +280,15 @@
 
         impl<'a> Builder<'a> {
             pub fn tool_exe(&self, tool: Tool) -> PathBuf {
-                let stage = self.tool_default_stage(tool);
                 match tool {
                     $(Tool::$name =>
                         self.ensure($name {
-                            compiler: self.compiler(stage, self.config.build),
+                            compiler: self.compiler(0, self.config.build),
                             target: self.config.build,
                         }),
                     )+
                 }
             }
-
-            pub fn tool_default_stage(&self, tool: Tool) -> u32 {
-                // Compile the error-index in the same stage as rustdoc to avoid
-                // recompiling rustdoc twice if we can. Otherwise compile
-                // everything else in stage0 as there's no need to rebootstrap
-                // everything.
-                match tool {
-                    Tool::ErrorIndex if self.top_stage >= 2 => self.top_stage,
-                    _ => 0,
-                }
-            }
         }
 
         $(
@@ -322,7 +307,8 @@
 
             fn make_run(run: RunConfig<'_>) {
                 run.builder.ensure($name {
-                    compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build),
+                    // snapshot compiler
+                    compiler: run.builder.compiler(0, run.builder.config.build),
                     target: run.target,
                 });
             }
@@ -332,7 +318,7 @@
                     compiler: self.compiler,
                     target: self.target,
                     tool: $tool_name,
-                    mode: $mode,
+                    mode: Mode::ToolBootstrap,
                     path: $path,
                     is_optional_tool: false,
                     source_type: if false $(|| $external)* {
@@ -348,22 +334,68 @@
     }
 }
 
-tool!(
-    Rustbook, "src/tools/rustbook", "rustbook", Mode::ToolBootstrap;
-    ErrorIndex, "src/tools/error_index_generator", "error_index_generator", Mode::ToolRustc;
-    UnstableBookGen, "src/tools/unstable-book-gen", "unstable-book-gen", Mode::ToolBootstrap;
-    Tidy, "src/tools/tidy", "tidy", Mode::ToolBootstrap;
-    Linkchecker, "src/tools/linkchecker", "linkchecker", Mode::ToolBootstrap;
-    CargoTest, "src/tools/cargotest", "cargotest", Mode::ToolBootstrap;
-    Compiletest, "src/tools/compiletest", "compiletest", Mode::ToolBootstrap, llvm_tools = true;
-    BuildManifest, "src/tools/build-manifest", "build-manifest", Mode::ToolBootstrap;
-    RemoteTestClient, "src/tools/remote-test-client", "remote-test-client", Mode::ToolBootstrap;
-    RustInstaller, "src/tools/rust-installer", "fabricate", Mode::ToolBootstrap,
-        is_external_tool = true;
-    RustdocTheme, "src/tools/rustdoc-themes", "rustdoc-themes", Mode::ToolBootstrap;
+bootstrap_tool!(
+    Rustbook, "src/tools/rustbook", "rustbook";
+    UnstableBookGen, "src/tools/unstable-book-gen", "unstable-book-gen";
+    Tidy, "src/tools/tidy", "tidy";
+    Linkchecker, "src/tools/linkchecker", "linkchecker";
+    CargoTest, "src/tools/cargotest", "cargotest";
+    Compiletest, "src/tools/compiletest", "compiletest", llvm_tools = true;
+    BuildManifest, "src/tools/build-manifest", "build-manifest";
+    RemoteTestClient, "src/tools/remote-test-client", "remote-test-client";
+    RustInstaller, "src/tools/rust-installer", "fabricate", is_external_tool = true;
+    RustdocTheme, "src/tools/rustdoc-themes", "rustdoc-themes";
 );
 
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+pub struct ErrorIndex {
+    pub compiler: Compiler,
+}
+
+impl ErrorIndex {
+    pub fn command(builder: &Builder<'_>, compiler: Compiler) -> Command {
+        let mut cmd = Command::new(builder.ensure(ErrorIndex {
+            compiler
+        }));
+        add_lib_path(
+            vec![PathBuf::from(&builder.sysroot_libdir(compiler, compiler.host))],
+            &mut cmd,
+        );
+        cmd
+    }
+}
+
+impl Step for ErrorIndex {
+    type Output = PathBuf;
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.path("src/tools/error_index_generator")
+    }
+
+    fn make_run(run: RunConfig<'_>) {
+        // Compile the error-index in the same stage as rustdoc to avoid
+        // recompiling rustdoc twice if we can.
+        let stage = if run.builder.top_stage >= 2 { run.builder.top_stage } else { 0 };
+        run.builder.ensure(ErrorIndex {
+            compiler: run.builder.compiler(stage, run.builder.config.build),
+        });
+    }
+
+    fn run(self, builder: &Builder<'_>) -> PathBuf {
+        builder.ensure(ToolBuild {
+            compiler: self.compiler,
+            target: self.compiler.host,
+            tool: "error_index_generator",
+            mode: Mode::ToolRustc,
+            path: "src/tools/error_index_generator",
+            is_optional_tool: false,
+            source_type: SourceType::InTree,
+            extra_features: Vec::new(),
+        }).expect("expected to build -- essential tool")
+    }
+}
+
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
 pub struct RemoteTestServer {
     pub compiler: Compiler,
     pub target: Interned<String>,
@@ -399,7 +431,9 @@
 
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
 pub struct Rustdoc {
-    pub host: Interned<String>,
+    /// This should only ever be 0 or 2.
+    /// We sometimes want to reference the "bootstrap" rustdoc, which is why this option is here.
+    pub compiler: Compiler,
 }
 
 impl Step for Rustdoc {
@@ -413,12 +447,12 @@
 
     fn make_run(run: RunConfig<'_>) {
         run.builder.ensure(Rustdoc {
-            host: run.host,
+            compiler: run.builder.compiler(run.builder.top_stage, run.host),
         });
     }
 
     fn run(self, builder: &Builder<'_>) -> PathBuf {
-        let target_compiler = builder.compiler(builder.top_stage, self.host);
+        let target_compiler = self.compiler;
         if target_compiler.stage == 0 {
             if !target_compiler.is_snapshot(builder) {
                 panic!("rustdoc in stage 0 must be snapshot rustdoc");
@@ -626,7 +660,7 @@
     /// `host`.
     pub fn tool_cmd(&self, tool: Tool) -> Command {
         let mut cmd = Command::new(self.tool_exe(tool));
-        let compiler = self.compiler(self.tool_default_stage(tool), self.config.build);
+        let compiler = self.compiler(0, self.config.build);
         self.prepare_tool_cmd(compiler, tool, &mut cmd);
         cmd
     }
@@ -638,7 +672,7 @@
     fn prepare_tool_cmd(&self, compiler: Compiler, tool: Tool, cmd: &mut Command) {
         let host = &compiler.host;
         let mut lib_paths: Vec<PathBuf> = vec![
-            if compiler.stage == 0 && tool != Tool::ErrorIndex {
+            if compiler.stage == 0 {
                 self.build.rustc_snapshot_libdir()
             } else {
                 PathBuf::from(&self.sysroot_libdir(compiler, compiler.host))
@@ -700,7 +734,7 @@
     }
 
     fn llvm_bin_path(&self) -> Option<PathBuf> {
-        if self.config.llvm_enabled {
+        if self.config.llvm_enabled() {
             let llvm_config = self.ensure(native::Llvm {
                 target: self.config.build,
                 emscripten: false,
diff --git a/src/ci/docker/disabled/dist-x86_64-redox/Dockerfile b/src/ci/docker/disabled/dist-x86_64-redox/Dockerfile
index f4c25f7..11a3acd 100644
--- a/src/ci/docker/disabled/dist-x86_64-redox/Dockerfile
+++ b/src/ci/docker/disabled/dist-x86_64-redox/Dockerfile
@@ -7,8 +7,8 @@
 RUN sh /scripts/crosstool-ng.sh
 
 WORKDIR /tmp
-COPY cross/install-x86_64-redox.sh /tmp/
-RUN ./install-x86_64-redox.sh
+COPY dist-various-1/install-x86_64-redox.sh /scripts/
+RUN sh /scripts/install-x86_64-redox.sh
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
diff --git a/src/ci/docker/dist-powerpc64-linux/build-powerpc64-toolchain.sh b/src/ci/docker/dist-powerpc64-linux/build-powerpc64-toolchain.sh
index f7aa2cd..fc53849 100755
--- a/src/ci/docker/dist-powerpc64-linux/build-powerpc64-toolchain.sh
+++ b/src/ci/docker/dist-powerpc64-linux/build-powerpc64-toolchain.sh
@@ -3,9 +3,29 @@
 
 source shared.sh
 
+BINUTILS=2.32
+TARGET=powerpc64-unknown-linux-gnu
+PREFIX=/x-tools/$TARGET
+SYSROOT=$PREFIX/$TARGET/sysroot
+
 mkdir build
 cd build
 cp ../powerpc64-linux-gnu.config .config
 hide_output ct-ng build
 cd ..
 rm -rf build
+
+chmod -R u+w $PREFIX
+
+# Next, download and build newer binutils.
+mkdir binutils-$TARGET
+pushd binutils-$TARGET
+curl https://ftp.gnu.org/gnu/binutils/binutils-$BINUTILS.tar.bz2 | tar xjf -
+mkdir binutils-build
+cd binutils-build
+hide_output ../binutils-$BINUTILS/configure --target=$TARGET \
+  --prefix=$PREFIX --with-sysroot=$SYSROOT
+hide_output make -j10
+hide_output make install
+popd
+rm -rf binutils-$TARGET
diff --git a/src/ci/docker/dist-powerpc64le-linux/build-powerpc64le-toolchain.sh b/src/ci/docker/dist-powerpc64le-linux/build-powerpc64le-toolchain.sh
index a01803d..f866a24 100755
--- a/src/ci/docker/dist-powerpc64le-linux/build-powerpc64le-toolchain.sh
+++ b/src/ci/docker/dist-powerpc64le-linux/build-powerpc64le-toolchain.sh
@@ -4,7 +4,7 @@
 
 source shared.sh
 
-BINUTILS=2.25.1
+BINUTILS=2.32
 GCC=5.3.0
 TARGET=powerpc64le-linux-gnu
 SYSROOT=/usr/local/$TARGET/sysroot
diff --git a/src/ci/docker/dist-various-1/install-x86_64-redox.sh b/src/ci/docker/dist-various-1/install-x86_64-redox.sh
index c39be14..339042b 100755
--- a/src/ci/docker/dist-various-1/install-x86_64-redox.sh
+++ b/src/ci/docker/dist-various-1/install-x86_64-redox.sh
@@ -3,11 +3,5 @@
 
 set -ex
 
-apt-get update
-apt-get install -y --no-install-recommends software-properties-common apt-transport-https
-
-apt-key adv --batch --yes --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys AA12E97F0881517F
-add-apt-repository -y 'deb https://static.redox-os.org/toolchain/apt /'
-
-apt-get update
-apt-get install -y x86-64-unknown-redox-gcc
+curl https://static.redox-os.org/toolchain/x86_64-unknown-redox/relibc-install.tar.gz | \
+tar --extract --gzip --directory /usr/local
diff --git a/src/ci/docker/dist-x86_64-musl/Dockerfile b/src/ci/docker/dist-x86_64-musl/Dockerfile
index 06f8a2f..560df2f 100644
--- a/src/ci/docker/dist-x86_64-musl/Dockerfile
+++ b/src/ci/docker/dist-x86_64-musl/Dockerfile
@@ -4,6 +4,7 @@
   g++ \
   make \
   file \
+  wget \
   curl \
   ca-certificates \
   python2.7 \
@@ -18,19 +19,17 @@
 
 WORKDIR /build/
 
-COPY scripts/musl.sh /build/
+COPY scripts/musl-toolchain.sh /build/
 # We need to mitigate rust-lang/rust#34978 when compiling musl itself as well
-RUN CC=gcc \
-    CFLAGS="-Wa,-mrelax-relocations=no" \
-    CXX=g++ \
+RUN CFLAGS="-Wa,-mrelax-relocations=no" \
     CXXFLAGS="-Wa,-mrelax-relocations=no" \
-    bash musl.sh x86_64 && rm -rf /build
+    bash musl-toolchain.sh x86_64 && rm -rf build
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
 ENV RUST_CONFIGURE_ARGS \
-      --musl-root-x86_64=/musl-x86_64 \
+      --musl-root-x86_64=/usr/local/x86_64-linux-musl \
       --enable-extended \
       --disable-docs
 
@@ -41,6 +40,12 @@
 # See: https://github.com/rust-lang/rust/issues/34978
 ENV CFLAGS_x86_64_unknown_linux_musl=-Wa,-mrelax-relocations=no
 
-ENV SCRIPT \
-      python2.7 ../x.py test --target x86_64-unknown-linux-musl && \
-      python2.7 ../x.py dist --target x86_64-unknown-linux-musl
+ENV HOSTS=x86_64-unknown-linux-musl \
+    CC_x86_64_unknown_linux_musl=x86_64-linux-musl-gcc \
+    CXX_x86_64_unknown_linux_musl=x86_64-linux-musl-g++
+
+# Musl defaults to static libs but we need them to be dynamic for host toolchain.
+# The toolchain will produce static libs by default.
+ENV RUSTFLAGS="-C target-feature=-crt-static"
+
+ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh
index b4426bb..ef15175 100755
--- a/src/ci/docker/run.sh
+++ b/src/ci/docker/run.sh
@@ -22,7 +22,18 @@
       hash_key=/tmp/.docker-hash-key.txt
       rm -f "${hash_key}"
       echo $image >> $hash_key
-      find $docker_dir -type f | sort | xargs cat >> $hash_key
+
+      cat "$docker_dir/$image/Dockerfile" >> $hash_key
+      # Look for all source files involves in the COPY command
+      copied_files=/tmp/.docker-copied-files.txt
+      rm -f "$copied_files"
+      for i in $(sed -n -e 's/^COPY \(.*\) .*$/\1/p' "$docker_dir/$image/Dockerfile"); do
+        # List the file names
+        find "$docker_dir/$i" -type f >> $copied_files
+      done
+      # Sort the file names and cat the content into the hash key
+      sort $copied_files | xargs cat >> $hash_key
+
       docker --version >> $hash_key
       cksum=$(sha512sum $hash_key | \
         awk '{print $1}')
diff --git a/src/ci/docker/scripts/musl-toolchain.sh b/src/ci/docker/scripts/musl-toolchain.sh
new file mode 100644
index 0000000..95b7c28
--- /dev/null
+++ b/src/ci/docker/scripts/musl-toolchain.sh
@@ -0,0 +1,70 @@
+# This script runs `musl-cross-make` to prepare C toolchain (Binutils, GCC, musl itself)
+# and builds static libunwind that we distribute for static target.
+#
+# Versions of the toolchain components are configurable in `musl-cross-make/Makefile` and
+# musl unlike GLIBC is forward compatible so upgrading it shouldn't break old distributions.
+# Right now we have: Binutils 2.27, GCC 6.3.0, musl 1.1.18
+set -ex
+
+hide_output() {
+  set +x
+  on_err="
+echo ERROR: An error was encountered with the build.
+cat /tmp/build.log
+exit 1
+"
+  trap "$on_err" ERR
+  bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
+  PING_LOOP_PID=$!
+  $@ &> /tmp/build.log
+  trap - ERR
+  kill $PING_LOOP_PID
+  rm /tmp/build.log
+  set -x
+}
+
+ARCH=$1
+TARGET=$ARCH-linux-musl
+
+OUTPUT=/usr/local
+shift
+
+git clone https://github.com/richfelker/musl-cross-make -b v0.9.7
+cd musl-cross-make
+
+hide_output make -j$(nproc) TARGET=$TARGET
+hide_output make install TARGET=$TARGET OUTPUT=$OUTPUT
+
+cd -
+
+# Install musl library to make binaries executable
+ln -s $OUTPUT/$TARGET/lib/libc.so /lib/ld-musl-$ARCH.so.1
+echo $OUTPUT/$TARGET/lib >> /etc/ld-musl-$ARCH.path
+
+
+export CC=$TARGET-gcc
+export CXX=$TARGET-g++
+
+LLVM=70
+
+# may have been downloaded in a previous run
+if [ ! -d libunwind-release_$LLVM ]; then
+  curl -L https://github.com/llvm-mirror/llvm/archive/release_$LLVM.tar.gz | tar xzf -
+  curl -L https://github.com/llvm-mirror/libunwind/archive/release_$LLVM.tar.gz | tar xzf -
+fi
+
+# fixme(mati865): Replace it with https://github.com/rust-lang/rust/pull/59089
+mkdir libunwind-build
+cd libunwind-build
+cmake ../libunwind-release_$LLVM \
+          -DLLVM_PATH=/build/llvm-release_$LLVM \
+          -DLIBUNWIND_ENABLE_SHARED=0 \
+          -DCMAKE_C_COMPILER=$CC \
+          -DCMAKE_CXX_COMPILER=$CXX \
+          -DCMAKE_C_FLAGS="$CFLAGS" \
+          -DCMAKE_CXX_FLAGS="$CXXFLAGS"
+
+hide_output make -j$(nproc)
+cp lib/libunwind.a $OUTPUT/$TARGET/lib
+cd - && rm -rf libunwind-build
+
diff --git a/src/ci/docker/test-various/Dockerfile b/src/ci/docker/test-various/Dockerfile
index 6c419e1..611a24a 100644
--- a/src/ci/docker/test-various/Dockerfile
+++ b/src/ci/docker/test-various/Dockerfile
@@ -11,7 +11,9 @@
   cmake \
   sudo \
   gdb \
-  xz-utils
+  xz-utils \
+  wget \
+  patch
 
 # FIXME: build the `ptx-linker` instead.
 RUN curl -sL https://github.com/denzp/rust-ptx-linker/releases/download/v0.9.0-alpha.2/rust-ptx-linker.linux64.tar.gz | \
@@ -20,10 +22,16 @@
 RUN curl -sL https://nodejs.org/dist/v9.2.0/node-v9.2.0-linux-x64.tar.xz | \
   tar -xJ
 
+WORKDIR /build/
+COPY scripts/musl-toolchain.sh /build/
+RUN bash musl-toolchain.sh x86_64 && rm -rf build
+WORKDIR /
+
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
 ENV RUST_CONFIGURE_ARGS \
+  --musl-root-x86_64=/usr/local/x86_64-linux-musl \
   --set build.nodejs=/node-v9.2.0-linux-x64/bin/node \
   --set rust.lld
 
@@ -45,6 +53,12 @@
 
 ENV NVPTX_TARGETS=nvptx64-nvidia-cuda
 ENV NVPTX_SCRIPT python2.7 /checkout/x.py test --target $NVPTX_TARGETS \
-  src/test/run-make
+  src/test/run-make \
+  src/test/assembly
 
-ENV SCRIPT $WASM_SCRIPT && $NVPTX_SCRIPT
+ENV MUSL_TARGETS=x86_64-unknown-linux-musl \
+    CC_x86_64_unknown_linux_musl=x86_64-linux-musl-gcc \
+    CXX_x86_64_unknown_linux_musl=x86_64-linux-musl-g++
+ENV MUSL_SCRIPT python2.7 /checkout/x.py test --target $MUSL_TARGETS
+
+ENV SCRIPT $WASM_SCRIPT && $NVPTX_SCRIPT && $MUSL_SCRIPT
diff --git a/src/ci/docker/x86_64-gnu-tools/checktools.sh b/src/ci/docker/x86_64-gnu-tools/checktools.sh
index 3343716..97e6ee2 100755
--- a/src/ci/docker/x86_64-gnu-tools/checktools.sh
+++ b/src/ci/docker/x86_64-gnu-tools/checktools.sh
@@ -78,6 +78,7 @@
     check_dispatch $1 beta clippy-driver src/tools/clippy
     # these tools are not required for beta to successfully branch
     check_dispatch $1 nightly miri src/tools/miri
+    check_dispatch $1 nightly embedded-book src/doc/embedded-book
 }
 
 # If this PR is intended to update one of these tools, do not let the build pass
diff --git a/src/liballoc/prelude.rs b/src/liballoc/prelude.rs
deleted file mode 100644
index 6767cf8..0000000
--- a/src/liballoc/prelude.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-//! The alloc Prelude
-//!
-//! The purpose of this module is to alleviate imports of commonly-used
-//! items of the `alloc` crate by adding a glob import to the top of modules:
-//!
-//! ```
-//! # #![allow(unused_imports)]
-//! # #![feature(alloc)]
-//! extern crate alloc;
-//! use alloc::prelude::*;
-//! ```
-
-#![unstable(feature = "alloc", issue = "27783")]
-
-#[unstable(feature = "alloc", issue = "27783")] pub use crate::borrow::ToOwned;
-#[unstable(feature = "alloc", issue = "27783")] pub use crate::boxed::Box;
-#[unstable(feature = "alloc", issue = "27783")] pub use crate::slice::SliceConcatExt;
-#[unstable(feature = "alloc", issue = "27783")] pub use crate::string::{String, ToString};
-#[unstable(feature = "alloc", issue = "27783")] pub use crate::vec::Vec;
diff --git a/src/liballoc/prelude/mod.rs b/src/liballoc/prelude/mod.rs
new file mode 100644
index 0000000..33cc51d
--- /dev/null
+++ b/src/liballoc/prelude/mod.rs
@@ -0,0 +1,16 @@
+//! The alloc Prelude
+//!
+//! The purpose of this module is to alleviate imports of commonly-used
+//! items of the `alloc` crate by adding a glob import to the top of modules:
+//!
+//! ```
+//! # #![allow(unused_imports)]
+//! # #![feature(alloc)]
+//! #![feature(alloc_prelude)]
+//! extern crate alloc;
+//! use alloc::prelude::v1::*;
+//! ```
+
+#![unstable(feature = "alloc_prelude", issue = "58935")]
+
+pub mod v1;
diff --git a/src/liballoc/prelude/v1.rs b/src/liballoc/prelude/v1.rs
new file mode 100644
index 0000000..b6b0139
--- /dev/null
+++ b/src/liballoc/prelude/v1.rs
@@ -0,0 +1,11 @@
+//! The first version of the prelude of `alloc` crate.
+//!
+//! See the [module-level documentation](../index.html) for more.
+
+#![unstable(feature = "alloc_prelude", issue = "58935")]
+
+#[unstable(feature = "alloc_prelude", issue = "58935")] pub use crate::borrow::ToOwned;
+#[unstable(feature = "alloc_prelude", issue = "58935")] pub use crate::boxed::Box;
+#[unstable(feature = "alloc_prelude", issue = "58935")] pub use crate::slice::SliceConcatExt;
+#[unstable(feature = "alloc_prelude", issue = "58935")] pub use crate::string::{String, ToString};
+#[unstable(feature = "alloc_prelude", issue = "58935")] pub use crate::vec::Vec;
diff --git a/src/liballoc/tests/binary_heap.rs b/src/liballoc/tests/binary_heap.rs
index 1d4a3ed..0930f8d 100644
--- a/src/liballoc/tests/binary_heap.rs
+++ b/src/liballoc/tests/binary_heap.rs
@@ -282,7 +282,7 @@
 //
 // Destructors must be called exactly once per element.
 #[test]
-#[cfg(not(miri))] // Miri does not support panics
+#[cfg(not(miri))] // Miri does not support panics nor entropy
 fn panic_safe() {
     static DROP_COUNTER: AtomicUsize = AtomicUsize::new(0);
 
diff --git a/src/liballoc/tests/btree/map.rs b/src/liballoc/tests/btree/map.rs
index f147500..844afe8 100644
--- a/src/liballoc/tests/btree/map.rs
+++ b/src/liballoc/tests/btree/map.rs
@@ -226,7 +226,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_range_equal_excluded() {
     let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
     map.range((Excluded(2), Excluded(2)));
@@ -234,7 +233,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_range_backwards_1() {
     let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
     map.range((Included(3), Included(2)));
@@ -242,7 +240,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_range_backwards_2() {
     let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
     map.range((Included(3), Excluded(2)));
@@ -250,7 +247,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_range_backwards_3() {
     let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
     map.range((Excluded(3), Included(2)));
@@ -258,7 +254,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_range_backwards_4() {
     let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
     map.range((Excluded(3), Excluded(2)));
diff --git a/src/liballoc/tests/slice.rs b/src/liballoc/tests/slice.rs
index feba46b..b54c128 100644
--- a/src/liballoc/tests/slice.rs
+++ b/src/liballoc/tests/slice.rs
@@ -258,7 +258,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_swap_remove_fail() {
     let mut v = vec![1];
     let _ = v.swap_remove(0);
@@ -632,7 +631,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_insert_oob() {
     let mut a = vec![1, 2, 3];
     a.insert(4, 5);
@@ -657,7 +655,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_remove_fail() {
     let mut a = vec![1];
     let _ = a.remove(0);
@@ -939,7 +936,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_windowsator_0() {
     let v = &[1, 2, 3, 4];
     let _it = v.windows(0);
@@ -964,7 +960,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_chunksator_0() {
     let v = &[1, 2, 3, 4];
     let _it = v.chunks(0);
@@ -989,7 +984,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_chunks_exactator_0() {
     let v = &[1, 2, 3, 4];
     let _it = v.chunks_exact(0);
@@ -1014,7 +1008,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_rchunksator_0() {
     let v = &[1, 2, 3, 4];
     let _it = v.rchunks(0);
@@ -1039,7 +1032,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_rchunks_exactator_0() {
     let v = &[1, 2, 3, 4];
     let _it = v.rchunks_exact(0);
@@ -1092,7 +1084,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_overflow_does_not_cause_segfault() {
     let mut v = vec![];
     v.reserve_exact(!0);
@@ -1102,7 +1093,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_overflow_does_not_cause_segfault_managed() {
     let mut v = vec![Rc::new(1)];
     v.reserve_exact(!0);
@@ -1278,7 +1268,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_mut_chunks_0() {
     let mut v = [1, 2, 3, 4];
     let _it = v.chunks_mut(0);
@@ -1311,7 +1300,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_mut_chunks_exact_0() {
     let mut v = [1, 2, 3, 4];
     let _it = v.chunks_exact_mut(0);
@@ -1344,7 +1332,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_mut_rchunks_0() {
     let mut v = [1, 2, 3, 4];
     let _it = v.rchunks_mut(0);
@@ -1377,7 +1364,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_mut_rchunks_exact_0() {
     let mut v = [1, 2, 3, 4];
     let _it = v.rchunks_exact_mut(0);
@@ -1411,7 +1397,7 @@
 #[test]
 #[allow(unused_must_use)] // here, we care about the side effects of `.clone()`
 #[cfg_attr(target_os = "emscripten", ignore)]
-#[cfg(not(miri))] // Miri does not support panics
+#[cfg(not(miri))] // Miri does not support threads nor entropy
 fn test_box_slice_clone_panics() {
     use std::sync::Arc;
     use std::sync::atomic::{AtomicUsize, Ordering};
@@ -1476,7 +1462,6 @@
 
 #[test]
 #[should_panic(expected = "destination and source slices have different lengths")]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_copy_from_slice_dst_longer() {
     let src = [0, 1, 2, 3];
     let mut dst = [0; 5];
@@ -1485,7 +1470,6 @@
 
 #[test]
 #[should_panic(expected = "destination and source slices have different lengths")]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_copy_from_slice_dst_shorter() {
     let src = [0, 1, 2, 3];
     let mut dst = [0; 3];
@@ -1605,7 +1589,7 @@
 
 #[test]
 #[cfg_attr(target_os = "emscripten", ignore)] // no threads
-#[cfg(not(miri))] // Miri does not support panics
+#[cfg(not(miri))] // Miri does not support threads nor entropy
 fn panic_safe() {
     let prev = panic::take_hook();
     panic::set_hook(Box::new(move |info| {
diff --git a/src/liballoc/tests/str.rs b/src/liballoc/tests/str.rs
index b33a564..b197516 100644
--- a/src/liballoc/tests/str.rs
+++ b/src/liballoc/tests/str.rs
@@ -7,7 +7,7 @@
     assert!("" <= "");
     assert!("" <= "foo");
     assert!("foo" <= "foo");
-    assert!("foo" != "bar");
+    assert_ne!("foo", "bar");
 }
 
 #[test]
@@ -351,7 +351,6 @@
     //  to be used in `should_panic`)
     #[test]
     #[should_panic(expected = "out of bounds")]
-    #[cfg(not(miri))] // Miri does not support panics
     fn assert_range_eq_can_fail_by_panic() {
         assert_range_eq!("abc", 0..5, "abc");
     }
@@ -361,7 +360,6 @@
     //  to be used in `should_panic`)
     #[test]
     #[should_panic(expected = "==")]
-    #[cfg(not(miri))] // Miri does not support panics
     fn assert_range_eq_can_fail_by_inequality() {
         assert_range_eq!("abc", 0..2, "abc");
     }
@@ -409,7 +407,6 @@
 
                 #[test]
                 #[should_panic(expected = $expect_msg)]
-                #[cfg(not(miri))] // Miri does not support panics
                 fn index_fail() {
                     let v: String = $data.into();
                     let v: &str = &v;
@@ -418,7 +415,6 @@
 
                 #[test]
                 #[should_panic(expected = $expect_msg)]
-                #[cfg(not(miri))] // Miri does not support panics
                 fn index_mut_fail() {
                     let mut v: String = $data.into();
                     let v: &mut str = &mut v;
@@ -514,7 +510,6 @@
 
     #[test]
     #[should_panic]
-    #[cfg(not(miri))] // Miri does not support panics
     fn test_slice_fail() {
         &"中华Việt Nam"[0..2];
     }
@@ -666,14 +661,12 @@
     // check the panic includes the prefix of the sliced string
     #[test]
     #[should_panic(expected="byte index 1024 is out of bounds of `Lorem ipsum dolor sit amet")]
-    #[cfg(not(miri))] // Miri does not support panics
     fn test_slice_fail_truncated_1() {
         &LOREM_PARAGRAPH[..1024];
     }
     // check the truncation in the panic message
     #[test]
     #[should_panic(expected="luctus, im`[...]")]
-    #[cfg(not(miri))] // Miri does not support panics
     fn test_slice_fail_truncated_2() {
         &LOREM_PARAGRAPH[..1024];
     }
@@ -688,7 +681,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_str_slice_rangetoinclusive_notok() {
     let s = "abcαβγ";
     &s[..=3];
@@ -704,7 +696,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_str_slicemut_rangetoinclusive_notok() {
     let mut s = "abcαβγ".to_owned();
     let s: &mut str = &mut s;
@@ -894,7 +885,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_as_bytes_fail() {
     // Don't double free. (I'm not sure if this exercises the
     // original problem code path anymore.)
@@ -984,7 +974,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_split_at_boundscheck() {
     let s = "ศไทย中华Việt Nam";
     s.split_at(1);
diff --git a/src/liballoc/tests/string.rs b/src/liballoc/tests/string.rs
index 7e93d84..7e75b8c 100644
--- a/src/liballoc/tests/string.rs
+++ b/src/liballoc/tests/string.rs
@@ -231,7 +231,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_split_off_past_end() {
     let orig = "Hello, world!";
     let mut split = String::from(orig);
@@ -240,7 +239,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_split_off_mid_char() {
     let mut orig = String::from("山");
     orig.split_off(1);
@@ -289,7 +287,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_str_truncate_split_codepoint() {
     let mut s = String::from("\u{FC}"); // ü
     s.truncate(1);
@@ -324,7 +321,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn remove_bad() {
     "ศ".to_string().remove(1);
 }
@@ -360,13 +356,11 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn insert_bad1() {
     "".to_string().insert(1, 't');
 }
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn insert_bad2() {
     "ệ".to_string().insert(1, 't');
 }
@@ -447,7 +441,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_replace_range_char_boundary() {
     let mut s = "Hello, 世界!".to_owned();
     s.replace_range(..8, "");
@@ -464,7 +457,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_replace_range_out_of_bounds() {
     let mut s = String::from("12345");
     s.replace_range(5..6, "789");
@@ -472,7 +464,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_replace_range_inclusive_out_of_bounds() {
     let mut s = String::from("12345");
     s.replace_range(5..=5, "789");
diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs
index 6e4ca1d..545332b 100644
--- a/src/liballoc/tests/vec.rs
+++ b/src/liballoc/tests/vec.rs
@@ -368,7 +368,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_vec_truncate_fail() {
     struct BadElem(i32);
     impl Drop for BadElem {
@@ -392,7 +391,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_index_out_of_bounds() {
     let vec = vec![1, 2, 3];
     let _ = vec[3];
@@ -400,7 +398,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_slice_out_of_bounds_1() {
     let x = vec![1, 2, 3, 4, 5];
     &x[!0..];
@@ -408,7 +405,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_slice_out_of_bounds_2() {
     let x = vec![1, 2, 3, 4, 5];
     &x[..6];
@@ -416,7 +412,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_slice_out_of_bounds_3() {
     let x = vec![1, 2, 3, 4, 5];
     &x[!0..4];
@@ -424,7 +419,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_slice_out_of_bounds_4() {
     let x = vec![1, 2, 3, 4, 5];
     &x[1..6];
@@ -432,7 +426,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_slice_out_of_bounds_5() {
     let x = vec![1, 2, 3, 4, 5];
     &x[3..2];
@@ -440,7 +433,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_swap_remove_empty() {
     let mut vec = Vec::<i32>::new();
     vec.swap_remove(0);
@@ -511,7 +503,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_drain_out_of_bounds() {
     let mut v = vec![1, 2, 3, 4, 5];
     v.drain(5..6);
@@ -585,7 +576,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_drain_inclusive_out_of_bounds() {
     let mut v = vec![1, 2, 3, 4, 5];
     v.drain(5..=5);
@@ -615,7 +605,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_splice_out_of_bounds() {
     let mut v = vec![1, 2, 3, 4, 5];
     let a = [10, 11, 12];
@@ -624,7 +613,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_splice_inclusive_out_of_bounds() {
     let mut v = vec![1, 2, 3, 4, 5];
     let a = [10, 11, 12];
diff --git a/src/liballoc/tests/vec_deque.rs b/src/liballoc/tests/vec_deque.rs
index 16ddc14..e0fe10a 100644
--- a/src/liballoc/tests/vec_deque.rs
+++ b/src/liballoc/tests/vec_deque.rs
@@ -108,7 +108,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_index_out_of_bounds() {
     let mut deq = VecDeque::new();
     for i in 1..4 {
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index 8383d30..753f10e 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -1186,7 +1186,6 @@
     /// # Examples
     ///
     /// ```
-    /// #![feature(refcell_map_split)]
     /// use std::cell::{Ref, RefCell};
     ///
     /// let cell = RefCell::new([1, 2, 3, 4]);
@@ -1195,7 +1194,7 @@
     /// assert_eq!(*begin, [1, 2]);
     /// assert_eq!(*end, [3, 4]);
     /// ```
-    #[unstable(feature = "refcell_map_split", issue = "51476")]
+    #[stable(feature = "refcell_map_split", since = "1.35.0")]
     #[inline]
     pub fn map_split<U: ?Sized, V: ?Sized, F>(orig: Ref<'b, T>, f: F) -> (Ref<'b, U>, Ref<'b, V>)
         where F: FnOnce(&T) -> (&U, &V)
@@ -1268,7 +1267,6 @@
     /// # Examples
     ///
     /// ```
-    /// #![feature(refcell_map_split)]
     /// use std::cell::{RefCell, RefMut};
     ///
     /// let cell = RefCell::new([1, 2, 3, 4]);
@@ -1279,7 +1277,7 @@
     /// begin.copy_from_slice(&[4, 3]);
     /// end.copy_from_slice(&[2, 1]);
     /// ```
-    #[unstable(feature = "refcell_map_split", issue = "51476")]
+    #[stable(feature = "refcell_map_split", since = "1.35.0")]
     #[inline]
     pub fn map_split<U: ?Sized, V: ?Sized, F>(
         orig: RefMut<'b, T>, f: F
diff --git a/src/libcore/char/mod.rs b/src/libcore/char/mod.rs
index f3369c4..66839766 100644
--- a/src/libcore/char/mod.rs
+++ b/src/libcore/char/mod.rs
@@ -389,11 +389,17 @@
     fn next(&mut self) -> Option<char> {
         self.0.next()
     }
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.0.size_hint()
+    }
 }
 
 #[stable(feature = "fused", since = "1.26.0")]
 impl FusedIterator for ToLowercase {}
 
+#[stable(feature = "exact_size_case_mapping_iter", since = "1.35.0")]
+impl ExactSizeIterator for ToLowercase {}
+
 /// Returns an iterator that yields the uppercase equivalent of a `char`.
 ///
 /// This `struct` is created by the [`to_uppercase`] method on [`char`]. See
@@ -411,11 +417,17 @@
     fn next(&mut self) -> Option<char> {
         self.0.next()
     }
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.0.size_hint()
+    }
 }
 
 #[stable(feature = "fused", since = "1.26.0")]
 impl FusedIterator for ToUppercase {}
 
+#[stable(feature = "exact_size_case_mapping_iter", since = "1.35.0")]
+impl ExactSizeIterator for ToUppercase {}
+
 #[derive(Debug, Clone)]
 enum CaseMappingIter {
     Three(char, char, char),
@@ -457,6 +469,16 @@
             CaseMappingIter::Zero => None,
         }
     }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let size = match self {
+            CaseMappingIter::Three(..) => 3,
+            CaseMappingIter::Two(..) => 2,
+            CaseMappingIter::One(_) => 1,
+            CaseMappingIter::Zero => 0,
+        };
+        (size, Some(size))
+    }
 }
 
 impl fmt::Display for CaseMappingIter {
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index 94bed37..ea52b0e 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -72,7 +72,7 @@
 /// }
 ///
 /// impl PartialEq for Book {
-///     fn eq(&self, other: &Book) -> bool {
+///     fn eq(&self, other: &Self) -> bool {
 ///         self.isbn == other.isbn
 ///     }
 /// }
@@ -233,7 +233,7 @@
 ///     format: BookFormat,
 /// }
 /// impl PartialEq for Book {
-///     fn eq(&self, other: &Book) -> bool {
+///     fn eq(&self, other: &Self) -> bool {
 ///         self.isbn == other.isbn
 ///     }
 /// }
@@ -493,19 +493,19 @@
 /// }
 ///
 /// impl Ord for Person {
-///     fn cmp(&self, other: &Person) -> Ordering {
+///     fn cmp(&self, other: &Self) -> Ordering {
 ///         self.height.cmp(&other.height)
 ///     }
 /// }
 ///
 /// impl PartialOrd for Person {
-///     fn partial_cmp(&self, other: &Person) -> Option<Ordering> {
+///     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
 ///         Some(self.cmp(other))
 ///     }
 /// }
 ///
 /// impl PartialEq for Person {
-///     fn eq(&self, other: &Person) -> bool {
+///     fn eq(&self, other: &Self) -> bool {
 ///         self.height == other.height
 ///     }
 /// }
@@ -567,6 +567,32 @@
     where Self: Sized {
         if self <= other { self } else { other }
     }
+
+    /// Returns max if self is greater than max, and min if self is less than min.
+    /// Otherwise this will return self.  Panics if min > max.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(clamp)]
+    ///
+    /// assert!((-3).clamp(-2, 1) == -2);
+    /// assert!(0.clamp(-2, 1) == 0);
+    /// assert!(2.clamp(-2, 1) == 1);
+    /// ```
+    #[unstable(feature = "clamp", issue = "44095")]
+    fn clamp(self, min: Self, max: Self) -> Self
+    where Self: Sized {
+        assert!(min <= max);
+        if self < min {
+            min
+        }
+        else if self > max {
+            max
+        } else {
+            self
+        }
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -665,13 +691,13 @@
 /// }
 ///
 /// impl PartialOrd for Person {
-///     fn partial_cmp(&self, other: &Person) -> Option<Ordering> {
+///     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
 ///         self.height.partial_cmp(&other.height)
 ///     }
 /// }
 ///
 /// impl PartialEq for Person {
-///     fn eq(&self, other: &Person) -> bool {
+///     fn eq(&self, other: &Self) -> bool {
 ///         self.height == other.height
 ///     }
 /// }
diff --git a/src/libcore/ffi.rs b/src/libcore/ffi.rs
index d88793f..5cc9c25 100644
--- a/src/libcore/ffi.rs
+++ b/src/libcore/ffi.rs
@@ -79,9 +79,9 @@
                      all supported platforms",
            issue = "44930")]
 struct VaListImpl {
-    stack: *mut (),
-    gr_top: *mut (),
-    vr_top: *mut (),
+    stack: *mut c_void,
+    gr_top: *mut c_void,
+    vr_top: *mut c_void,
     gr_offs: i32,
     vr_offs: i32,
 }
@@ -98,8 +98,8 @@
     gpr: u8,
     fpr: u8,
     reserved: u16,
-    overflow_arg_area: *mut (),
-    reg_save_area: *mut (),
+    overflow_arg_area: *mut c_void,
+    reg_save_area: *mut c_void,
 }
 
 /// x86_64 ABI implementation of a `va_list`.
@@ -113,8 +113,8 @@
 struct VaListImpl {
     gp_offset: i32,
     fp_offset: i32,
-    overflow_arg_area: *mut (),
-    reg_save_area: *mut (),
+    overflow_arg_area: *mut c_void,
+    reg_save_area: *mut c_void,
 }
 
 /// A wrapper for a `va_list`
diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs
index d4ad22c..cccd51b 100644
--- a/src/libcore/iter/adapters/mod.rs
+++ b/src/libcore/iter/adapters/mod.rs
@@ -1198,7 +1198,7 @@
     }
 }
 
-/// An iterator that rejects elements while `predicate` is true.
+/// An iterator that rejects elements while `predicate` returns `true`.
 ///
 /// This `struct` is created by the [`skip_while`] method on [`Iterator`]. See its
 /// documentation for more.
@@ -1286,7 +1286,7 @@
 impl<I, P> FusedIterator for SkipWhile<I, P>
     where I: FusedIterator, P: FnMut(&I::Item) -> bool {}
 
-/// An iterator that only accepts elements while `predicate` is true.
+/// An iterator that only accepts elements while `predicate` returns `true`.
 ///
 /// This `struct` is created by the [`take_while`] method on [`Iterator`]. See its
 /// documentation for more.
diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs
index 5dcca7e..e6a616b 100644
--- a/src/libcore/iter/mod.rs
+++ b/src/libcore/iter/mod.rs
@@ -101,7 +101,7 @@
 //!     type Item = usize;
 //!
 //!     // next() is the only required method
-//!     fn next(&mut self) -> Option<usize> {
+//!     fn next(&mut self) -> Option<Self::Item> {
 //!         // Increment our count. This is why we started at zero.
 //!         self.count += 1;
 //!
diff --git a/src/libcore/iter/sources.rs b/src/libcore/iter/sources.rs
index 74ff7f4..ffc24df 100644
--- a/src/libcore/iter/sources.rs
+++ b/src/libcore/iter/sources.rs
@@ -39,8 +39,7 @@
 
 /// Creates a new iterator that endlessly repeats a single element.
 ///
-/// The `repeat()` function repeats a single value over and over and over and
-/// over and over and 🔁.
+/// The `repeat()` function repeats a single value over and over again.
 ///
 /// Infinite iterators like `repeat()` are often used with adapters like
 /// [`take`], in order to make them finite.
@@ -128,8 +127,7 @@
 /// Creates a new iterator that repeats elements of type `A` endlessly by
 /// applying the provided closure, the repeater, `F: FnMut() -> A`.
 ///
-/// The `repeat_with()` function calls the repeater over and over and over and
-/// over and over and 🔁.
+/// The `repeat_with()` function calls the repeater over and over again.
 ///
 /// Infinite iterators like `repeat_with()` are often used with adapters like
 /// [`take`], in order to make them finite.
diff --git a/src/libcore/iter/traits/collect.rs b/src/libcore/iter/traits/collect.rs
index 5204f6a..cd61ab5 100644
--- a/src/libcore/iter/traits/collect.rs
+++ b/src/libcore/iter/traits/collect.rs
@@ -167,7 +167,7 @@
 /// // and we'll implement IntoIterator
 /// impl IntoIterator for MyCollection {
 ///     type Item = i32;
-///     type IntoIter = ::std::vec::IntoIter<i32>;
+///     type IntoIter = ::std::vec::IntoIter<Self::Item>;
 ///
 ///     fn into_iter(self) -> Self::IntoIter {
 ///         self.0.into_iter()
diff --git a/src/libcore/iter/traits/exact_size.rs b/src/libcore/iter/traits/exact_size.rs
index d6eab40..8fc4ac9 100644
--- a/src/libcore/iter/traits/exact_size.rs
+++ b/src/libcore/iter/traits/exact_size.rs
@@ -45,7 +45,7 @@
 /// # }
 /// # impl Iterator for Counter {
 /// #     type Item = usize;
-/// #     fn next(&mut self) -> Option<usize> {
+/// #     fn next(&mut self) -> Option<Self::Item> {
 /// #         self.count += 1;
 /// #         if self.count < 6 {
 /// #             Some(self.count)
diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs
index b052f59..d77936c 100644
--- a/src/libcore/macros.rs
+++ b/src/libcore/macros.rs
@@ -559,6 +559,65 @@
     ($($arg:tt)+) => (panic!("not yet implemented: {}", format_args!($($arg)*)));
 }
 
+/// A standardized placeholder for marking unfinished code.
+///
+/// This can be useful if you are prototyping and are just looking to have your
+/// code typecheck. `todo!` works exactly like `unimplemented!`, there only
+/// difference between the two macros is the name.
+///
+/// # Panics
+///
+/// This will always [panic!](macro.panic.html)
+///
+/// # Examples
+///
+/// Here's an example of some in-progress code. We have a trait `Foo`:
+///
+/// ```
+/// trait Foo {
+///     fn bar(&self);
+///     fn baz(&self);
+/// }
+/// ```
+///
+/// We want to implement `Foo` on one of our types, but we also want to work on
+/// just `bar()` first. In order for our code to compile, we need to implement
+/// `baz()`, so we can use `todo!`:
+///
+/// ```
+/// #![feature(todo_macro)]
+///
+/// # trait Foo {
+/// #     fn bar(&self);
+/// #     fn baz(&self);
+/// # }
+/// struct MyStruct;
+///
+/// impl Foo for MyStruct {
+///     fn bar(&self) {
+///         // implementation goes here
+///     }
+///
+///     fn baz(&self) {
+///         // let's not worry about implementing baz() for now
+///         todo!();
+///     }
+/// }
+///
+/// fn main() {
+///     let s = MyStruct;
+///     s.bar();
+///
+///     // we aren't even using baz() yet, so this is fine.
+/// }
+/// ```
+#[macro_export]
+#[unstable(feature = "todo_macro", issue = "59277")]
+macro_rules! todo {
+    () => (panic!("not yet implemented"));
+    ($($arg:tt)+) => (panic!("not yet implemented: {}", format_args!($($arg)*)));
+}
+
 /// A macro to create an array of [`MaybeUninit`]
 ///
 /// This macro constructs an uninitialized array of the type `[MaybeUninit<K>; N]`.
diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs
index 90e84d0..3d2fcdc 100644
--- a/src/libcore/mem.rs
+++ b/src/libcore/mem.rs
@@ -1111,11 +1111,12 @@
 /// ```
 ///
 /// The compiler then knows to not make any incorrect assumptions or optimizations on this code.
+//
 // FIXME before stabilizing, explain how to initialize a struct field-by-field.
 #[allow(missing_debug_implementations)]
 #[unstable(feature = "maybe_uninit", issue = "53491")]
 #[derive(Copy)]
-// NOTE after stabilizing `MaybeUninit` proceed to deprecate `mem::uninitialized`.
+// NOTE: after stabilizing `MaybeUninit`, proceed to deprecate `mem::uninitialized`.
 pub union MaybeUninit<T> {
     uninit: (),
     value: ManuallyDrop<T>,
@@ -1125,13 +1126,13 @@
 impl<T: Copy> Clone for MaybeUninit<T> {
     #[inline(always)]
     fn clone(&self) -> Self {
-        // Not calling T::clone(), we cannot know if we are initialized enough for that.
+        // Not calling `T::clone()`, we cannot know if we are initialized enough for that.
         *self
     }
 }
 
 impl<T> MaybeUninit<T> {
-    /// Create a new `MaybeUninit<T>` initialized with the given value.
+    /// Creates a new `MaybeUninit<T>` initialized with the given value.
     ///
     /// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code.
     /// It is your responsibility to make sure `T` gets dropped if it got initialized.
@@ -1239,6 +1240,7 @@
     /// let x_vec = unsafe { &*x.as_ptr() };
     /// // We have created a reference to an uninitialized vector! This is undefined behavior.
     /// ```
+    ///
     /// (Notice that the rules around references to uninitialized data are not finalized yet, but
     /// until they are, it is advisable to avoid them.)
     #[unstable(feature = "maybe_uninit", issue = "53491")]
@@ -1277,6 +1279,7 @@
     /// let x_vec = unsafe { &mut *x.as_mut_ptr() };
     /// // We have created a reference to an uninitialized vector! This is undefined behavior.
     /// ```
+    ///
     /// (Notice that the rules around references to uninitialized data are not finalized yet, but
     /// until they are, it is advisable to avoid them.)
     #[unstable(feature = "maybe_uninit", issue = "53491")]
diff --git a/src/libcore/num/dec2flt/algorithm.rs b/src/libcore/num/dec2flt/algorithm.rs
index 3b57bb7..a83134a 100644
--- a/src/libcore/num/dec2flt/algorithm.rs
+++ b/src/libcore/num/dec2flt/algorithm.rs
@@ -326,7 +326,7 @@
     round_by_remainder(v, rem, q, z)
 }
 
-/// Skip over most Algorithm M iterations by checking the bit length.
+/// Skips over most Algorithm M iterations by checking the bit length.
 fn quick_start<T: RawFloat>(u: &mut Big, v: &mut Big, k: &mut i16) {
     // The bit length is an estimate of the base two logarithm, and log(u / v) = log(u) - log(v).
     // The estimate is off by at most 1, but always an under-estimate, so the error on log(u)
diff --git a/src/libcore/num/dec2flt/mod.rs b/src/libcore/num/dec2flt/mod.rs
index 47ea5aa..d62cdae 100644
--- a/src/libcore/num/dec2flt/mod.rs
+++ b/src/libcore/num/dec2flt/mod.rs
@@ -304,8 +304,8 @@
     }
 }
 
-/// Quick and dirty upper bound on the size (log10) of the largest value that Algorithm R and
-/// Algorithm M will compute while working on the given decimal.
+/// Returns a quick-an-dirty upper bound on the size (log10) of the largest value that Algorithm R
+/// and Algorithm M will compute while working on the given decimal.
 fn bound_intermediate_digits(decimal: &Decimal, e: i64) -> u64 {
     // We don't need to worry too much about overflow here thanks to trivial_cases() and the
     // parser, which filter out the most extreme inputs for us.
@@ -324,7 +324,7 @@
     }
 }
 
-/// Detect obvious overflows and underflows without even looking at the decimal digits.
+/// Detects obvious overflows and underflows without even looking at the decimal digits.
 fn trivial_cases<T: RawFloat>(decimal: &Decimal) -> Option<T> {
     // There were zeros but they were stripped by simplify()
     if decimal.integral.is_empty() && decimal.fractional.is_empty() {
diff --git a/src/libcore/num/dec2flt/parse.rs b/src/libcore/num/dec2flt/parse.rs
index 933f8c1..f970595 100644
--- a/src/libcore/num/dec2flt/parse.rs
+++ b/src/libcore/num/dec2flt/parse.rs
@@ -78,7 +78,7 @@
     }
 }
 
-/// Carve off decimal digits up to the first non-digit character.
+/// Carves off decimal digits up to the first non-digit character.
 fn eat_digits(s: &[u8]) -> (&[u8], &[u8]) {
     let mut i = 0;
     while i < s.len() && b'0' <= s[i] && s[i] <= b'9' {
diff --git a/src/libcore/num/flt2dec/decoder.rs b/src/libcore/num/flt2dec/decoder.rs
index a3bf783..a8da31d 100644
--- a/src/libcore/num/flt2dec/decoder.rs
+++ b/src/libcore/num/flt2dec/decoder.rs
@@ -10,7 +10,7 @@
 ///
 /// - Any number from `(mant - minus) * 2^exp` to `(mant + plus) * 2^exp` will
 ///   round to the original value. The range is inclusive only when
-///   `inclusive` is true.
+///   `inclusive` is `true`.
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 pub struct Decoded {
     /// The scaled mantissa.
diff --git a/src/libcore/num/flt2dec/mod.rs b/src/libcore/num/flt2dec/mod.rs
index f9b46a1..defd424 100644
--- a/src/libcore/num/flt2dec/mod.rs
+++ b/src/libcore/num/flt2dec/mod.rs
@@ -315,15 +315,15 @@
     }
 }
 
-/// Formats given decimal digits `0.<...buf...> * 10^exp` into the exponential form
-/// with at least given number of significant digits. When `upper` is true,
+/// Formats the given decimal digits `0.<...buf...> * 10^exp` into the exponential
+/// form with at least the given number of significant digits. When `upper` is `true`,
 /// the exponent will be prefixed by `E`; otherwise that's `e`. The result is
 /// stored to the supplied parts array and a slice of written parts is returned.
 ///
 /// `min_digits` can be less than the number of actual significant digits in `buf`;
 /// it will be ignored and full digits will be printed. It is only used to print
-/// additional zeroes after rendered digits. Thus `min_digits` of 0 means that
-/// it will only print given digits and nothing else.
+/// additional zeroes after rendered digits. Thus, `min_digits == 0` means that
+/// it will only print the given digits and nothing else.
 fn digits_to_exp_str<'a>(buf: &'a [u8], exp: i16, min_ndigits: usize, upper: bool,
                          parts: &'a mut [Part<'a>]) -> &'a [Part<'a>] {
     assert!(!buf.is_empty());
@@ -384,7 +384,7 @@
     }
 }
 
-/// Formats given floating point number into the decimal form with at least
+/// Formats the given floating point number into the decimal form with at least
 /// given number of fractional digits. The result is stored to the supplied parts
 /// array while utilizing given byte buffer as a scratch. `upper` is currently
 /// unused but left for the future decision to change the case of non-finite values,
@@ -438,7 +438,7 @@
     }
 }
 
-/// Formats given floating point number into the decimal form or
+/// Formats the given floating point number into the decimal form or
 /// the exponential form, depending on the resulting exponent. The result is
 /// stored to the supplied parts array while utilizing given byte buffer
 /// as a scratch. `upper` is used to determine the case of non-finite values
@@ -497,7 +497,7 @@
     }
 }
 
-/// Returns rather crude approximation (upper bound) for the maximum buffer size
+/// Returns a rather crude approximation (upper bound) for the maximum buffer size
 /// calculated from the given decoded exponent.
 ///
 /// The exact limit is:
diff --git a/src/libcore/ops/arith.rs b/src/libcore/ops/arith.rs
index 38ec0d8..28c9ff9 100644
--- a/src/libcore/ops/arith.rs
+++ b/src/libcore/ops/arith.rs
@@ -20,10 +20,10 @@
 /// }
 ///
 /// impl Add for Point {
-///     type Output = Point;
+///     type Output = Self;
 ///
-///     fn add(self, other: Point) -> Point {
-///         Point {
+///     fn add(self, other: Self) -> Self {
+///         Self {
 ///             x: self.x + other.x,
 ///             y: self.y + other.y,
 ///         }
@@ -50,10 +50,10 @@
 ///
 /// // Notice that the implementation uses the associated type `Output`.
 /// impl<T: Add<Output = T>> Add for Point<T> {
-///     type Output = Point<T>;
+///     type Output = Self;
 ///
-///     fn add(self, other: Point<T>) -> Point<T> {
-///         Point {
+///     fn add(self, other: Self) -> Self::Output {
+///         Self {
 ///             x: self.x + other.x,
 ///             y: self.y + other.y,
 ///         }
@@ -158,9 +158,9 @@
 ///
 /// // Notice that the implementation uses the associated type `Output`.
 /// impl<T: Sub<Output = T>> Sub for Point<T> {
-///     type Output = Point<T>;
+///     type Output = Self;
 ///
-///     fn sub(self, other: Point<T>) -> Point<T> {
+///     fn sub(self, other: Self) -> Self::Output {
 ///         Point {
 ///             x: self.x - other.x,
 ///             y: self.y - other.y,
@@ -280,9 +280,9 @@
 /// struct Vector { value: Vec<usize> }
 ///
 /// impl Mul<Scalar> for Vector {
-///     type Output = Vector;
+///     type Output = Self;
 ///
-///     fn mul(self, rhs: Scalar) -> Vector {
+///     fn mul(self, rhs: Scalar) -> Self::Output {
 ///         Vector { value: self.value.iter().map(|v| v * rhs.value).collect() }
 ///     }
 /// }
@@ -364,7 +364,7 @@
 ///     // The division of rational numbers is a closed operation.
 ///     type Output = Self;
 ///
-///     fn div(self, rhs: Self) -> Self {
+///     fn div(self, rhs: Self) -> Self::Output {
 ///         if rhs.nominator == 0 {
 ///             panic!("Cannot divide by zero-valued `Rational`!");
 ///         }
@@ -404,9 +404,9 @@
 /// struct Vector { value: Vec<f32> }
 ///
 /// impl Div<Scalar> for Vector {
-///     type Output = Vector;
+///     type Output = Self;
 ///
-///     fn div(self, rhs: Scalar) -> Vector {
+///     fn div(self, rhs: Scalar) -> Self::Output {
 ///         Vector { value: self.value.iter().map(|v| v / rhs.value).collect() }
 ///     }
 /// }
@@ -485,9 +485,9 @@
 /// }
 ///
 /// impl<'a, T> Rem<usize> for SplitSlice<'a, T> {
-///     type Output = SplitSlice<'a, T>;
+///     type Output = Self;
 ///
-///     fn rem(self, modulus: usize) -> Self {
+///     fn rem(self, modulus: usize) -> Self::Output {
 ///         let len = self.slice.len();
 ///         let rem = len % modulus;
 ///         let start = len - rem;
@@ -571,7 +571,7 @@
 /// impl Neg for Sign {
 ///     type Output = Sign;
 ///
-///     fn neg(self) -> Sign {
+///     fn neg(self) -> Self::Output {
 ///         match self {
 ///             Sign::Negative => Sign::Positive,
 ///             Sign::Zero => Sign::Zero,
@@ -650,8 +650,8 @@
 /// }
 ///
 /// impl AddAssign for Point {
-///     fn add_assign(&mut self, other: Point) {
-///         *self = Point {
+///     fn add_assign(&mut self, other: Self) {
+///         *self = Self {
 ///             x: self.x + other.x,
 ///             y: self.y + other.y,
 ///         };
@@ -706,8 +706,8 @@
 /// }
 ///
 /// impl SubAssign for Point {
-///     fn sub_assign(&mut self, other: Point) {
-///         *self = Point {
+///     fn sub_assign(&mut self, other: Self) {
+///         *self = Self {
 ///             x: self.x - other.x,
 ///             y: self.y - other.y,
 ///         };
diff --git a/src/libcore/ops/bit.rs b/src/libcore/ops/bit.rs
index 1b9c5e6b..a8f862f 100644
--- a/src/libcore/ops/bit.rs
+++ b/src/libcore/ops/bit.rs
@@ -17,7 +17,7 @@
 /// impl Not for Answer {
 ///     type Output = Answer;
 ///
-///     fn not(self) -> Answer {
+///     fn not(self) -> Self::Output {
 ///         match self {
 ///             Answer::Yes => Answer::No,
 ///             Answer::No => Answer::Yes
@@ -75,7 +75,7 @@
 ///     type Output = Self;
 ///
 ///     // rhs is the "right-hand side" of the expression `a & b`
-///     fn bitand(self, rhs: Self) -> Self {
+///     fn bitand(self, rhs: Self) -> Self::Output {
 ///         Scalar(self.0 & rhs.0)
 ///     }
 /// }
@@ -97,7 +97,7 @@
 /// impl BitAnd for BooleanVector {
 ///     type Output = Self;
 ///
-///     fn bitand(self, BooleanVector(rhs): Self) -> Self {
+///     fn bitand(self, BooleanVector(rhs): Self) -> Self::Output {
 ///         let BooleanVector(lhs) = self;
 ///         assert_eq!(lhs.len(), rhs.len());
 ///         BooleanVector(lhs.iter().zip(rhs.iter()).map(|(x, y)| *x && *y).collect())
@@ -181,7 +181,7 @@
 /// impl BitOr for BooleanVector {
 ///     type Output = Self;
 ///
-///     fn bitor(self, BooleanVector(rhs): Self) -> Self {
+///     fn bitor(self, BooleanVector(rhs): Self) -> Self::Output {
 ///         let BooleanVector(lhs) = self;
 ///         assert_eq!(lhs.len(), rhs.len());
 ///         BooleanVector(lhs.iter().zip(rhs.iter()).map(|(x, y)| *x || *y).collect())
@@ -243,7 +243,7 @@
 ///     type Output = Self;
 ///
 ///     // rhs is the "right-hand side" of the expression `a ^ b`
-///     fn bitxor(self, rhs: Self) -> Self {
+///     fn bitxor(self, rhs: Self) -> Self::Output {
 ///         Scalar(self.0 ^ rhs.0)
 ///     }
 /// }
@@ -265,7 +265,7 @@
 /// impl BitXor for BooleanVector {
 ///     type Output = Self;
 ///
-///     fn bitxor(self, BooleanVector(rhs): Self) -> Self {
+///     fn bitxor(self, BooleanVector(rhs): Self) -> Self::Output {
 ///         let BooleanVector(lhs) = self;
 ///         assert_eq!(lhs.len(), rhs.len());
 ///         BooleanVector(lhs.iter()
@@ -355,7 +355,7 @@
 /// impl<T: Clone> Shl<usize> for SpinVector<T> {
 ///     type Output = Self;
 ///
-///     fn shl(self, rhs: usize) -> SpinVector<T> {
+///     fn shl(self, rhs: usize) -> Self::Output {
 ///         // Rotate the vector by `rhs` places.
 ///         let (a, b) = self.vec.split_at(rhs);
 ///         let mut spun_vector: Vec<T> = vec![];
@@ -464,7 +464,7 @@
 /// impl<T: Clone> Shr<usize> for SpinVector<T> {
 ///     type Output = Self;
 ///
-///     fn shr(self, rhs: usize) -> SpinVector<T> {
+///     fn shr(self, rhs: usize) -> Self::Output {
 ///         // Rotate the vector by `rhs` places.
 ///         let (a, b) = self.vec.split_at(self.vec.len() - rhs);
 ///         let mut spun_vector: Vec<T> = vec![];
diff --git a/src/libcore/ops/deref.rs b/src/libcore/ops/deref.rs
index eb76c2d..e44a6c4 100644
--- a/src/libcore/ops/deref.rs
+++ b/src/libcore/ops/deref.rs
@@ -49,7 +49,7 @@
 /// impl<T> Deref for DerefExample<T> {
 ///     type Target = T;
 ///
-///     fn deref(&self) -> &T {
+///     fn deref(&self) -> &Self::Target {
 ///         &self.value
 ///     }
 /// }
@@ -139,13 +139,13 @@
 /// impl<T> Deref for DerefMutExample<T> {
 ///     type Target = T;
 ///
-///     fn deref(&self) -> &T {
+///     fn deref(&self) -> &Self::Target {
 ///         &self.value
 ///     }
 /// }
 ///
 /// impl<T> DerefMut for DerefMutExample<T> {
-///     fn deref_mut(&mut self) -> &mut T {
+///     fn deref_mut(&mut self) -> &mut Self::Target {
 ///         &mut self.value
 ///     }
 /// }
diff --git a/src/libcore/ops/index.rs b/src/libcore/ops/index.rs
index d4ed861..3158f58 100644
--- a/src/libcore/ops/index.rs
+++ b/src/libcore/ops/index.rs
@@ -33,7 +33,7 @@
 /// impl Index<Nucleotide> for NucleotideCount {
 ///     type Output = usize;
 ///
-///     fn index(&self, nucleotide: Nucleotide) -> &usize {
+///     fn index(&self, nucleotide: Nucleotide) -> &Self::Output {
 ///         match nucleotide {
 ///             Nucleotide::A => &self.a,
 ///             Nucleotide::C => &self.c,
@@ -105,7 +105,7 @@
 /// impl Index<Side> for Balance {
 ///     type Output = Weight;
 ///
-///     fn index<'a>(&'a self, index: Side) -> &'a Weight {
+///     fn index<'a>(&'a self, index: Side) -> &'a Self::Output {
 ///         println!("Accessing {:?}-side of balance immutably", index);
 ///         match index {
 ///             Side::Left => &self.left,
@@ -115,7 +115,7 @@
 /// }
 ///
 /// impl IndexMut<Side> for Balance {
-///     fn index_mut<'a>(&'a mut self, index: Side) -> &'a mut Weight {
+///     fn index_mut<'a>(&'a mut self, index: Side) -> &'a mut Self::Output {
 ///         println!("Accessing {:?}-side of balance mutably", index);
 ///         match index {
 ///             Side::Left => &mut self.left,
diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs
index 81a8d00..4f71c8e 100644
--- a/src/libcore/ops/range.rs
+++ b/src/libcore/ops/range.rs
@@ -71,7 +71,7 @@
 /// assert_eq!(arr[1..=3], [  1,2,3  ]);
 /// ```
 #[doc(alias = "..")]
-#[derive(Clone, PartialEq, Eq, Hash)]  // not Copy -- see #27186
+#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Range<Idx> {
     /// The lower bound of the range (inclusive).
@@ -95,8 +95,6 @@
     /// # Examples
     ///
     /// ```
-    /// #![feature(range_contains)]
-    ///
     /// use std::f32;
     ///
     /// assert!(!(3..5).contains(&2));
@@ -112,7 +110,7 @@
     /// assert!(!(0.0..f32::NAN).contains(&0.5));
     /// assert!(!(f32::NAN..1.0).contains(&0.5));
     /// ```
-    #[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
+    #[stable(feature = "range_contains", since = "1.35.0")]
     pub fn contains<U>(&self, item: &U) -> bool
     where
         Idx: PartialOrd<U>,
@@ -175,7 +173,7 @@
 ///
 /// [`Iterator`]: ../iter/trait.IntoIterator.html
 #[doc(alias = "..")]
-#[derive(Clone, PartialEq, Eq, Hash)]  // not Copy -- see #27186
+#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RangeFrom<Idx> {
     /// The lower bound of the range (inclusive).
@@ -196,8 +194,6 @@
     /// # Examples
     ///
     /// ```
-    /// #![feature(range_contains)]
-    ///
     /// use std::f32;
     ///
     /// assert!(!(3..).contains(&2));
@@ -208,7 +204,7 @@
     /// assert!(!(0.0..).contains(&f32::NAN));
     /// assert!(!(f32::NAN..).contains(&0.5));
     /// ```
-    #[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
+    #[stable(feature = "range_contains", since = "1.35.0")]
     pub fn contains<U>(&self, item: &U) -> bool
     where
         Idx: PartialOrd<U>,
@@ -280,8 +276,6 @@
     /// # Examples
     ///
     /// ```
-    /// #![feature(range_contains)]
-    ///
     /// use std::f32;
     ///
     /// assert!( (..5).contains(&-1_000_000_000));
@@ -292,7 +286,7 @@
     /// assert!(!(..1.0).contains(&f32::NAN));
     /// assert!(!(..f32::NAN).contains(&0.5));
     /// ```
-    #[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
+    #[stable(feature = "range_contains", since = "1.35.0")]
     pub fn contains<U>(&self, item: &U) -> bool
     where
         Idx: PartialOrd<U>,
@@ -329,7 +323,7 @@
 /// assert_eq!(arr[1..=3], [  1,2,3  ]);  // RangeInclusive
 /// ```
 #[doc(alias = "..=")]
-#[derive(Clone)]  // not Copy -- see #27186
+#[derive(Clone)] // not Copy -- see #27186
 #[stable(feature = "inclusive_range", since = "1.26.0")]
 pub struct RangeInclusive<Idx> {
     pub(crate) start: Idx,
@@ -365,7 +359,8 @@
 impl<Idx: PartialEq> PartialEq for RangeInclusive<Idx> {
     #[inline]
     fn eq(&self, other: &Self) -> bool {
-        self.start == other.start && self.end == other.end
+        self.start == other.start
+            && self.end == other.end
             && RangeInclusiveEquality::canonicalized_is_empty(self)
                 == RangeInclusiveEquality::canonicalized_is_empty(other)
     }
@@ -397,7 +392,11 @@
     #[inline]
     #[rustc_promotable]
     pub const fn new(start: Idx, end: Idx) -> Self {
-        Self { start, end, is_empty: None }
+        Self {
+            start,
+            end,
+            is_empty: None,
+        }
     }
 
     /// Returns the lower bound of the range (inclusive).
@@ -478,8 +477,6 @@
     /// # Examples
     ///
     /// ```
-    /// #![feature(range_contains)]
-    ///
     /// use std::f32;
     ///
     /// assert!(!(3..=5).contains(&2));
@@ -496,7 +493,7 @@
     /// assert!(!(0.0..=f32::NAN).contains(&0.0));
     /// assert!(!(f32::NAN..=1.0).contains(&1.0));
     /// ```
-    #[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
+    #[stable(feature = "range_contains", since = "1.35.0")]
     pub fn contains<U>(&self, item: &U) -> bool
     where
         Idx: PartialOrd<U>,
@@ -609,15 +606,12 @@
     }
 }
 
-#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
 impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> {
     /// Returns `true` if `item` is contained in the range.
     ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(range_contains)]
-    ///
     /// use std::f32;
     ///
     /// assert!( (..=5).contains(&-1_000_000_000));
@@ -628,7 +622,7 @@
     /// assert!(!(..=1.0).contains(&f32::NAN));
     /// assert!(!(..=f32::NAN).contains(&0.5));
     /// ```
-    #[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
+    #[stable(feature = "range_contains", since = "1.35.0")]
     pub fn contains<U>(&self, item: &U) -> bool
     where
         Idx: PartialOrd<U>,
@@ -730,14 +724,11 @@
     #[stable(feature = "collections_range", since = "1.28.0")]
     fn end_bound(&self) -> Bound<&T>;
 
-
     /// Returns `true` if `item` is contained in the range.
     ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(range_contains)]
-    ///
     /// use std::f32;
     ///
     /// assert!( (3..5).contains(&4));
@@ -747,7 +738,7 @@
     /// assert!(!(0.0..1.0).contains(&f32::NAN));
     /// assert!(!(0.0..f32::NAN).contains(&0.5));
     /// assert!(!(f32::NAN..1.0).contains(&0.5));
-    #[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
+    #[stable(feature = "range_contains", since = "1.35.0")]
     fn contains<U>(&self, item: &U) -> bool
     where
         T: PartialOrd<U>,
@@ -757,9 +748,7 @@
             Included(ref start) => *start <= item,
             Excluded(ref start) => *start < item,
             Unbounded => true,
-        })
-        &&
-        (match self.end_bound() {
+        }) && (match self.end_bound() {
             Included(ref end) => item <= *end,
             Excluded(ref end) => item < *end,
             Unbounded => true,
@@ -835,7 +824,7 @@
         match *self {
             (Included(ref start), _) => Included(start),
             (Excluded(ref start), _) => Excluded(start),
-            (Unbounded, _)           => Unbounded,
+            (Unbounded, _) => Unbounded,
         }
     }
 
@@ -843,7 +832,7 @@
         match *self {
             (_, Included(ref end)) => Included(end),
             (_, Excluded(ref end)) => Excluded(end),
-            (_, Unbounded)         => Unbounded,
+            (_, Unbounded) => Unbounded,
         }
     }
 }
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index 46dfe28..dfc3884 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -210,7 +210,7 @@
     // Adapter for working with references
     /////////////////////////////////////////////////////////////////////////
 
-    /// Converts from `Option<T>` to `Option<&T>`.
+    /// Converts from `&Option<T>` to `Option<&T>`.
     ///
     /// # Examples
     ///
@@ -239,7 +239,7 @@
         }
     }
 
-    /// Converts from `Option<T>` to `Option<&mut T>`.
+    /// Converts from `&mut Option<T>` to `Option<&mut T>`.
     ///
     /// # Examples
     ///
@@ -881,15 +881,13 @@
     /// # Examples
     ///
     /// ```
-    /// #![feature(copied)]
-    ///
     /// let x = 12;
     /// let opt_x = Some(&x);
     /// assert_eq!(opt_x, Some(&12));
     /// let copied = opt_x.copied();
     /// assert_eq!(copied, Some(12));
     /// ```
-    #[unstable(feature = "copied", issue = "57126")]
+    #[stable(feature = "copied", since = "1.35.0")]
     pub fn copied(self) -> Option<T> {
         self.map(|&t| t)
     }
@@ -902,15 +900,13 @@
     /// # Examples
     ///
     /// ```
-    /// #![feature(copied)]
-    ///
     /// let mut x = 12;
     /// let opt_x = Some(&mut x);
     /// assert_eq!(opt_x, Some(&mut 12));
     /// let copied = opt_x.copied();
     /// assert_eq!(copied, Some(12));
     /// ```
-    #[unstable(feature = "copied", issue = "57126")]
+    #[stable(feature = "copied", since = "1.35.0")]
     pub fn copied(self) -> Option<T> {
         self.map(|&mut t| t)
     }
diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs
index fb78f5e..57bd3ed 100644
--- a/src/libcore/pin.rs
+++ b/src/libcore/pin.rs
@@ -1,4 +1,4 @@
-//! Types which pin data to its location in memory
+//! Types that pin data to its location in memory.
 //!
 //! It is sometimes useful to have objects that are guaranteed to not move,
 //! in the sense that their placement in memory does not change, and can thus be relied upon.
@@ -109,7 +109,7 @@
 //! assert_eq!(still_unmoved.slice, NonNull::from(&still_unmoved.data));
 //!
 //! // Since our type doesn't implement Unpin, this will fail to compile:
-//! // let new_unmoved = Unmovable::new("world".to_string());
+//! // let mut new_unmoved = Unmovable::new("world".to_string());
 //! // std::mem::swap(&mut *still_unmoved, &mut *new_unmoved);
 //! ```
 //!
diff --git a/src/libcore/result.rs b/src/libcore/result.rs
index 2bd6b53..967f7e3 100644
--- a/src/libcore/result.rs
+++ b/src/libcore/result.rs
@@ -369,7 +369,7 @@
     // Adapter for working with references
     /////////////////////////////////////////////////////////////////////////
 
-    /// Converts from `Result<T, E>` to `Result<&T, &E>`.
+    /// Converts from `&Result<T, E>` to `Result<&T, &E>`.
     ///
     /// Produces a new `Result`, containing a reference
     /// into the original, leaving the original in place.
@@ -394,7 +394,7 @@
         }
     }
 
-    /// Converts from `Result<T, E>` to `Result<&mut T, &mut E>`.
+    /// Converts from `&mut Result<T, E>` to `Result<&mut T, &mut E>`.
     ///
     /// # Examples
     ///
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 53334ad..528281d 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -2968,7 +2968,7 @@
     ///
     /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern
     /// allows a reverse search and forward/reverse search yields the same
-    /// elements. This is true for, eg, [`char`] but not for `&str`.
+    /// elements. This is true for, e.g., [`char`], but not for `&str`.
     ///
     /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
     ///
@@ -3143,7 +3143,7 @@
     ///
     /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern
     /// allows a reverse search and forward/reverse search yields the same
-    /// elements. This is true for, eg, [`char`] but not for `&str`.
+    /// elements. This is true for, e.g., [`char`], but not for `&str`.
     ///
     /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
     ///
@@ -3326,7 +3326,7 @@
     ///
     /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern
     /// allows a reverse search and forward/reverse search yields the same
-    /// elements. This is true for, eg, [`char`] but not for `&str`.
+    /// elements. This is true for, e.g., [`char`], but not for `&str`.
     ///
     /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
     ///
@@ -3402,7 +3402,7 @@
     ///
     /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern
     /// allows a reverse search and forward/reverse search yields the same
-    /// elements. This is true for, eg, [`char`] but not for `&str`.
+    /// elements. This is true for, e.g., [`char`], but not for `&str`.
     ///
     /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
     ///
diff --git a/src/libcore/task/wake.rs b/src/libcore/task/wake.rs
index 21f0a8c..12f812d 100644
--- a/src/libcore/task/wake.rs
+++ b/src/libcore/task/wake.rs
@@ -108,7 +108,7 @@
         unsafe { (self.waker.vtable.wake)(self.waker.data) }
     }
 
-    /// Returns whether or not this `Waker` and other `Waker` have awaken the same task.
+    /// Returns `true` if this `Waker` and another `Waker` have awoken the same task.
     ///
     /// This function works on a best-effort basis, and may return false even
     /// when the `Waker`s would awaken the same task. However, if this function
diff --git a/src/libcore/tests/cell.rs b/src/libcore/tests/cell.rs
index b164160..7bd7d18 100644
--- a/src/libcore/tests/cell.rs
+++ b/src/libcore/tests/cell.rs
@@ -5,15 +5,15 @@
 #[test]
 fn smoketest_cell() {
     let x = Cell::new(10);
-    assert!(x == Cell::new(10));
-    assert!(x.get() == 10);
+    assert_eq!(x, Cell::new(10));
+    assert_eq!(x.get(), 10);
     x.set(20);
-    assert!(x == Cell::new(20));
-    assert!(x.get() == 20);
+    assert_eq!(x, Cell::new(20));
+    assert_eq!(x.get(), 20);
 
     let y = Cell::new((30, 40));
-    assert!(y == Cell::new((30, 40)));
-    assert!(y.get() == (30, 40));
+    assert_eq!(y, Cell::new((30, 40)));
+    assert_eq!(y.get(), (30, 40));
 }
 
 #[test]
@@ -109,7 +109,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn discard_doesnt_unborrow() {
     let x = RefCell::new(0);
     let _b = x.borrow();
@@ -350,7 +349,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn refcell_swap_borrows() {
     let x = RefCell::new(0);
     let _b = x.borrow();
@@ -360,7 +358,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn refcell_replace_borrows() {
     let x = RefCell::new(0);
     let _b = x.borrow();
diff --git a/src/libcore/tests/char.rs b/src/libcore/tests/char.rs
index 6185624..57e9f4e 100644
--- a/src/libcore/tests/char.rs
+++ b/src/libcore/tests/char.rs
@@ -76,6 +76,8 @@
 #[test]
 fn test_to_lowercase() {
     fn lower(c: char) -> String {
+        let to_lowercase = c.to_lowercase();
+        assert_eq!(to_lowercase.len(), to_lowercase.count());
         let iter: String = c.to_lowercase().collect();
         let disp: String = c.to_lowercase().to_string();
         assert_eq!(iter, disp);
@@ -101,6 +103,8 @@
 #[test]
 fn test_to_uppercase() {
     fn upper(c: char) -> String {
+        let to_uppercase = c.to_uppercase();
+        assert_eq!(to_uppercase.len(), to_uppercase.count());
         let iter: String = c.to_uppercase().collect();
         let disp: String = c.to_uppercase().to_string();
         assert_eq!(iter, disp);
diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs
index a9db9b3..a3f0b02 100644
--- a/src/libcore/tests/iter.rs
+++ b/src/libcore/tests/iter.rs
@@ -253,7 +253,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_iterator_step_by_zero() {
     let mut it = (0..).step_by(0);
     it.next();
@@ -1442,7 +1441,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_rposition_panic() {
     let v: [(Box<_>, Box<_>); 4] =
         [(box 0, box 0), (box 0, box 0),
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index d002137..08dda4b 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -1,6 +1,5 @@
 #![feature(box_syntax)]
 #![feature(cell_update)]
-#![feature(copied)]
 #![feature(core_private_bignum)]
 #![feature(core_private_diy_float)]
 #![feature(dec2flt)]
@@ -17,7 +16,6 @@
 #![feature(pattern)]
 #![feature(range_is_empty)]
 #![feature(raw)]
-#![feature(refcell_map_split)]
 #![feature(refcell_replace_swap)]
 #![feature(slice_patterns)]
 #![feature(sort_internals)]
diff --git a/src/libcore/tests/num/bignum.rs b/src/libcore/tests/num/bignum.rs
index 956c22c..b873f1d 100644
--- a/src/libcore/tests/num/bignum.rs
+++ b/src/libcore/tests/num/bignum.rs
@@ -3,7 +3,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_from_u64_overflow() {
     Big::from_u64(0x1000000);
 }
@@ -20,14 +19,12 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_add_overflow_1() {
     Big::from_small(1).add(&Big::from_u64(0xffffff));
 }
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_add_overflow_2() {
     Big::from_u64(0xffffff).add(&Big::from_small(1));
 }
@@ -45,7 +42,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_add_small_overflow() {
     Big::from_u64(0xffffff).add_small(1);
 }
@@ -61,14 +57,12 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_sub_underflow_1() {
     Big::from_u64(0x10665).sub(&Big::from_u64(0x10666));
 }
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_sub_underflow_2() {
     Big::from_small(0).sub(&Big::from_u64(0x123456));
 }
@@ -82,7 +76,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_mul_small_overflow() {
     Big::from_u64(0x800000).mul_small(2);
 }
@@ -101,14 +94,12 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_mul_pow2_overflow_1() {
     Big::from_u64(0x1).mul_pow2(24);
 }
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_mul_pow2_overflow_2() {
     Big::from_u64(0x123).mul_pow2(16);
 }
@@ -127,14 +118,12 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_mul_pow5_overflow_1() {
     Big::from_small(1).mul_pow5(12);
 }
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_mul_pow5_overflow_2() {
     Big::from_small(230).mul_pow5(8);
 }
@@ -152,14 +141,12 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_mul_digits_overflow_1() {
     Big::from_u64(0x800000).mul_digits(&[2]);
 }
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_mul_digits_overflow_2() {
     Big::from_u64(0x1000).mul_digits(&[0, 0x10]);
 }
@@ -219,7 +206,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_get_bit_out_of_range() {
     Big::from_small(42).get_bit(24);
 }
diff --git a/src/libcore/tests/num/int_macros.rs b/src/libcore/tests/num/int_macros.rs
index 5c6ee8f..4881f79 100644
--- a/src/libcore/tests/num/int_macros.rs
+++ b/src/libcore/tests/num/int_macros.rs
@@ -12,7 +12,7 @@
     fn test_overflows() {
         assert!(MAX > 0);
         assert!(MIN <= 0);
-        assert!(MIN + MAX + 1 == 0);
+        assert_eq!(MIN + MAX + 1, 0);
     }
 
     #[test]
@@ -22,22 +22,22 @@
 
     #[test]
     fn test_rem_euclid() {
-        assert!((-1 as $T).rem_euclid(MIN) == MAX);
+        assert_eq!((-1 as $T).rem_euclid(MIN), MAX);
     }
 
     #[test]
     pub fn test_abs() {
-        assert!((1 as $T).abs() == 1 as $T);
-        assert!((0 as $T).abs() == 0 as $T);
-        assert!((-1 as $T).abs() == 1 as $T);
+        assert_eq!((1 as $T).abs(), 1 as $T);
+        assert_eq!((0 as $T).abs(), 0 as $T);
+        assert_eq!((-1 as $T).abs(), 1 as $T);
     }
 
     #[test]
     fn test_signum() {
-        assert!((1 as $T).signum() == 1 as $T);
-        assert!((0 as $T).signum() == 0 as $T);
-        assert!((-0 as $T).signum() == 0 as $T);
-        assert!((-1 as $T).signum() == -1 as $T);
+        assert_eq!((1 as $T).signum(), 1 as $T);
+        assert_eq!((0 as $T).signum(), 0 as $T);
+        assert_eq!((-0 as $T).signum(), 0 as $T);
+        assert_eq!((-1 as $T).signum(), -1 as $T);
     }
 
     #[test]
@@ -58,12 +58,12 @@
 
     #[test]
     fn test_bitwise_operators() {
-        assert!(0b1110 as $T == (0b1100 as $T).bitor(0b1010 as $T));
-        assert!(0b1000 as $T == (0b1100 as $T).bitand(0b1010 as $T));
-        assert!(0b0110 as $T == (0b1100 as $T).bitxor(0b1010 as $T));
-        assert!(0b1110 as $T == (0b0111 as $T).shl(1));
-        assert!(0b0111 as $T == (0b1110 as $T).shr(1));
-        assert!(-(0b11 as $T) - (1 as $T) == (0b11 as $T).not());
+        assert_eq!(0b1110 as $T, (0b1100 as $T).bitor(0b1010 as $T));
+        assert_eq!(0b1000 as $T, (0b1100 as $T).bitand(0b1010 as $T));
+        assert_eq!(0b0110 as $T, (0b1100 as $T).bitxor(0b1010 as $T));
+        assert_eq!(0b1110 as $T, (0b0111 as $T).shl(1));
+        assert_eq!(0b0111 as $T, (0b1110 as $T).shr(1));
+        assert_eq!(-(0b11 as $T) - (1 as $T), (0b11 as $T).not());
     }
 
     const A: $T = 0b0101100;
@@ -75,17 +75,17 @@
 
     #[test]
     fn test_count_ones() {
-        assert!(A.count_ones() == 3);
-        assert!(B.count_ones() == 2);
-        assert!(C.count_ones() == 5);
+        assert_eq!(A.count_ones(), 3);
+        assert_eq!(B.count_ones(), 2);
+        assert_eq!(C.count_ones(), 5);
     }
 
     #[test]
     fn test_count_zeros() {
         let bits = mem::size_of::<$T>() * 8;
-        assert!(A.count_zeros() == bits as u32 - 3);
-        assert!(B.count_zeros() == bits as u32 - 2);
-        assert!(C.count_zeros() == bits as u32 - 5);
+        assert_eq!(A.count_zeros(), bits as u32 - 3);
+        assert_eq!(B.count_zeros(), bits as u32 - 2);
+        assert_eq!(C.count_zeros(), bits as u32 - 5);
     }
 
     #[test]
@@ -148,9 +148,9 @@
 
     #[test]
     fn test_signed_checked_div() {
-        assert!((10 as $T).checked_div(2) == Some(5));
-        assert!((5 as $T).checked_div(0) == None);
-        assert!(isize::MIN.checked_div(-1) == None);
+        assert_eq!((10 as $T).checked_div(2), Some(5));
+        assert_eq!((5 as $T).checked_div(0), None);
+        assert_eq!(isize::MIN.checked_div(-1), None);
     }
 
     #[test]
diff --git a/src/libcore/tests/ops.rs b/src/libcore/tests/ops.rs
index 401644e..78cf071 100644
--- a/src/libcore/tests/ops.rs
+++ b/src/libcore/tests/ops.rs
@@ -7,11 +7,11 @@
     let r = Range { start: 2, end: 10 };
     let mut count = 0;
     for (i, ri) in r.enumerate() {
-        assert!(ri == i + 2);
+        assert_eq!(ri, i + 2);
         assert!(ri >= 2 && ri < 10);
         count += 1;
     }
-    assert!(count == 8);
+    assert_eq!(count, 8);
 }
 
 #[test]
@@ -19,11 +19,11 @@
     let r = RangeFrom { start: 2 };
     let mut count = 0;
     for (i, ri) in r.take(10).enumerate() {
-        assert!(ri == i + 2);
+        assert_eq!(ri, i + 2);
         assert!(ri >= 2 && ri < 12);
         count += 1;
     }
-    assert!(count == 10);
+    assert_eq!(count, 10);
 }
 
 #[test]
diff --git a/src/libcore/tests/option.rs b/src/libcore/tests/option.rs
index 87ce272..b059b13 100644
--- a/src/libcore/tests/option.rs
+++ b/src/libcore/tests/option.rs
@@ -69,7 +69,6 @@
 }
 
 #[test] #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_option_too_much_dance() {
     struct A;
     let mut y = Some(A);
@@ -130,7 +129,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_unwrap_panic1() {
     let x: Option<isize> = None;
     x.unwrap();
@@ -138,7 +136,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_unwrap_panic2() {
     let x: Option<String> = None;
     x.unwrap();
diff --git a/src/libcore/tests/result.rs b/src/libcore/tests/result.rs
index bbc85685..1fab075 100644
--- a/src/libcore/tests/result.rs
+++ b/src/libcore/tests/result.rs
@@ -117,7 +117,6 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 pub fn test_unwrap_or_else_panic() {
     fn handler(msg: &'static str) -> isize {
         if msg == "I got this." {
@@ -139,7 +138,6 @@
 }
 #[test]
 #[should_panic(expected="Got expected error: \"All good\"")]
-#[cfg(not(miri))] // Miri does not support panics
 pub fn test_expect_err() {
     let err: Result<isize, &'static str> = Err("All good");
     err.expect("Got expected error");
@@ -153,7 +151,6 @@
 }
 #[test]
 #[should_panic(expected="Got expected ok: \"All good\"")]
-#[cfg(not(miri))] // Miri does not support panics
 pub fn test_expect_err_ok() {
     let err: Result<&'static str, isize> = Ok("All good");
     err.expect_err("Got expected ok");
diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs
index 31d16e0..ac9c17a 100644
--- a/src/libcore/tests/slice.rs
+++ b/src/libcore/tests/slice.rs
@@ -782,7 +782,6 @@
     //  to be used in `should_panic`)
     #[test]
     #[should_panic(expected = "out of range")]
-    #[cfg(not(miri))] // Miri does not support panics
     fn assert_range_eq_can_fail_by_panic() {
         assert_range_eq!([0, 1, 2], 0..5, [0, 1, 2]);
     }
@@ -792,7 +791,6 @@
     //  to be used in `should_panic`)
     #[test]
     #[should_panic(expected = "==")]
-    #[cfg(not(miri))] // Miri does not support panics
     fn assert_range_eq_can_fail_by_inequality() {
         assert_range_eq!([0, 1, 2], 0..2, [0, 1, 2]);
     }
@@ -842,7 +840,6 @@
 
                 #[test]
                 #[should_panic(expected = $expect_msg)]
-                #[cfg(not(miri))] // Miri does not support panics
                 fn index_fail() {
                     let v = $data;
                     let v: &[_] = &v;
@@ -851,7 +848,6 @@
 
                 #[test]
                 #[should_panic(expected = $expect_msg)]
-                #[cfg(not(miri))] // Miri does not support panics
                 fn index_mut_fail() {
                     let mut v = $data;
                     let v: &mut [_] = &mut v;
@@ -1304,7 +1300,6 @@
 
 #[test]
 #[should_panic(expected = "src is out of bounds")]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_copy_within_panics_src_too_long() {
     let mut bytes = *b"Hello, World!";
     // The length is only 13, so 14 is out of bounds.
@@ -1313,7 +1308,6 @@
 
 #[test]
 #[should_panic(expected = "dest is out of bounds")]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_copy_within_panics_dest_too_long() {
     let mut bytes = *b"Hello, World!";
     // The length is only 13, so a slice of length 4 starting at index 10 is out of bounds.
@@ -1321,7 +1315,6 @@
 }
 #[test]
 #[should_panic(expected = "src end is before src start")]
-#[cfg(not(miri))] // Miri does not support panics
 fn test_copy_within_panics_src_inverted() {
     let mut bytes = *b"Hello, World!";
     // 2 is greater than 1, so this range is invalid.
diff --git a/src/libcore/tests/time.rs b/src/libcore/tests/time.rs
index 09aae45..6efd225 100644
--- a/src/libcore/tests/time.rs
+++ b/src/libcore/tests/time.rs
@@ -107,14 +107,12 @@
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn sub_bad1() {
     let _ = Duration::new(0, 0) - Duration::new(0, 1);
 }
 
 #[test]
 #[should_panic]
-#[cfg(not(miri))] // Miri does not support panics
 fn sub_bad2() {
     let _ = Duration::new(0, 0) - Duration::new(1, 0);
 }
diff --git a/src/libcore/time.rs b/src/libcore/time.rs
index 91161ca..ae6d807 100644
--- a/src/libcore/time.rs
+++ b/src/libcore/time.rs
@@ -21,7 +21,6 @@
 const NANOS_PER_MICRO: u32 = 1_000;
 const MILLIS_PER_SEC: u64 = 1_000;
 const MICROS_PER_SEC: u64 = 1_000_000;
-const MAX_NANOS_F64: f64 = ((u64::MAX as u128 + 1)*(NANOS_PER_SEC as u128)) as f64;
 
 /// A `Duration` type to represent a span of time, typically used for system
 /// timeouts.
@@ -510,15 +509,34 @@
     /// use std::time::Duration;
     ///
     /// let dur = Duration::new(2, 700_000_000);
-    /// assert_eq!(dur.as_float_secs(), 2.7);
+    /// assert_eq!(dur.as_secs_f64(), 2.7);
     /// ```
     #[unstable(feature = "duration_float", issue = "54361")]
     #[inline]
-    pub const fn as_float_secs(&self) -> f64 {
+    pub const fn as_secs_f64(&self) -> f64 {
         (self.secs as f64) + (self.nanos as f64) / (NANOS_PER_SEC as f64)
     }
 
-    /// Creates a new `Duration` from the specified number of seconds.
+    /// Returns the number of seconds contained by this `Duration` as `f32`.
+    ///
+    /// The returned value does include the fractional (nanosecond) part of the duration.
+    ///
+    /// # Examples
+    /// ```
+    /// #![feature(duration_float)]
+    /// use std::time::Duration;
+    ///
+    /// let dur = Duration::new(2, 700_000_000);
+    /// assert_eq!(dur.as_secs_f32(), 2.7);
+    /// ```
+    #[unstable(feature = "duration_float", issue = "54361")]
+    #[inline]
+    pub const fn as_secs_f32(&self) -> f32 {
+        (self.secs as f32) + (self.nanos as f32) / (NANOS_PER_SEC as f32)
+    }
+
+    /// Creates a new `Duration` from the specified number of seconds represented
+    /// as `f64`.
     ///
     /// # Panics
     /// This constructor will panic if `secs` is not finite, negative or overflows `Duration`.
@@ -528,12 +546,14 @@
     /// #![feature(duration_float)]
     /// use std::time::Duration;
     ///
-    /// let dur = Duration::from_float_secs(2.7);
+    /// let dur = Duration::from_secs_f64(2.7);
     /// assert_eq!(dur, Duration::new(2, 700_000_000));
     /// ```
     #[unstable(feature = "duration_float", issue = "54361")]
     #[inline]
-    pub fn from_float_secs(secs: f64) -> Duration {
+    pub fn from_secs_f64(secs: f64) -> Duration {
+        const MAX_NANOS_F64: f64 =
+            ((u64::MAX as u128 + 1)*(NANOS_PER_SEC as u128)) as f64;
         let nanos =  secs * (NANOS_PER_SEC as f64);
         if !nanos.is_finite() {
             panic!("got non-finite value when converting float to duration");
@@ -551,6 +571,42 @@
         }
     }
 
+    /// Creates a new `Duration` from the specified number of seconds represented
+    /// as `f32`.
+    ///
+    /// # Panics
+    /// This constructor will panic if `secs` is not finite, negative or overflows `Duration`.
+    ///
+    /// # Examples
+    /// ```
+    /// #![feature(duration_float)]
+    /// use std::time::Duration;
+    ///
+    /// let dur = Duration::from_secs_f32(2.7);
+    /// assert_eq!(dur, Duration::new(2, 700_000_000));
+    /// ```
+    #[unstable(feature = "duration_float", issue = "54361")]
+    #[inline]
+    pub fn from_secs_f32(secs: f32) -> Duration {
+        const MAX_NANOS_F32: f32 =
+            ((u64::MAX as u128 + 1)*(NANOS_PER_SEC as u128)) as f32;
+        let nanos =  secs * (NANOS_PER_SEC as f32);
+        if !nanos.is_finite() {
+            panic!("got non-finite value when converting float to duration");
+        }
+        if nanos >= MAX_NANOS_F32 {
+            panic!("overflow when converting float to duration");
+        }
+        if nanos < 0.0 {
+            panic!("underflow when converting float to duration");
+        }
+        let nanos =  nanos as u128;
+        Duration {
+            secs: (nanos / (NANOS_PER_SEC as u128)) as u64,
+            nanos: (nanos % (NANOS_PER_SEC as u128)) as u32,
+        }
+    }
+
     /// Multiplies `Duration` by `f64`.
     ///
     /// # Panics
@@ -568,7 +624,29 @@
     #[unstable(feature = "duration_float", issue = "54361")]
     #[inline]
     pub fn mul_f64(self, rhs: f64) -> Duration {
-        Duration::from_float_secs(rhs * self.as_float_secs())
+        Duration::from_secs_f64(rhs * self.as_secs_f64())
+    }
+
+    /// Multiplies `Duration` by `f32`.
+    ///
+    /// # Panics
+    /// This method will panic if result is not finite, negative or overflows `Duration`.
+    ///
+    /// # Examples
+    /// ```
+    /// #![feature(duration_float)]
+    /// use std::time::Duration;
+    ///
+    /// let dur = Duration::new(2, 700_000_000);
+    /// // note that due to rounding errors result is slightly different
+    /// // from 8.478 and 847800.0
+    /// assert_eq!(dur.mul_f32(3.14), Duration::new(8, 478_000_640));
+    /// assert_eq!(dur.mul_f32(3.14e5), Duration::new(847799, 969_120_256));
+    /// ```
+    #[unstable(feature = "duration_float", issue = "54361")]
+    #[inline]
+    pub fn mul_f32(self, rhs: f32) -> Duration {
+        Duration::from_secs_f32(rhs * self.as_secs_f32())
     }
 
     /// Divide `Duration` by `f64`.
@@ -589,7 +667,30 @@
     #[unstable(feature = "duration_float", issue = "54361")]
     #[inline]
     pub fn div_f64(self, rhs: f64) -> Duration {
-        Duration::from_float_secs(self.as_float_secs() / rhs)
+        Duration::from_secs_f64(self.as_secs_f64() / rhs)
+    }
+
+    /// Divide `Duration` by `f32`.
+    ///
+    /// # Panics
+    /// This method will panic if result is not finite, negative or overflows `Duration`.
+    ///
+    /// # Examples
+    /// ```
+    /// #![feature(duration_float)]
+    /// use std::time::Duration;
+    ///
+    /// let dur = Duration::new(2, 700_000_000);
+    /// // note that due to rounding errors result is slightly
+    /// // different from 0.859_872_611
+    /// assert_eq!(dur.div_f32(3.14), Duration::new(0, 859_872_576));
+    /// // note that truncation is used, not rounding
+    /// assert_eq!(dur.div_f32(3.14e5), Duration::new(0, 8_598));
+    /// ```
+    #[unstable(feature = "duration_float", issue = "54361")]
+    #[inline]
+    pub fn div_f32(self, rhs: f32) -> Duration {
+        Duration::from_secs_f32(self.as_secs_f32() / rhs)
     }
 
     /// Divide `Duration` by `Duration` and return `f64`.
@@ -601,12 +702,29 @@
     ///
     /// let dur1 = Duration::new(2, 700_000_000);
     /// let dur2 = Duration::new(5, 400_000_000);
-    /// assert_eq!(dur1.div_duration(dur2), 0.5);
+    /// assert_eq!(dur1.div_duration_f64(dur2), 0.5);
     /// ```
     #[unstable(feature = "duration_float", issue = "54361")]
     #[inline]
-    pub fn div_duration(self, rhs: Duration) -> f64 {
-        self.as_float_secs() / rhs.as_float_secs()
+    pub fn div_duration_f64(self, rhs: Duration) -> f64 {
+        self.as_secs_f64() / rhs.as_secs_f64()
+    }
+
+    /// Divide `Duration` by `Duration` and return `f32`.
+    ///
+    /// # Examples
+    /// ```
+    /// #![feature(duration_float)]
+    /// use std::time::Duration;
+    ///
+    /// let dur1 = Duration::new(2, 700_000_000);
+    /// let dur2 = Duration::new(5, 400_000_000);
+    /// assert_eq!(dur1.div_duration_f32(dur2), 0.5);
+    /// ```
+    #[unstable(feature = "duration_float", issue = "54361")]
+    #[inline]
+    pub fn div_duration_f32(self, rhs: Duration) -> f32 {
+        self.as_secs_f32() / rhs.as_secs_f32()
     }
 }
 
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 41a4a80..43e865a 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -423,7 +423,7 @@
     }
 }
 
-define_dep_nodes!( <'tcx>
+rustc_dep_node_append!([define_dep_nodes!][ <'tcx>
     // We use this for most things when incr. comp. is turned off.
     [] Null,
 
@@ -492,9 +492,6 @@
     // table in the tcx (or elsewhere) maps to one of these
     // nodes.
     [] AssociatedItems(DefId),
-    [] TypeOfItem(DefId),
-    [] GenericsOfItem(DefId),
-    [] PredicatesOfItem(DefId),
     [] ExplicitPredicatesOfItem(DefId),
     [] PredicatesDefinedOnItem(DefId),
     [] InferredOutlivesOf(DefId),
@@ -570,7 +567,6 @@
     [] FnArgNames(DefId),
     [] RenderedConst(DefId),
     [] DylibDepFormats(CrateNum),
-    [] IsPanicRuntime(CrateNum),
     [] IsCompilerBuiltins(CrateNum),
     [] HasGlobalAllocator(CrateNum),
     [] HasPanicHandler(CrateNum),
@@ -588,7 +584,6 @@
     [] CheckTraitItemWellFormed(DefId),
     [] CheckImplItemWellFormed(DefId),
     [] ReachableNonGenerics(CrateNum),
-    [] NativeLibraries(CrateNum),
     [] EntryFn(CrateNum),
     [] PluginRegistrarFn(CrateNum),
     [] ProcMacroDeclsStatic(CrateNum),
@@ -679,7 +674,23 @@
 
     [] UpstreamMonomorphizations(CrateNum),
     [] UpstreamMonomorphizationsFor(DefId),
-);
+]);
+
+pub trait RecoverKey<'tcx>: Sized {
+    fn recover(tcx: TyCtxt<'_, 'tcx, 'tcx>, dep_node: &DepNode) -> Option<Self>;
+}
+
+impl RecoverKey<'tcx> for CrateNum {
+    fn recover(tcx: TyCtxt<'_, 'tcx, 'tcx>, dep_node: &DepNode) -> Option<Self> {
+        dep_node.extract_def_id(tcx).map(|id| id.krate)
+    }
+}
+
+impl RecoverKey<'tcx> for DefId {
+    fn recover(tcx: TyCtxt<'_, 'tcx, 'tcx>, dep_node: &DepNode) -> Option<Self> {
+        dep_node.extract_def_id(tcx)
+    }
+}
 
 trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug {
     const CAN_RECONSTRUCT_QUERY_KEY: bool;
@@ -724,7 +735,7 @@
     }
 
     fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String {
-        tcx.item_path_str(*self)
+        tcx.def_path_str(*self)
     }
 }
 
@@ -736,7 +747,7 @@
     }
 
     fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String {
-        tcx.item_path_str(DefId::local(*self))
+        tcx.def_path_str(DefId::local(*self))
     }
 }
 
diff --git a/src/librustc/dep_graph/mod.rs b/src/librustc/dep_graph/mod.rs
index b84d2ad..1535e6d 100644
--- a/src/librustc/dep_graph/mod.rs
+++ b/src/librustc/dep_graph/mod.rs
@@ -9,7 +9,7 @@
 pub mod cgu_reuse_tracker;
 
 pub use self::dep_tracking_map::{DepTrackingMap, DepTrackingMapConfig};
-pub use self::dep_node::{DepNode, DepKind, DepConstructor, WorkProductId, label_strs};
+pub use self::dep_node::{DepNode, DepKind, DepConstructor, WorkProductId, RecoverKey, label_strs};
 pub use self::graph::{DepGraph, WorkProduct, DepNodeIndex, DepNodeColor, TaskDeps, hash_result};
 pub use self::graph::WorkProductFileKind;
 pub use self::prev::PreviousDepGraph;
diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs
index 86f7e14..8602d15 100644
--- a/src/librustc/hir/check_attr.rs
+++ b/src/librustc/hir/check_attr.rs
@@ -166,7 +166,7 @@
         // ```
         let hints: Vec<_> = item.attrs
             .iter()
-            .filter(|attr| attr.name() == "repr")
+            .filter(|attr| attr.check_name("repr"))
             .filter_map(|attr| attr.meta_item_list())
             .flatten()
             .collect();
@@ -177,7 +177,7 @@
         let mut is_transparent = false;
 
         for hint in &hints {
-            let name = if let Some(name) = hint.name() {
+            let name = if let Some(name) = hint.ident_str() {
                 name
             } else {
                 // Invalid repr hint like repr(42). We don't check for unrecognized hints here
@@ -185,7 +185,7 @@
                 continue;
             };
 
-            let (article, allowed_targets) = match &*name.as_str() {
+            let (article, allowed_targets) = match name {
                 "C" | "align" => {
                     is_c |= name == "C";
                     if target != Target::Struct &&
@@ -233,7 +233,7 @@
                 _ => continue,
             };
             self.emit_repr_error(
-                hint.span,
+                hint.span(),
                 item.span,
                 &format!("attribute should be applied to {}", allowed_targets),
                 &format!("not {} {}", article, allowed_targets),
@@ -242,7 +242,7 @@
 
         // Just point at all repr hints if there are any incompatibilities.
         // This is not ideal, but tracking precisely which ones are at fault is a huge hassle.
-        let hint_spans = hints.iter().map(|hint| hint.span);
+        let hint_spans = hints.iter().map(|hint| hint.span());
 
         // Error on repr(transparent, <anything else>).
         if is_transparent && hints.len() > 1 {
@@ -313,7 +313,7 @@
 
     fn check_used(&self, item: &hir::Item, target: Target) {
         for attr in &item.attrs {
-            if attr.name() == "used" && target != Target::Static {
+            if attr.check_name("used") && target != Target::Static {
                 self.tcx.sess
                     .span_err(attr.span, "attribute must be applied to a `static` variable");
             }
diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs
index ed1c15a..397843f 100644
--- a/src/librustc/hir/def_id.rs
+++ b/src/librustc/hir/def_id.rs
@@ -249,7 +249,7 @@
         if self.is_local() && self.index == CRATE_DEF_INDEX {
             format!("top-level module")
         } else {
-            format!("module `{}`", tcx.item_path_str(*self))
+            format!("module `{}`", tcx.def_path_str(*self))
         }
     }
 }
diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs
index f454d69..dca4ce4 100644
--- a/src/librustc/hir/map/definitions.rs
+++ b/src/librustc/hir/map/definitions.rs
@@ -679,13 +679,13 @@
                 return name
             }
             // note that this does not show up in user printouts
-            CrateRoot => "{{root}}",
+            CrateRoot => "{{crate}}",
             Impl => "{{impl}}",
-            Misc => "{{?}}",
+            Misc => "{{misc}}",
             ClosureExpr => "{{closure}}",
             StructCtor => "{{constructor}}",
             AnonConst => "{{constant}}",
-            ImplTrait => "{{impl-Trait}}",
+            ImplTrait => "{{opaque}}",
         };
 
         Symbol::intern(s).as_interned_str()
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 747e65f..151c541 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -541,7 +541,8 @@
 
     pub fn ty_param_owner(&self, id: HirId) -> HirId {
         match self.get_by_hir_id(id) {
-            Node::Item(&Item { node: ItemKind::Trait(..), .. }) => id,
+            Node::Item(&Item { node: ItemKind::Trait(..), .. }) |
+            Node::Item(&Item { node: ItemKind::TraitAlias(..), .. }) => id,
             Node::GenericParam(_) => self.get_parent_node_by_hir_id(id),
             _ => bug!("ty_param_owner: {} not a type parameter", self.hir_to_string(id))
         }
@@ -549,7 +550,8 @@
 
     pub fn ty_param_name(&self, id: HirId) -> Name {
         match self.get_by_hir_id(id) {
-            Node::Item(&Item { node: ItemKind::Trait(..), .. }) => keywords::SelfUpper.name(),
+            Node::Item(&Item { node: ItemKind::Trait(..), .. }) |
+            Node::Item(&Item { node: ItemKind::TraitAlias(..), .. }) => keywords::SelfUpper.name(),
             Node::GenericParam(param) => param.name.ident().name,
             _ => bug!("ty_param_name: {} not a type parameter", self.hir_to_string(id)),
         }
@@ -1351,7 +1353,8 @@
         // the user-friendly path, otherwise fall back to stringifying DefPath.
         crate::ty::tls::with_opt(|tcx| {
             if let Some(tcx) = tcx {
-                tcx.node_path_str(id)
+                let def_id = map.local_def_id(id);
+                tcx.def_path_str(def_id)
             } else if let Some(path) = map.def_path_from_id(id) {
                 path.data.into_iter().map(|elem| {
                     elem.data.to_string()
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index 54a21f2..bff4190 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -591,12 +591,12 @@
                 self.s.word(";")?;
                 self.end()?; // end the outer cbox
             }
-            hir::ItemKind::Fn(ref decl, header, ref typarams, body) => {
+            hir::ItemKind::Fn(ref decl, header, ref param_names, body) => {
                 self.head("")?;
                 self.print_fn(decl,
                               header,
                               Some(item.ident.name),
-                              typarams,
+                              param_names,
                               &item.vis,
                               &[],
                               Some(body))?;
diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs
index f34423c..496ccc8 100644
--- a/src/librustc/ich/impls_syntax.rs
+++ b/src/librustc/ich/impls_syntax.rs
@@ -197,7 +197,8 @@
         let filtered: SmallVec<[&ast::Attribute; 8]> = self
             .iter()
             .filter(|attr| {
-                !attr.is_sugared_doc && !hcx.is_ignored_attr(attr.name())
+                !attr.is_sugared_doc &&
+                !attr.ident().map_or(false, |ident| hcx.is_ignored_attr(ident.name))
             })
             .collect();
 
@@ -224,7 +225,7 @@
                                           hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         // Make sure that these have been filtered out.
-        debug_assert!(!hcx.is_ignored_attr(self.name()));
+        debug_assert!(!self.ident().map_or(false, |ident| hcx.is_ignored_attr(ident.name)));
         debug_assert!(!self.is_sugared_doc);
 
         let ast::Attribute {
@@ -359,15 +360,13 @@
     }
 }
 
-impl_stable_hash_for_spanned!(::syntax::ast::NestedMetaItemKind);
-
-impl_stable_hash_for!(enum ::syntax::ast::NestedMetaItemKind {
+impl_stable_hash_for!(enum ::syntax::ast::NestedMetaItem {
     MetaItem(meta_item),
     Literal(lit)
 });
 
 impl_stable_hash_for!(struct ::syntax::ast::MetaItem {
-    ident,
+    path,
     node,
     span
 });
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index c793653..2810b5a 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -223,7 +223,7 @@
                     self.hir().span_by_hir_id(node),
                 ),
                 _ => (
-                    format!("the lifetime {} as defined on", fr.bound_region),
+                    format!("the lifetime {} as defined on", region),
                     cm.def_span(self.hir().span_by_hir_id(node)),
                 ),
             },
@@ -444,17 +444,109 @@
         terr: &TypeError<'tcx>,
         sp: Span,
     ) {
+        use hir::def_id::CrateNum;
+        use hir::map::DisambiguatedDefPathData;
+        use ty::print::Printer;
+        use ty::subst::Kind;
+
+        struct AbsolutePathPrinter<'a, 'gcx, 'tcx> {
+            tcx: TyCtxt<'a, 'gcx, 'tcx>,
+        }
+
+        struct NonTrivialPath;
+
+        impl<'gcx, 'tcx> Printer<'gcx, 'tcx> for AbsolutePathPrinter<'_, 'gcx, 'tcx> {
+            type Error = NonTrivialPath;
+
+            type Path = Vec<String>;
+            type Region = !;
+            type Type = !;
+            type DynExistential = !;
+
+            fn tcx<'a>(&'a self) -> TyCtxt<'a, 'gcx, 'tcx> {
+                self.tcx
+            }
+
+            fn print_region(
+                self,
+                _region: ty::Region<'_>,
+            ) -> Result<Self::Region, Self::Error> {
+                Err(NonTrivialPath)
+            }
+
+            fn print_type(
+                self,
+                _ty: Ty<'tcx>,
+            ) -> Result<Self::Type, Self::Error> {
+                Err(NonTrivialPath)
+            }
+
+            fn print_dyn_existential(
+                self,
+                _predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
+            ) -> Result<Self::DynExistential, Self::Error> {
+                Err(NonTrivialPath)
+            }
+
+            fn path_crate(
+                self,
+                cnum: CrateNum,
+            ) -> Result<Self::Path, Self::Error> {
+                Ok(vec![self.tcx.original_crate_name(cnum).to_string()])
+            }
+            fn path_qualified(
+                self,
+                _self_ty: Ty<'tcx>,
+                _trait_ref: Option<ty::TraitRef<'tcx>>,
+            ) -> Result<Self::Path, Self::Error> {
+                Err(NonTrivialPath)
+            }
+
+            fn path_append_impl(
+                self,
+                _print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+                _disambiguated_data: &DisambiguatedDefPathData,
+                _self_ty: Ty<'tcx>,
+                _trait_ref: Option<ty::TraitRef<'tcx>>,
+            ) -> Result<Self::Path, Self::Error> {
+                Err(NonTrivialPath)
+            }
+            fn path_append(
+                self,
+                print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+                disambiguated_data: &DisambiguatedDefPathData,
+            ) -> Result<Self::Path, Self::Error> {
+                let mut path = print_prefix(self)?;
+                path.push(disambiguated_data.data.as_interned_str().to_string());
+                Ok(path)
+            }
+            fn path_generic_args(
+                self,
+                print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+                _args: &[Kind<'tcx>],
+            ) -> Result<Self::Path, Self::Error> {
+                print_prefix(self)
+            }
+        }
+
         let report_path_match = |err: &mut DiagnosticBuilder<'_>, did1: DefId, did2: DefId| {
             // Only external crates, if either is from a local
             // module we could have false positives
             if !(did1.is_local() || did2.is_local()) && did1.krate != did2.krate {
-                let exp_path = self.tcx.item_path_str(did1);
-                let found_path = self.tcx.item_path_str(did2);
-                let exp_abs_path = self.tcx.absolute_item_path_str(did1);
-                let found_abs_path = self.tcx.absolute_item_path_str(did2);
+                let abs_path = |def_id| {
+                    AbsolutePathPrinter { tcx: self.tcx }
+                        .print_def_path(def_id, &[])
+                };
+
                 // We compare strings because DefPath can be different
                 // for imported and non-imported crates
-                if exp_path == found_path || exp_abs_path == found_abs_path {
+                let same_path = || -> Result<_, NonTrivialPath> {
+                    Ok(
+                        self.tcx.def_path_str(did1) == self.tcx.def_path_str(did2) ||
+                        abs_path(did1)? == abs_path(did2)?
+                    )
+                };
+                if same_path().unwrap_or(false) {
                     let crate_name = self.tcx.crate_name(did1.krate);
                     err.span_note(
                         sp,
@@ -658,7 +750,7 @@
                 return Some(());
             }
             if let &ty::Adt(def, _) = &ta.sty {
-                let path_ = self.tcx.item_path_str(def.did.clone());
+                let path_ = self.tcx.def_path_str(def.did.clone());
                 if path_ == other_path {
                     self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, &other_ty);
                     return Some(());
@@ -683,7 +775,7 @@
     }
 
     /// For generic types with parameters with defaults, remove the parameters corresponding to
-    /// the defaults. This repeats a lot of the logic found in `PrintContext::parameterized`.
+    /// the defaults. This repeats a lot of the logic found in `ty::print::pretty`.
     fn strip_generic_default_params(
         &self,
         def_id: DefId,
@@ -742,11 +834,15 @@
             mutbl: hir::Mutability,
             s: &mut DiagnosticStyledString,
         ) {
-            let r = &r.to_string();
+            let mut r = r.to_string();
+            if r == "'_" {
+                r.clear();
+            } else {
+                r.push(' ');
+            }
             s.push_highlighted(format!(
-                "&{}{}{}",
+                "&{}{}",
                 r,
-                if r == "" { "" } else { " " },
                 if mutbl == hir::MutMutable { "mut " } else { "" }
             ));
             s.push_normal(ty.to_string());
@@ -757,8 +853,8 @@
                 let sub_no_defaults_1 = self.strip_generic_default_params(def1.did, sub1);
                 let sub_no_defaults_2 = self.strip_generic_default_params(def2.did, sub2);
                 let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
-                let path1 = self.tcx.item_path_str(def1.did.clone());
-                let path2 = self.tcx.item_path_str(def2.did.clone());
+                let path1 = self.tcx.def_path_str(def1.did.clone());
+                let path2 = self.tcx.def_path_str(def2.did.clone());
                 if def1.did == def2.did {
                     // Easy case. Replace same types with `_` to shorten the output and highlight
                     // the differing ones.
@@ -1013,7 +1109,7 @@
                             if exp_is_struct && &exp_found.expected == ret_ty.skip_binder() {
                                 let message = format!(
                                     "did you mean `{}(/* fields */)`?",
-                                    self.tcx.item_path_str(def_id)
+                                    self.tcx.def_path_str(def_id)
                                 );
                                 diag.span_label(span, message);
                             }
@@ -1425,7 +1521,10 @@
         var_origin: RegionVariableOrigin,
     ) -> DiagnosticBuilder<'tcx> {
         let br_string = |br: ty::BoundRegion| {
-            let mut s = br.to_string();
+            let mut s = match br {
+                ty::BrNamed(_, name) => name.to_string(),
+                _ => String::new(),
+            };
             if !s.is_empty() {
                 s.push_str(" ");
             }
diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs
index 9e0e48e..0a83b83 100644
--- a/src/librustc/infer/error_reporting/need_type_info.rs
+++ b/src/librustc/infer/error_reporting/need_type_info.rs
@@ -1,8 +1,10 @@
+use crate::hir::def::Namespace;
 use crate::hir::{self, Local, Pat, Body, HirId};
 use crate::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use crate::infer::InferCtxt;
 use crate::infer::type_variable::TypeVariableOrigin;
 use crate::ty::{self, Ty, Infer, TyVar};
+use crate::ty::print::Print;
 use syntax::source_map::CompilerDesugaringKind;
 use syntax_pos::Span;
 use errors::DiagnosticBuilder;
@@ -64,18 +66,26 @@
 
 
 impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
-    pub fn extract_type_name(&self, ty: &'a Ty<'tcx>) -> String {
+    pub fn extract_type_name(
+        &self,
+        ty: &'a Ty<'tcx>,
+        highlight: Option<ty::print::RegionHighlightMode>,
+    ) -> String {
         if let ty::Infer(ty::TyVar(ty_vid)) = (*ty).sty {
             let ty_vars = self.type_variables.borrow();
             if let TypeVariableOrigin::TypeParameterDefinition(_, name) =
                 *ty_vars.var_origin(ty_vid) {
-                name.to_string()
-            } else {
-                ty.to_string()
+                return name.to_string();
             }
-        } else {
-            ty.to_string()
         }
+
+        let mut s = String::new();
+        let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
+        if let Some(highlight) = highlight {
+            printer.region_highlight_mode = highlight;
+        }
+        let _ = ty.print(printer);
+        s
     }
 
     pub fn need_type_info_err(&self,
@@ -84,7 +94,7 @@
                             ty: Ty<'tcx>)
                             -> DiagnosticBuilder<'gcx> {
         let ty = self.resolve_type_vars_if_possible(&ty);
-        let name = self.extract_type_name(&ty);
+        let name = self.extract_type_name(&ty, None);
 
         let mut err_span = span;
         let mut labels = vec![(
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 506388c..e708454 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
@@ -1,14 +1,17 @@
 use errors::DiagnosticBuilder;
+use crate::hir::def::Namespace;
 use crate::hir::def_id::DefId;
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::infer::lexical_region_resolve::RegionResolutionError;
 use crate::infer::ValuePairs;
 use crate::infer::{SubregionOrigin, TypeTrace};
 use crate::traits::{ObligationCause, ObligationCauseCode};
-use crate::ty;
+use crate::ty::{self, TyCtxt};
 use crate::ty::error::ExpectedFound;
 use crate::ty::subst::SubstsRef;
-use crate::util::ppaux::RegionHighlightMode;
+use crate::ty::print::{Print, RegionHighlightMode, FmtPrinter};
+
+use std::fmt::{self, Write};
 
 impl NiceRegionError<'me, 'gcx, 'tcx> {
     /// When given a `ConcreteFailure` for a function with arguments containing a named region and
@@ -193,7 +196,7 @@
             cause.span(&self.tcx()),
             &format!(
                 "implementation of `{}` is not general enough",
-                self.tcx().item_path_str(trait_def_id),
+                self.tcx().def_path_str(trait_def_id),
             ),
         );
 
@@ -201,7 +204,7 @@
             ObligationCauseCode::ItemObligation(def_id) => {
                 err.note(&format!(
                     "Due to a where-clause on `{}`,",
-                    self.tcx().item_path_str(def_id),
+                    self.tcx().def_path_str(def_id),
                 ));
             }
             _ => (),
@@ -309,13 +312,46 @@
         sup_placeholder: Option<ty::Region<'tcx>>,
         has_sub: Option<usize>,
         has_sup: Option<usize>,
-        expected_trait_ref: ty::TraitRef<'_>,
-        actual_trait_ref: ty::TraitRef<'_>,
+        expected_trait_ref: ty::TraitRef<'tcx>,
+        actual_trait_ref: ty::TraitRef<'tcx>,
         vid: Option<ty::Region<'tcx>>,
         expected_has_vid: Option<usize>,
         actual_has_vid: Option<usize>,
         any_self_ty_has_vid: bool,
     ) {
+        // HACK(eddyb) maybe move this in a more central location.
+        #[derive(Copy, Clone)]
+        struct Highlighted<'a, 'gcx, 'tcx, T> {
+            tcx: TyCtxt<'a, 'gcx, 'tcx>,
+            highlight: RegionHighlightMode,
+            value: T,
+        }
+
+        impl<'a, 'gcx, 'tcx, T> Highlighted<'a, 'gcx, 'tcx, T> {
+            fn map<U>(self, f: impl FnOnce(T) -> U) -> Highlighted<'a, 'gcx, 'tcx, U> {
+                Highlighted {
+                    tcx: self.tcx,
+                    highlight: self.highlight,
+                    value: f(self.value),
+                }
+            }
+        }
+
+        impl<'a, 'gcx, 'tcx, T> fmt::Display for Highlighted<'a, 'gcx, 'tcx, T>
+            where T: for<'b, 'c> Print<'gcx, 'tcx,
+                FmtPrinter<'a, 'gcx, 'tcx, &'b mut fmt::Formatter<'c>>,
+                Error = fmt::Error,
+            >,
+        {
+            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                let mut printer = ty::print::FmtPrinter::new(self.tcx, f, Namespace::TypeNS);
+                printer.region_highlight_mode = self.highlight;
+
+                self.value.print(printer)?;
+                Ok(())
+            }
+        }
+
         // The weird thing here with the `maybe_highlighting_region` calls and the
         // the match inside is meant to be like this:
         //
@@ -331,112 +367,93 @@
         // None, an then we check again inside the closure, but this
         // setup sort of minimized the number of calls and so form.
 
-        RegionHighlightMode::maybe_highlighting_region(sub_placeholder, has_sub, || {
-            RegionHighlightMode::maybe_highlighting_region(sup_placeholder, has_sup, || {
-                match (has_sub, has_sup) {
-                    (Some(n1), Some(n2)) => {
-                        if any_self_ty_has_vid {
-                            err.note(&format!(
-                                "`{}` would have to be implemented for the type `{}`, \
-                                 for any two lifetimes `'{}` and `'{}`",
-                                expected_trait_ref,
-                                expected_trait_ref.self_ty(),
-                                std::cmp::min(n1, n2),
-                                std::cmp::max(n1, n2),
-                            ));
-                        } else {
-                            err.note(&format!(
-                                "`{}` must implement `{}`, \
-                                 for any two lifetimes `'{}` and `'{}`",
-                                expected_trait_ref.self_ty(),
-                                expected_trait_ref,
-                                std::cmp::min(n1, n2),
-                                std::cmp::max(n1, n2),
-                            ));
-                        }
+        let highlight_trait_ref = |trait_ref| Highlighted {
+            tcx: self.tcx(),
+            highlight: RegionHighlightMode::default(),
+            value: trait_ref,
+        };
+
+        let mut expected_trait_ref = highlight_trait_ref(expected_trait_ref);
+        expected_trait_ref.highlight.maybe_highlighting_region(sub_placeholder, has_sub);
+        expected_trait_ref.highlight.maybe_highlighting_region(sup_placeholder, has_sup);
+        err.note(&{
+            let passive_voice = match (has_sub, has_sup) {
+                (Some(_), _) | (_, Some(_)) => any_self_ty_has_vid,
+                (None, None) => {
+                    expected_trait_ref.highlight.maybe_highlighting_region(vid, expected_has_vid);
+                    match expected_has_vid {
+                        Some(_) => true,
+                        None => any_self_ty_has_vid,
                     }
-                    (Some(n), _) | (_, Some(n)) => {
-                        if any_self_ty_has_vid {
-                            err.note(&format!(
-                                "`{}` would have to be implemented for the type `{}`, \
-                                 for any lifetime `'{}`",
-                                expected_trait_ref,
-                                expected_trait_ref.self_ty(),
-                                n,
-                            ));
-                        } else {
-                            err.note(&format!(
-                                "`{}` must implement `{}`, for any lifetime `'{}`",
-                                expected_trait_ref.self_ty(),
-                                expected_trait_ref,
-                                n,
-                            ));
-                        }
-                    }
-                    (None, None) => RegionHighlightMode::maybe_highlighting_region(
-                        vid,
-                        expected_has_vid,
-                        || {
-                            if let Some(n) = expected_has_vid {
-                                err.note(&format!(
-                                    "`{}` would have to be implemented for the type `{}`, \
-                                     for some specific lifetime `'{}`",
-                                    expected_trait_ref,
-                                    expected_trait_ref.self_ty(),
-                                    n,
-                                ));
-                            } else {
-                                if any_self_ty_has_vid {
-                                    err.note(&format!(
-                                        "`{}` would have to be implemented for the type `{}`",
-                                        expected_trait_ref,
-                                        expected_trait_ref.self_ty(),
-                                    ));
-                                } else {
-                                    err.note(&format!(
-                                        "`{}` must implement `{}`",
-                                        expected_trait_ref.self_ty(),
-                                        expected_trait_ref,
-                                    ));
-                                }
-                            }
-                        },
-                    ),
                 }
-            })
+            };
+
+            let mut note = if passive_voice {
+                format!(
+                    "`{}` would have to be implemented for the type `{}`",
+                    expected_trait_ref,
+                    expected_trait_ref.map(|tr| tr.self_ty()),
+                )
+            } else {
+                format!(
+                    "`{}` must implement `{}`",
+                    expected_trait_ref.map(|tr| tr.self_ty()),
+                    expected_trait_ref,
+                )
+            };
+
+            match (has_sub, has_sup) {
+                (Some(n1), Some(n2)) => {
+                    let _ = write!(note,
+                        ", 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 `'{}`",
+                        n,
+                    );
+                }
+                (None, None) => if let Some(n) = expected_has_vid {
+                    let _ = write!(note,
+                        ", for some specific lifetime `'{}`",
+                        n,
+                    );
+                },
+            }
+
+            note
         });
 
-        RegionHighlightMode::maybe_highlighting_region(
-            vid,
-            actual_has_vid,
-            || match actual_has_vid {
-                Some(n) => {
-                    if any_self_ty_has_vid {
-                        err.note(&format!(
-                            "but `{}` is actually implemented for the type `{}`, \
-                             for some specific lifetime `'{}`",
-                            actual_trait_ref,
-                            actual_trait_ref.self_ty(),
-                            n
-                        ));
-                    } else {
-                        err.note(&format!(
-                            "but `{}` actually implements `{}`, for some specific lifetime `'{}`",
-                            actual_trait_ref.self_ty(),
-                            actual_trait_ref,
-                            n
-                        ));
-                    }
-                }
+        let mut actual_trait_ref = highlight_trait_ref(actual_trait_ref);
+        actual_trait_ref.highlight.maybe_highlighting_region(vid, actual_has_vid);
+        err.note(&{
+            let passive_voice = match actual_has_vid {
+                Some(_) => any_self_ty_has_vid,
+                None => true,
+            };
 
-                _ => {
-                    err.note(&format!(
-                        "but `{}` is actually implemented for the type `{}`",
-                        actual_trait_ref,
-                        actual_trait_ref.self_ty(),
-                    ));
-                }
-            },
-        );
+            let mut note = if passive_voice {
+                format!(
+                    "but `{}` is actually implemented for the type `{}`",
+                    actual_trait_ref,
+                    actual_trait_ref.map(|tr| tr.self_ty()),
+                )
+            } else {
+                format!(
+                    "but `{}` actually implements `{}`",
+                    actual_trait_ref.map(|tr| tr.self_ty()),
+                    actual_trait_ref,
+                )
+            };
+
+            if let Some(n) = actual_has_vid {
+                let _ = write!(note, ", for some specific lifetime `'{}`", n);
+            }
+
+            note
+        });
     }
 }
diff --git a/src/librustc/infer/error_reporting/nice_region_error/util.rs b/src/librustc/infer/error_reporting/nice_region_error/util.rs
index 6db1bc3..3ed28a1 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/util.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/util.rs
@@ -3,7 +3,7 @@
 
 use crate::hir;
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
-use crate::ty::{self, Region, Ty};
+use crate::ty::{self, DefIdTree, Region, Ty};
 use crate::hir::def_id::DefId;
 use syntax_pos::Span;
 
@@ -44,7 +44,7 @@
         let (id, bound_region) = match *anon_region {
             ty::ReFree(ref free_region) => (free_region.scope, free_region.bound_region),
             ty::ReEarlyBound(ref ebr) => (
-                self.tcx().parent_def_id(ebr.def_id).unwrap(),
+                self.tcx().parent(ebr.def_id).unwrap(),
                 ty::BoundRegion::BrNamed(ebr.def_id, ebr.name),
             ),
             _ => return None, // not a free region
diff --git a/src/librustc/infer/outlives/free_region_map.rs b/src/librustc/infer/outlives/free_region_map.rs
index 78353e5..5349e99 100644
--- a/src/librustc/infer/outlives/free_region_map.rs
+++ b/src/librustc/infer/outlives/free_region_map.rs
@@ -91,7 +91,7 @@
 impl<'a, 'tcx> Lift<'tcx> for FreeRegionMap<'a> {
     type Lifted = FreeRegionMap<'tcx>;
     fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<FreeRegionMap<'tcx>> {
-        self.relation.maybe_map(|&fr| fr.lift_to_tcx(tcx))
+        self.relation.maybe_map(|&fr| tcx.lift(&fr))
                      .map(|relation| FreeRegionMap { relation })
     }
 }
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index 681dffc..4b2fda3 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -31,6 +31,7 @@
 #![deny(rust_2018_idioms)]
 #![allow(explicit_outlives_requirements)]
 
+#![feature(arbitrary_self_types)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(core_intrinsics)]
@@ -59,6 +60,8 @@
 #![feature(test)]
 #![feature(in_band_lifetimes)]
 #![feature(crate_visibility_modifier)]
+#![feature(proc_macro_hygiene)]
+#![feature(log_syntax)]
 
 #![recursion_limit="512"]
 
@@ -68,6 +71,7 @@
 #[macro_use] extern crate scoped_tls;
 #[cfg(windows)]
 extern crate libc;
+#[macro_use] extern crate rustc_macros;
 #[macro_use] extern crate rustc_data_structures;
 
 #[macro_use] extern crate log;
@@ -95,6 +99,9 @@
 // registered before they are used.
 pub mod diagnostics;
 
+#[macro_use]
+pub mod query;
+
 pub mod cfg;
 pub mod dep_graph;
 pub mod hir;
@@ -134,7 +141,6 @@
 pub mod util {
     pub mod captures;
     pub mod common;
-    pub mod ppaux;
     pub mod nodemap;
     pub mod profiling;
     pub mod bug;
diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs
index 3c6635c..19e899c 100644
--- a/src/librustc/lint/levels.rs
+++ b/src/librustc/lint/levels.rs
@@ -194,7 +194,7 @@
             struct_span_err!(sess, span, E0452, "malformed lint attribute")
         };
         for attr in attrs {
-            let level = match Level::from_str(&attr.name().as_str()) {
+            let level = match attr.ident_str().and_then(|name| Level::from_str(name)) {
                 None => continue,
                 Some(lvl) => lvl,
             };
@@ -221,7 +221,7 @@
                 match item.node {
                     ast::MetaItemKind::Word => {}  // actual lint names handled later
                     ast::MetaItemKind::NameValue(ref name_value) => {
-                        if item.ident == "reason" {
+                        if item.path == "reason" {
                             // found reason, reslice meta list to exclude it
                             metas = &metas[0..metas.len()-1];
                             // FIXME (#55112): issue unused-attributes lint if we thereby
@@ -255,13 +255,13 @@
             }
 
             for li in metas {
-                let word = match li.word() {
-                    Some(word) => word,
-                    None => {
-                        let mut err = bad_attr(li.span);
+                let meta_item = match li.meta_item() {
+                    Some(meta_item) if meta_item.is_word() => meta_item,
+                    _ => {
+                        let mut err = bad_attr(li.span());
                         if let Some(item) = li.meta_item() {
                             if let ast::MetaItemKind::NameValue(_) = item.node {
-                                if item.ident == "reason" {
+                                if item.path == "reason" {
                                     err.help("reason in lint attribute must come last");
                                 }
                             }
@@ -270,26 +270,27 @@
                         continue;
                     }
                 };
-                let tool_name = if let Some(lint_tool) = word.is_scoped() {
-                    if !attr::is_known_lint_tool(lint_tool) {
+                let tool_name = if meta_item.path.segments.len() > 1 {
+                    let tool_ident = meta_item.path.segments[0].ident;
+                    if !attr::is_known_lint_tool(tool_ident) {
                         span_err!(
                             sess,
-                            lint_tool.span,
+                            tool_ident.span,
                             E0710,
                             "an unknown tool name found in scoped lint: `{}`",
-                            word.ident
+                            meta_item.path
                         );
                         continue;
                     }
 
-                    Some(lint_tool.as_str())
+                    Some(tool_ident.as_str())
                 } else {
                     None
                 };
-                let name = word.name();
+                let name = meta_item.path.segments.last().expect("empty lint name").ident.name;
                 match store.check_lint_name(&name.as_str(), tool_name) {
                     CheckLintNameResult::Ok(ids) => {
-                        let src = LintSource::Node(name, li.span, reason);
+                        let src = LintSource::Node(name, li.span(), reason);
                         for id in ids {
                             specs.insert(*id, (level, src));
                         }
@@ -300,7 +301,7 @@
                             Ok(ids) => {
                                 let complete_name = &format!("{}::{}", tool_name.unwrap(), name);
                                 let src = LintSource::Node(
-                                    Symbol::intern(complete_name), li.span, reason
+                                    Symbol::intern(complete_name), li.span(), reason
                                 );
                                 for id in ids {
                                     specs.insert(*id, (level, src));
@@ -322,18 +323,18 @@
                                     lint,
                                     lvl,
                                     src,
-                                    Some(li.span.into()),
+                                    Some(li.span().into()),
                                     &msg,
                                 );
                                 err.span_suggestion(
-                                    li.span,
+                                    li.span(),
                                     "change it to",
                                     new_lint_name.to_string(),
                                     Applicability::MachineApplicable,
                                 ).emit();
 
                                 let src = LintSource::Node(
-                                    Symbol::intern(&new_lint_name), li.span, reason
+                                    Symbol::intern(&new_lint_name), li.span(), reason
                                 );
                                 for id in ids {
                                     specs.insert(*id, (level, src));
@@ -360,11 +361,11 @@
                                                               lint,
                                                               level,
                                                               src,
-                                                              Some(li.span.into()),
+                                                              Some(li.span().into()),
                                                               &msg);
                         if let Some(new_name) = renamed {
                             err.span_suggestion(
-                                li.span,
+                                li.span(),
                                 "use the new name",
                                 new_name,
                                 Applicability::MachineApplicable
@@ -383,12 +384,12 @@
                                                 lint,
                                                 level,
                                                 src,
-                                                Some(li.span.into()),
+                                                Some(li.span().into()),
                                                 &msg);
 
                         if let Some(suggestion) = suggestion {
                             db.span_suggestion(
-                                li.span,
+                                li.span(),
                                 "did you mean",
                                 suggestion.to_string(),
                                 Applicability::MachineApplicable,
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index c01b0ae..03ed62f 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -724,7 +724,7 @@
 pub fn maybe_lint_level_root(tcx: TyCtxt<'_, '_, '_>, id: hir::HirId) -> bool {
     let attrs = tcx.hir().attrs_by_hir_id(id);
     for attr in attrs {
-        if Level::from_str(&attr.name().as_str()).is_some() {
+        if attr.ident_str().and_then(Level::from_str).is_some() {
             return true;
         }
     }
@@ -833,7 +833,8 @@
 
 /// Returns whether `span` originates in a foreign crate's external macro.
 ///
-/// This is used to test whether a lint should be entirely aborted above.
+/// This is used to test whether a lint should not even begin to figure out whether it should
+/// be reported on the current node.
 pub fn in_external_macro(sess: &Session, span: Span) -> bool {
     let info = match span.ctxt().outer().expn_info() {
         Some(info) => info,
@@ -859,3 +860,17 @@
         Err(_) => true,
     }
 }
+
+/// Returns whether `span` originates in a derive macro's expansion
+pub fn in_derive_expansion(span: Span) -> bool {
+    let info = match span.ctxt().outer().expn_info() {
+        Some(info) => info,
+        // no ExpnInfo means this span doesn't come from a macro
+        None => return false,
+    };
+
+    match info.format {
+        ExpnFormat::MacroAttribute(symbol) => symbol.as_str().starts_with("derive("),
+        _ => false,
+    }
+}
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index 94de999..3da82d7 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -12,7 +12,7 @@
 use crate::hir::def_id::{DefId, LOCAL_CRATE};
 use crate::lint;
 use crate::middle::privacy;
-use crate::ty::{self, TyCtxt};
+use crate::ty::{self, DefIdTree, TyCtxt};
 use crate::util::nodemap::FxHashSet;
 
 use rustc_data_structures::fx::FxHashMap;
@@ -78,7 +78,7 @@
             Def::PrimTy(..) | Def::SelfTy(..) | Def::SelfCtor(..) |
             Def::Local(..) | Def::Upvar(..) => {}
             Def::Variant(variant_id) | Def::VariantCtor(variant_id, ..) => {
-                if let Some(enum_id) = self.tcx.parent_def_id(variant_id) {
+                if let Some(enum_id) = self.tcx.parent(variant_id) {
                     self.check_def_id(enum_id);
                 }
                 if !self.ignore_variant_stack.contains(&variant_id) {
diff --git a/src/librustc/middle/lib_features.rs b/src/librustc/middle/lib_features.rs
index 9d15b05..237b00d 100644
--- a/src/librustc/middle/lib_features.rs
+++ b/src/librustc/middle/lib_features.rs
@@ -65,9 +65,9 @@
                 for meta in metas {
                     if let Some(mi) = meta.meta_item() {
                         // Find the `feature = ".."` meta-item.
-                        match (&*mi.name().as_str(), mi.value_str()) {
-                            ("feature", val) => feature = val,
-                            ("since", val) => since = val,
+                        match (mi.ident_str(), mi.value_str()) {
+                            (Some("feature"), val) => feature = val,
+                            (Some("since"), val) => since = val,
                             _ => {}
                         }
                     }
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index a3e8598..b36d2a5 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -64,7 +64,7 @@
 use crate::infer::InferCtxt;
 use crate::hir::def::{Def, CtorKind};
 use crate::ty::adjustment;
-use crate::ty::{self, Ty, TyCtxt};
+use crate::ty::{self, DefIdTree, Ty, TyCtxt};
 use crate::ty::fold::TypeFoldable;
 use crate::ty::layout::VariantIdx;
 
@@ -786,7 +786,8 @@
         // FnMut          | copied -> &'env mut  | upvar -> &'env mut -> &'up bk
         // FnOnce         | copied               | upvar -> &'up bk
 
-        let kind = match self.node_ty(fn_hir_id)?.sty {
+        let ty = self.node_ty(fn_hir_id)?;
+        let kind = match ty.sty {
             ty::Generator(..) => ty::ClosureKind::FnOnce,
             ty::Closure(closure_def_id, closure_substs) => {
                 match self.infcx {
@@ -803,7 +804,7 @@
                                 .closure_kind(closure_def_id, self.tcx.global_tcx()),
                 }
             }
-            ref t => span_bug!(span, "unexpected type for fn in mem_categorization: {:?}", t),
+            _ => span_bug!(span, "unexpected type for fn in mem_categorization: {:?}", ty),
         };
 
         let closure_expr_def_id = self.tcx.hir().local_def_id(fn_node_id);
@@ -1064,7 +1065,7 @@
                 let bk = ty::BorrowKind::from_mutbl(mutbl);
                 BorrowedPtr(bk, r)
             }
-            ref ty => bug!("unexpected type in cat_deref: {:?}", ty)
+            _ => bug!("unexpected type in cat_deref: {:?}", base_cmt.ty)
         };
         let ret = cmt_ {
             hir_id: node.hir_id(),
@@ -1132,7 +1133,7 @@
                                              variant_did: DefId)
                                              -> cmt<'tcx> {
         // univariant enums do not need downcasts
-        let base_did = self.tcx.parent_def_id(variant_did).unwrap();
+        let base_did = self.tcx.parent(variant_did).unwrap();
         if self.tcx.adt_def(base_did).variants.len() != 1 {
             let base_ty = base_cmt.ty;
             let ret = Rc::new(cmt_ {
@@ -1274,16 +1275,17 @@
                         return Err(())
                     }
                     Def::VariantCtor(def_id, CtorKind::Fn) => {
-                        let enum_def = self.tcx.parent_def_id(def_id).unwrap();
+                        let enum_def = self.tcx.parent(def_id).unwrap();
                         (self.cat_downcast_if_needed(pat, cmt, def_id),
                         self.tcx.adt_def(enum_def).variant_with_id(def_id).fields.len())
                     }
                     Def::StructCtor(_, CtorKind::Fn) | Def::SelfCtor(..) => {
-                        match self.pat_ty_unadjusted(&pat)?.sty {
+                        let ty = self.pat_ty_unadjusted(&pat)?;
+                        match ty.sty {
                             ty::Adt(adt_def, _) => {
                                 (cmt, adt_def.non_enum_variant().fields.len())
                             }
-                            ref ty => {
+                            _ => {
                                 span_bug!(pat.span,
                                           "tuple struct pattern unexpected type {:?}", ty);
                             }
@@ -1334,9 +1336,10 @@
 
             PatKind::Tuple(ref subpats, ddpos) => {
                 // (p1, ..., pN)
-                let expected_len = match self.pat_ty_unadjusted(&pat)?.sty {
+                let ty = self.pat_ty_unadjusted(&pat)?;
+                let expected_len = match ty.sty {
                     ty::Tuple(ref tys) => tys.len(),
-                    ref ty => span_bug!(pat.span, "tuple pattern unexpected type {:?}", ty),
+                    _ => span_bug!(pat.span, "tuple pattern unexpected type {:?}", ty),
                 };
                 for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
                     let subpat_ty = self.pat_ty_adjusted(&subpat)?; // see (*2)
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index 42e2532..2b38023 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -17,7 +17,7 @@
 use syntax::source_map;
 use syntax::ast;
 use syntax_pos::{Span, DUMMY_SP};
-use crate::ty::TyCtxt;
+use crate::ty::{DefIdTree, TyCtxt};
 use crate::ty::query::Providers;
 
 use crate::hir;
@@ -650,7 +650,7 @@
     pub fn early_free_scope<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
                                       br: &ty::EarlyBoundRegion)
                                       -> Scope {
-        let param_owner = tcx.parent_def_id(br.def_id).unwrap();
+        let param_owner = tcx.parent(br.def_id).unwrap();
 
         let param_owner_id = tcx.hir().as_local_hir_id(param_owner).unwrap();
         let scope = tcx.hir().maybe_body_owned_by_by_hir_id(param_owner_id).map(|body_id| {
@@ -679,7 +679,7 @@
                                  -> Scope {
         let param_owner = match fr.bound_region {
             ty::BoundRegion::BrNamed(def_id, _) => {
-                tcx.parent_def_id(def_id).unwrap()
+                tcx.parent(def_id).unwrap()
             }
             _ => fr.scope
         };
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index 96f0bea..ab105360 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -2299,6 +2299,7 @@
         let span = lifetime_refs[0].span;
         let mut late_depth = 0;
         let mut scope = self.scope;
+        let mut lifetime_names = FxHashSet::default();
         let error = loop {
             match *scope {
                 // Do not assign any resolution, it will be inferred.
@@ -2306,12 +2307,18 @@
 
                 Scope::Root => break None,
 
-                Scope::Binder { s, .. } => {
+                Scope::Binder { s, ref lifetimes, .. } => {
+                    // collect named lifetimes for suggestions
+                    for name in lifetimes.keys() {
+                        if let hir::ParamName::Plain(name) = name {
+                            lifetime_names.insert(*name);
+                        }
+                    }
                     late_depth += 1;
                     scope = s;
                 }
 
-                Scope::Elision { ref elide, .. } => {
+                Scope::Elision { ref elide, ref s, .. } => {
                     let lifetime = match *elide {
                         Elide::FreshLateAnon(ref counter) => {
                             for lifetime_ref in lifetime_refs {
@@ -2321,7 +2328,17 @@
                             return;
                         }
                         Elide::Exact(l) => l.shifted(late_depth),
-                        Elide::Error(ref e) => break Some(e),
+                        Elide::Error(ref e) => {
+                            if let Scope::Binder { ref lifetimes, .. } = s {
+                                // collect named lifetimes for suggestions
+                                for name in lifetimes.keys() {
+                                    if let hir::ParamName::Plain(name) = name {
+                                        lifetime_names.insert(*name);
+                                    }
+                                }
+                            }
+                            break Some(e);
+                        }
                     };
                     for lifetime_ref in lifetime_refs {
                         self.insert_lifetime(lifetime_ref, lifetime);
@@ -2344,7 +2361,13 @@
             }
         }
         if add_label {
-            add_missing_lifetime_specifiers_label(&mut err, span, lifetime_refs.len());
+            add_missing_lifetime_specifiers_label(
+                &mut err,
+                span,
+                lifetime_refs.len(),
+                &lifetime_names,
+                self.tcx.sess.source_map().span_to_snippet(span).ok().as_ref().map(|s| s.as_str()),
+            );
         }
 
         err.emit();
@@ -2885,10 +2908,23 @@
     err: &mut DiagnosticBuilder<'_>,
     span: Span,
     count: usize,
+    lifetime_names: &FxHashSet<ast::Ident>,
+    snippet: Option<&str>,
 ) {
     if count > 1 {
         err.span_label(span, format!("expected {} lifetime parameters", count));
+    } else if let (1, Some(name), Some("&")) = (
+        lifetime_names.len(),
+        lifetime_names.iter().next(),
+        snippet,
+    ) {
+        err.span_suggestion(
+            span,
+            "consider using the named lifetime",
+            format!("&{} ", name),
+            Applicability::MaybeIncorrect,
+        );
     } else {
         err.span_label(span, "expected lifetime parameter");
-    };
+    }
 }
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index 1677384..c1a97cd 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -3,7 +3,7 @@
 
 pub use self::StabilityLevel::*;
 
-use crate::lint::{self, Lint};
+use crate::lint::{self, Lint, in_derive_expansion};
 use crate::hir::{self, Item, Generics, StructField, Variant, HirId};
 use crate::hir::def::Def;
 use crate::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE};
@@ -194,11 +194,12 @@
         } else {
             // Emit errors for non-staged-api crates.
             for attr in attrs {
-                let tag = attr.name();
-                if tag == "unstable" || tag == "stable" || tag == "rustc_deprecated" {
-                    attr::mark_used(attr);
-                    self.tcx.sess.span_err(attr.span(), "stability attributes may not be used \
-                                                         outside of the standard library");
+                if let Some(tag) = attr.ident_str() {
+                    if tag == "unstable" || tag == "stable" || tag == "rustc_deprecated" {
+                        attr::mark_used(attr);
+                        self.tcx.sess.span_err(attr.span, "stability attributes may not be used \
+                                                           outside of the standard library");
+                    }
                 }
             }
 
@@ -561,6 +562,9 @@
                                suggestion: Option<Symbol>,
                                message: &str,
                                lint: &'static Lint| {
+            if in_derive_expansion(span) {
+                return;
+            }
             let msg = if let Some(note) = note {
                 format!("{}: {}", message, note)
             } else {
@@ -593,7 +597,7 @@
                                .map_or(false, |parent_depr| parent_depr.same_origin(&depr_entry));
 
                 if !skip {
-                    let path = self.item_path_str(def_id);
+                    let path = self.def_path_str(def_id);
                     let message = format!("use of deprecated item '{}'", path);
                     lint_deprecated(def_id,
                                     id,
@@ -620,7 +624,7 @@
         if let Some(id) = id {
             if let Some(stability) = stability {
                 if let Some(depr) = &stability.rustc_depr {
-                    let path = self.item_path_str(def_id);
+                    let path = self.def_path_str(def_id);
                     if deprecation_in_effect(&depr.since.as_str()) {
                         let message = format!("use of deprecated item '{}'", path);
                         lint_deprecated(def_id,
diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs
index d4ee60e..80fef91 100644
--- a/src/librustc/mir/interpret/allocation.rs
+++ b/src/librustc/mir/interpret/allocation.rs
@@ -101,8 +101,7 @@
 impl<Tag, Extra> Allocation<Tag, Extra> {
     /// Creates a read-only allocation initialized by the given bytes
     pub fn from_bytes(slice: &[u8], align: Align, extra: Extra) -> Self {
-        let mut undef_mask = UndefMask::new(Size::ZERO);
-        undef_mask.grow(Size::from_bytes(slice.len() as u64), true);
+        let undef_mask = UndefMask::new(Size::from_bytes(slice.len() as u64), true);
         Self {
             bytes: slice.to_owned(),
             relocations: Relocations::new(),
@@ -122,7 +121,7 @@
         Allocation {
             bytes: vec![0; size.bytes() as usize],
             relocations: Relocations::new(),
-            undef_mask: UndefMask::new(size),
+            undef_mask: UndefMask::new(size, false),
             align,
             mutability: Mutability::Mutable,
             extra,
@@ -614,8 +613,9 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 type Block = u64;
-const BLOCK_SIZE: u64 = 64;
 
+/// A bitmask where each bit refers to the byte with the same index. If the bit is `true`, the byte
+/// is defined. If it is `false` the byte is undefined.
 #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
 pub struct UndefMask {
     blocks: Vec<Block>,
@@ -625,12 +625,14 @@
 impl_stable_hash_for!(struct mir::interpret::UndefMask{blocks, len});
 
 impl UndefMask {
-    pub fn new(size: Size) -> Self {
+    pub const BLOCK_SIZE: u64 = 64;
+
+    pub fn new(size: Size, state: bool) -> Self {
         let mut m = UndefMask {
             blocks: vec![],
             len: Size::ZERO,
         };
-        m.grow(size, false);
+        m.grow(size, state);
         m
     }
 
@@ -644,6 +646,7 @@
             return Err(self.len);
         }
 
+        // FIXME(oli-obk): optimize this for allocations larger than a block.
         let idx = (start.bytes()..end.bytes())
             .map(|i| Size::from_bytes(i))
             .find(|&i| !self.get(i));
@@ -663,20 +666,63 @@
     }
 
     pub fn set_range_inbounds(&mut self, start: Size, end: Size, new_state: bool) {
-        for i in start.bytes()..end.bytes() {
-            self.set(Size::from_bytes(i), new_state);
+        let (blocka, bita) = bit_index(start);
+        let (blockb, bitb) = bit_index(end);
+        if blocka == blockb {
+            // first set all bits but the first `bita`
+            // then unset the last `64 - bitb` bits
+            let range = if bitb == 0 {
+                u64::max_value() << bita
+            } else {
+                (u64::max_value() << bita) & (u64::max_value() >> (64 - bitb))
+            };
+            if new_state {
+                self.blocks[blocka] |= range;
+            } else {
+                self.blocks[blocka] &= !range;
+            }
+            return;
+        }
+        // across block boundaries
+        if new_state {
+            // set bita..64 to 1
+            self.blocks[blocka] |= u64::max_value() << bita;
+            // set 0..bitb to 1
+            if bitb != 0 {
+                self.blocks[blockb] |= u64::max_value() >> (64 - bitb);
+            }
+            // fill in all the other blocks (much faster than one bit at a time)
+            for block in (blocka + 1) .. blockb {
+                self.blocks[block] = u64::max_value();
+            }
+        } else {
+            // set bita..64 to 0
+            self.blocks[blocka] &= !(u64::max_value() << bita);
+            // set 0..bitb to 0
+            if bitb != 0 {
+                self.blocks[blockb] &= !(u64::max_value() >> (64 - bitb));
+            }
+            // fill in all the other blocks (much faster than one bit at a time)
+            for block in (blocka + 1) .. blockb {
+                self.blocks[block] = 0;
+            }
         }
     }
 
     #[inline]
     pub fn get(&self, i: Size) -> bool {
         let (block, bit) = bit_index(i);
-        (self.blocks[block] & 1 << bit) != 0
+        (self.blocks[block] & (1 << bit)) != 0
     }
 
     #[inline]
     pub fn set(&mut self, i: Size, new_state: bool) {
         let (block, bit) = bit_index(i);
+        self.set_bit(block, bit, new_state);
+    }
+
+    #[inline]
+    fn set_bit(&mut self, block: usize, bit: usize, new_state: bool) {
         if new_state {
             self.blocks[block] |= 1 << bit;
         } else {
@@ -685,11 +731,15 @@
     }
 
     pub fn grow(&mut self, amount: Size, new_state: bool) {
-        let unused_trailing_bits = self.blocks.len() as u64 * BLOCK_SIZE - self.len.bytes();
+        if amount.bytes() == 0 {
+            return;
+        }
+        let unused_trailing_bits = self.blocks.len() as u64 * Self::BLOCK_SIZE - self.len.bytes();
         if amount.bytes() > unused_trailing_bits {
-            let additional_blocks = amount.bytes() / BLOCK_SIZE + 1;
+            let additional_blocks = amount.bytes() / Self::BLOCK_SIZE + 1;
             assert_eq!(additional_blocks as usize as u64, additional_blocks);
             self.blocks.extend(
+                // FIXME(oli-obk): optimize this by repeating `new_state as Block`
                 iter::repeat(0).take(additional_blocks as usize),
             );
         }
@@ -702,8 +752,8 @@
 #[inline]
 fn bit_index(bits: Size) -> (usize, usize) {
     let bits = bits.bytes();
-    let a = bits / BLOCK_SIZE;
-    let b = bits % BLOCK_SIZE;
+    let a = bits / UndefMask::BLOCK_SIZE;
+    let b = bits % UndefMask::BLOCK_SIZE;
     assert_eq!(a as usize as u64, a);
     assert_eq!(b as usize as u64, b);
     (a as usize, b as usize)
diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs
index 9620ac9..7b47c02 100644
--- a/src/librustc/mir/interpret/value.rs
+++ b/src/librustc/mir/interpret/value.rs
@@ -1,7 +1,8 @@
 use std::fmt;
 use rustc_macros::HashStable;
 
-use crate::ty::{Ty, InferConst, ParamConst, layout::{HasDataLayout, Size}};
+use crate::ty::{Ty, InferConst, ParamConst, layout::{HasDataLayout, Size}, subst::SubstsRef};
+use crate::hir::def_id::DefId;
 
 use super::{EvalResult, Pointer, PointerArithmetic, Allocation, AllocId, sign_extend, truncate};
 
@@ -42,6 +43,10 @@
     /// An allocation together with a pointer into the allocation.
     /// Invariant: the pointer's `AllocId` resolves to the allocation.
     ByRef(Pointer, &'tcx Allocation),
+
+    /// Used in the HIR by using `Unevaluated` everywhere and later normalizing to one of the other
+    /// variants when the code is monomorphic enough for that.
+    Unevaluated(DefId, SubstsRef<'tcx>),
 }
 
 #[cfg(target_arch = "x86_64")]
@@ -54,6 +59,7 @@
             ConstValue::Param(_) |
             ConstValue::Infer(_) |
             ConstValue::ByRef(..) |
+            ConstValue::Unevaluated(..) |
             ConstValue::Slice(..) => None,
             ConstValue::Scalar(val) => Some(val),
         }
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index 3a4422a..9f2027e 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -2,7 +2,7 @@
 //!
 //! [rustc guide]: https://rust-lang.github.io/rustc-guide/mir/index.html
 
-use crate::hir::def::CtorKind;
+use crate::hir::def::{CtorKind, Namespace};
 use crate::hir::def_id::DefId;
 use crate::hir::{self, HirId, InlineAsm};
 use crate::mir::interpret::{ConstValue, EvalErrorKind, Scalar};
@@ -34,7 +34,7 @@
     self, AdtDef, CanonicalUserTypeAnnotations, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt,
     UserTypeAnnotationIndex,
 };
-use crate::util::ppaux;
+use crate::ty::print::{FmtPrinter, Printer};
 
 pub use crate::mir::interpret::AssertMessage;
 
@@ -2062,7 +2062,7 @@
             Base(PlaceBase::Static(box self::Static { def_id, ty })) => write!(
                 fmt,
                 "({}: {:?})",
-                ty::tls::with(|tcx| tcx.item_path_str(def_id)),
+                ty::tls::with(|tcx| tcx.def_path_str(def_id)),
                 ty
             ),
             Base(PlaceBase::Promoted(ref promoted)) => write!(
@@ -2179,8 +2179,8 @@
             span,
             ty,
             user_ty: None,
-            literal: tcx.mk_lazy_const(
-                ty::LazyConst::Evaluated(ty::Const::zero_sized(ty)),
+            literal: tcx.mk_const(
+                ty::Const::zero_sized(ty),
             ),
         })
     }
@@ -2369,7 +2369,10 @@
                 };
 
                 // When printing regions, add trailing space if necessary.
-                let region = if ppaux::verbose() || ppaux::identify_regions() {
+                let print_region = ty::tls::with(|tcx| {
+                    tcx.sess.verbose() || tcx.sess.opts.debugging_opts.identify_regions
+                });
+                let region = if print_region {
                     let mut region = region.to_string();
                     if region.len() > 0 {
                         region.push(' ');
@@ -2403,7 +2406,13 @@
                     AggregateKind::Adt(adt_def, variant, substs, _user_ty, _) => {
                         let variant_def = &adt_def.variants[variant];
 
-                        ppaux::parameterized(fmt, substs, variant_def.did, &[])?;
+                        let f = &mut *fmt;
+                        ty::tls::with(|tcx| {
+                            let substs = tcx.lift(&substs).expect("could not lift for printing");
+                            FmtPrinter::new(tcx, f, Namespace::ValueNS)
+                                .print_def_path(variant_def.did, substs)?;
+                            Ok(())
+                        })?;
 
                         match variant_def.ctor_kind {
                             CtorKind::Const => Ok(()),
@@ -2488,7 +2497,7 @@
     /// Needed for NLL to impose user-given type constraints.
     pub user_ty: Option<UserTypeAnnotationIndex>,
 
-    pub literal: &'tcx ty::LazyConst<'tcx>,
+    pub literal: &'tcx ty::Const<'tcx>,
 }
 
 /// A collection of projections into user types.
@@ -2687,18 +2696,9 @@
 impl<'tcx> Debug for Constant<'tcx> {
     fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
         write!(fmt, "const ")?;
-        fmt_lazy_const_val(fmt, self.literal)
+        fmt_const_val(fmt, *self.literal)
     }
 }
-
-/// Write a `ConstValue` in a way closer to the original source code than the `Debug` output.
-pub fn fmt_lazy_const_val(f: &mut impl Write, const_val: &ty::LazyConst<'_>) -> fmt::Result {
-    match *const_val {
-        ty::LazyConst::Unevaluated(..) => write!(f, "{:?}", const_val),
-        ty::LazyConst::Evaluated(c) => fmt_const_val(f, c),
-    }
-}
-
 /// Write a `ConstValue` in a way closer to the original source code than the `Debug` output.
 pub fn fmt_const_val(f: &mut impl Write, const_val: ty::Const<'_>) -> fmt::Result {
     use crate::ty::TyKind::*;
@@ -2729,7 +2729,7 @@
     }
     // print function definitions
     if let FnDef(did, _) = ty.sty {
-        return write!(f, "{}", item_path_str(did));
+        return write!(f, "{}", def_path_str(did));
     }
     // print string literals
     if let ConstValue::Slice(ptr, len) = value {
@@ -2751,11 +2751,11 @@
         }
     }
     // just raw dump everything else
-    write!(f, "{:?}:{}", value, ty)
+    write!(f, "{:?} : {}", value, ty)
 }
 
-fn item_path_str(def_id: DefId) -> String {
-    ty::tls::with(|tcx| tcx.item_path_str(def_id))
+fn def_path_str(def_id: DefId) -> String {
+    ty::tls::with(|tcx| tcx.def_path_str(def_id))
 }
 
 impl<'tcx> graph::DirectedGraph for Mir<'tcx> {
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index 28e816f..8bc0075 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -232,7 +232,7 @@
             }
 
             fn visit_const(&mut self,
-                           constant: & $($mutability)? &'tcx ty::LazyConst<'tcx>,
+                           constant: & $($mutability)? &'tcx ty::Const<'tcx>,
                            _: Location) {
                 self.super_const(constant);
             }
@@ -886,7 +886,7 @@
             fn super_region(&mut self, _region: & $($mutability)? ty::Region<'tcx>) {
             }
 
-            fn super_const(&mut self, _const: & $($mutability)? &'tcx ty::LazyConst<'tcx>) {
+            fn super_const(&mut self, _const: & $($mutability)? &'tcx ty::Const<'tcx>) {
             }
 
             fn super_substs(&mut self, _substs: & $($mutability)? SubstsRef<'tcx>) {
diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs
new file mode 100644
index 0000000..ecc0089
--- /dev/null
+++ b/src/librustc/query/mod.rs
@@ -0,0 +1,66 @@
+use crate::ty::query::QueryDescription;
+use crate::ty::query::queries;
+use crate::ty::TyCtxt;
+use crate::ty;
+use crate::hir::def_id::CrateNum;
+use crate::dep_graph::SerializedDepNodeIndex;
+use std::borrow::Cow;
+
+// Each of these queries corresponds to a function pointer field in the
+// `Providers` struct for requesting a value of that type, and a method
+// on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way
+// which memoizes and does dep-graph tracking, wrapping around the actual
+// `Providers` that the driver creates (using several `rustc_*` crates).
+//
+// The result type of each query must implement `Clone`, and additionally
+// `ty::query::values::Value`, which produces an appropriate placeholder
+// (error) value if the query resulted in a query cycle.
+// Queries marked with `fatal_cycle` do not need the latter implementation,
+// as they will raise an fatal error on query cycles instead.
+rustc_queries! {
+    Other {
+        /// Records the type of every item.
+        query type_of(key: DefId) -> Ty<'tcx> {
+            cache { key.is_local() }
+        }
+
+        /// Maps from the `DefId` of an item (trait/struct/enum/fn) to its
+        /// associated generics.
+        query generics_of(key: DefId) -> &'tcx ty::Generics {
+            cache { key.is_local() }
+            load_cached(tcx, id) {
+                let generics: Option<ty::Generics> = tcx.queries.on_disk_cache
+                                                        .try_load_query_result(tcx, id);
+                generics.map(|x| tcx.alloc_generics(x))
+            }
+        }
+
+        /// Maps from the `DefId` of an item (trait/struct/enum/fn) to the
+        /// predicates (where-clauses) that must be proven true in order
+        /// to reference it. This is almost always the "predicates query"
+        /// that you want.
+        ///
+        /// `predicates_of` builds on `predicates_defined_on` -- in fact,
+        /// it is almost always the same as that query, except for the
+        /// case of traits. For traits, `predicates_of` contains
+        /// an additional `Self: Trait<...>` predicate that users don't
+        /// actually write. This reflects the fact that to invoke the
+        /// trait (e.g., via `Default::default`) you must supply types
+        /// that actually implement the trait. (However, this extra
+        /// predicate gets in the way of some checks, which are intended
+        /// to operate over only the actual where-clauses written by the
+        /// user.)
+        query predicates_of(_: DefId) -> Lrc<ty::GenericPredicates<'tcx>> {}
+
+        query native_libraries(_: CrateNum) -> Lrc<Vec<NativeLibrary>> {
+            desc { "looking up the native libraries of a linked crate" }
+        }
+    }
+
+    Codegen {
+        query is_panic_runtime(_: CrateNum) -> bool {
+            fatal_cycle
+            desc { "checking if the crate is_panic_runtime" }
+        }
+    }
+}
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 55c4b0e..0ae7c10 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -800,6 +800,7 @@
         pub const parse_opt_pathbuf: Option<&str> = Some("a path");
         pub const parse_list: Option<&str> = Some("a space-separated list of strings");
         pub const parse_opt_list: Option<&str> = Some("a space-separated list of strings");
+        pub const parse_opt_comma_list: Option<&str> = Some("a comma-separated list of strings");
         pub const parse_uint: Option<&str> = Some("a number");
         pub const parse_passes: Option<&str> =
             Some("a space-separated list of passes, or `all`");
@@ -926,6 +927,18 @@
             }
         }
 
+        fn parse_opt_comma_list(slot: &mut Option<Vec<String>>, v: Option<&str>)
+                      -> bool {
+            match v {
+                Some(s) => {
+                    let v = s.split(',').map(|s| s.to_string()).collect();
+                    *slot = Some(v);
+                    true
+                },
+                None => false,
+            }
+        }
+
         fn parse_uint(slot: &mut usize, v: Option<&str>) -> bool {
             match v.and_then(|s| s.parse().ok()) {
                 Some(i) => { *slot = i; true },
@@ -1427,6 +1440,8 @@
     merge_functions: Option<MergeFunctions> = (None, parse_merge_functions, [TRACKED],
         "control the operation of the MergeFunctions LLVM pass, taking
          the same values as the target option of the same name"),
+    allow_features: Option<Vec<String>> = (None, parse_opt_comma_list, [TRACKED],
+        "only allow the listed language features to be enabled in code (space separated)"),
 }
 
 pub fn default_lib_output() -> CrateType {
@@ -1824,7 +1839,7 @@
 
             match &mut parser.parse_meta_item() {
                 Ok(meta_item) if parser.token == token::Eof => {
-                    if meta_item.ident.segments.len() != 1 {
+                    if meta_item.path.segments.len() != 1 {
                         error!("argument key must be an identifier");
                     }
                     match &meta_item.node {
@@ -1835,7 +1850,8 @@
                             error!("argument value must be a string");
                         }
                         MetaItemKind::NameValue(..) | MetaItemKind::Word => {
-                            return (meta_item.name(), meta_item.value_str());
+                            let ident = meta_item.ident().expect("multi-segment cfg key");
+                            return (ident.name, meta_item.value_str());
                         }
                     }
                 }
@@ -3273,6 +3289,10 @@
         opts = reference.clone();
         opts.debugging_opts.merge_functions = Some(MergeFunctions::Disabled);
         assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
+
+        opts = reference.clone();
+        opts.debugging_opts.allow_features = Some(vec![String::from("lang_items")]);
+        assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
     }
 
     #[test]
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index c7674ae..6c8fe08 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -854,10 +854,11 @@
                     _ => vec![ArgKind::empty()],
                 };
 
-                let expected = match expected_trait_ref.skip_binder().substs.type_at(1).sty {
+                let expected_ty = expected_trait_ref.skip_binder().substs.type_at(1);
+                let expected = match expected_ty.sty {
                     ty::Tuple(ref tys) => tys.iter()
                         .map(|t| ArgKind::from_expected_ty(t, Some(span))).collect(),
-                    ref sty => vec![ArgKind::Arg("_".to_owned(), sty.to_string())],
+                    _ => vec![ArgKind::Arg("_".to_owned(), expected_ty.to_string())],
                 };
 
                 if found.len() == expected.len() {
@@ -1284,11 +1285,11 @@
         let span = self.sess.source_map().def_span(span);
         let mut err = struct_span_err!(self.sess, span, E0072,
                                        "recursive type `{}` has infinite size",
-                                       self.item_path_str(type_def_id));
+                                       self.def_path_str(type_def_id));
         err.span_label(span, "recursive type has infinite size");
         err.help(&format!("insert indirection (e.g., a `Box`, `Rc`, or `&`) \
                            at some point to make `{}` representable",
-                          self.item_path_str(type_def_id)));
+                          self.def_path_str(type_def_id)));
         err
     }
 
@@ -1298,7 +1299,7 @@
                                       violations: Vec<ObjectSafetyViolation>)
                                       -> DiagnosticBuilder<'tcx>
     {
-        let trait_str = self.item_path_str(trait_def_id);
+        let trait_str = self.def_path_str(trait_def_id);
         let span = self.sess.source_map().def_span(span);
         let mut err = struct_span_err!(
             self.sess, span, E0038,
@@ -1523,7 +1524,7 @@
                                   region, object_ty));
             }
             ObligationCauseCode::ItemObligation(item_def_id) => {
-                let item_name = tcx.item_path_str(item_def_id);
+                let item_name = tcx.def_path_str(item_def_id);
                 let msg = format!("required by `{}`", item_name);
 
                 if let Some(sp) = tcx.hir().span_if_local(item_def_id) {
@@ -1686,10 +1687,10 @@
             ty::Tuple(ref tys) => ArgKind::Tuple(
                 span,
                 tys.iter()
-                   .map(|ty| ("_".to_owned(), ty.sty.to_string()))
+                   .map(|ty| ("_".to_owned(), ty.to_string()))
                    .collect::<Vec<_>>()
             ),
-            _ => ArgKind::Arg("_".to_owned(), t.sty.to_string()),
+            _ => ArgKind::Arg("_".to_owned(), t.to_string()),
         }
     }
 }
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index df127b9..78c80b4 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -650,7 +650,7 @@
 ) -> bool {
     debug!("type_known_to_meet_bound_modulo_regions(ty={:?}, bound={:?})",
            ty,
-           infcx.tcx.item_path_str(def_id));
+           infcx.tcx.def_path_str(def_id));
 
     let trait_ref = ty::TraitRef {
         def_id,
@@ -665,7 +665,7 @@
 
     let result = infcx.predicate_must_hold_modulo_regions(&obligation);
     debug!("type_known_to_meet_ty={:?} bound={} => {:?}",
-           ty, infcx.tcx.item_path_str(def_id), result);
+           ty, infcx.tcx.def_path_str(def_id), result);
 
     if result && (ty.has_infer_types() || ty.has_closure_types()) {
         // Because of inference "guessing", selection can sometimes claim
@@ -692,13 +692,13 @@
             Ok(()) => {
                 debug!("type_known_to_meet_bound_modulo_regions: ty={:?} bound={} success",
                        ty,
-                       infcx.tcx.item_path_str(def_id));
+                       infcx.tcx.def_path_str(def_id));
                 true
             }
             Err(e) => {
                 debug!("type_known_to_meet_bound_modulo_regions: ty={:?} bound={} errors={:?}",
                        ty,
-                       infcx.tcx.item_path_str(def_id),
+                       infcx.tcx.def_path_str(def_id),
                        e);
                 false
             }
diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs
index e7a5138..1c8ea5c 100644
--- a/src/librustc/traits/object_safety.rs
+++ b/src/librustc/traits/object_safety.rs
@@ -133,7 +133,7 @@
                         hir::CRATE_HIR_ID,
                         *span,
                         &format!("the trait `{}` cannot be made into an object",
-                                 self.item_path_str(trait_def_id)),
+                                 self.def_path_str(trait_def_id)),
                         &violation.error_msg());
                     false
                 } else {
diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs
index c86fd0d..d0acaf6 100644
--- a/src/librustc/traits/on_unimplemented.rs
+++ b/src/librustc/traits/on_unimplemented.rs
@@ -107,7 +107,7 @@
             {
                 if let Some(items) = item.meta_item_list() {
                     if let Ok(subcommand) =
-                        Self::parse(tcx, trait_def_id, &items, item.span, false)
+                        Self::parse(tcx, trait_def_id, &items, item.span(), false)
                     {
                         subcommands.push(subcommand);
                     } else {
@@ -118,7 +118,7 @@
             }
 
             // nothing found
-            parse_error(tcx, item.span,
+            parse_error(tcx, item.span(),
                         "this attribute must have a valid value",
                         "expected value here",
                         Some(r#"eg `#[rustc_on_unimplemented(message="foo")]`"#));
@@ -177,10 +177,12 @@
         for command in self.subcommands.iter().chain(Some(self)).rev() {
             if let Some(ref condition) = command.condition {
                 if !attr::eval_condition(condition, &tcx.sess.parse_sess, &mut |c| {
-                    options.contains(&(
-                        c.name().as_str().to_string(),
-                        c.value_str().map(|s| s.as_str().to_string())
-                    ))
+                    c.ident_str().map_or(false, |name| {
+                        options.contains(&(
+                            name.to_string(),
+                            c.value_str().map(|s| s.as_str().to_string())
+                        ))
+                    })
                 }) {
                     debug!("evaluate: skipping {:?} due to condition", command);
                     continue
@@ -276,7 +278,7 @@
                   -> String
     {
         let name = tcx.item_name(trait_ref.def_id);
-        let trait_str = tcx.item_path_str(trait_ref.def_id);
+        let trait_str = tcx.def_path_str(trait_ref.def_id);
         let generics = tcx.generics_of(trait_ref.def_id);
         let generic_map = generics.params.iter().filter_map(|param| {
             let value = match param.kind {
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index 197bea1..360e232 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -15,7 +15,7 @@
 use crate::hir::def_id::DefId;
 use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
 use crate::infer::type_variable::TypeVariableOrigin;
-use crate::mir::interpret::{GlobalId};
+use crate::mir::interpret::{GlobalId, ConstValue};
 use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap};
 use rustc_macros::HashStable;
 use syntax::ast::Ident;
@@ -397,8 +397,8 @@
         }
     }
 
-    fn fold_const(&mut self, constant: &'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
-        if let ty::LazyConst::Unevaluated(def_id, substs) = *constant {
+    fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
+        if let ConstValue::Unevaluated(def_id, substs) = constant.val {
             let tcx = self.selcx.tcx().global_tcx();
             if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) {
                 if substs.needs_infer() || substs.has_placeholders() {
@@ -411,8 +411,9 @@
                         };
                         if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
                             let substs = tcx.lift_to_global(&substs).unwrap();
+                            let evaluated = tcx.mk_const(evaluated);
                             let evaluated = evaluated.subst(tcx, substs);
-                            return tcx.mk_lazy_const(ty::LazyConst::Evaluated(evaluated));
+                            return evaluated;
                         }
                     }
                 } else {
@@ -424,7 +425,7 @@
                                 promoted: None
                             };
                             if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
-                                return tcx.mk_lazy_const(ty::LazyConst::Evaluated(evaluated));
+                                return tcx.mk_const(evaluated);
                             }
                         }
                     }
@@ -1549,7 +1550,7 @@
         // should have failed in astconv.
         bug!("No associated type `{}` for {}",
              assoc_ty_name,
-             tcx.item_path_str(impl_def_id))
+             tcx.def_path_str(impl_def_id))
     }
 }
 
diff --git a/src/librustc/traits/query/normalize.rs b/src/librustc/traits/query/normalize.rs
index 8a30c18..9940249 100644
--- a/src/librustc/traits/query/normalize.rs
+++ b/src/librustc/traits/query/normalize.rs
@@ -5,7 +5,7 @@
 use crate::infer::at::At;
 use crate::infer::canonical::OriginalQueryValues;
 use crate::infer::{InferCtxt, InferOk};
-use crate::mir::interpret::GlobalId;
+use crate::mir::interpret::{GlobalId, ConstValue};
 use crate::traits::project::Normalized;
 use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
 use crate::ty::fold::{TypeFoldable, TypeFolder};
@@ -188,8 +188,8 @@
         }
     }
 
-    fn fold_const(&mut self, constant: &'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
-        if let ty::LazyConst::Unevaluated(def_id, substs) = *constant {
+    fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
+        if let ConstValue::Unevaluated(def_id, substs) = constant.val {
             let tcx = self.infcx.tcx.global_tcx();
             if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) {
                 if substs.needs_infer() || substs.has_placeholders() {
@@ -202,8 +202,9 @@
                         };
                         if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
                             let substs = tcx.lift_to_global(&substs).unwrap();
+                            let evaluated = tcx.mk_const(evaluated);
                             let evaluated = evaluated.subst(tcx, substs);
-                            return tcx.mk_lazy_const(ty::LazyConst::Evaluated(evaluated));
+                            return evaluated;
                         }
                     }
                 } else {
@@ -215,7 +216,7 @@
                                 promoted: None,
                             };
                             if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
-                                return tcx.mk_lazy_const(ty::LazyConst::Evaluated(evaluated));
+                                return tcx.mk_const(evaluated);
                             }
                         }
                     }
diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs
index a2924cb..c576586 100644
--- a/src/librustc/traits/specialize/mod.rs
+++ b/src/librustc/traits/specialize/mod.rs
@@ -411,7 +411,7 @@
         w.push('<');
         w.push_str(&substs.iter()
             .map(|k| k.to_string())
-            .filter(|k| &k[..] != "'_")
+            .filter(|k| k != "'_")
             .collect::<Vec<_>>().join(", "));
         w.push('>');
     }
diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs
index b5be177..f3a800b 100644
--- a/src/librustc/traits/structural_impls.rs
+++ b/src/librustc/traits/structural_impls.rs
@@ -165,7 +165,8 @@
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         use crate::traits::WhereClause::*;
 
-        // Bypass ppaux because it does not print out anonymous regions.
+        // Bypass `ty::print` because it does not print out anonymous regions.
+        // FIXME(eddyb) implement a custom `PrettyPrinter`, or move this to `ty::print`.
         fn write_region_name<'tcx>(
             r: ty::Region<'tcx>,
             fmt: &mut fmt::Formatter<'_>
@@ -256,7 +257,7 @@
 }
 
 /// Collect names for regions / types bound by a quantified goal / clause.
-/// This collector does not try to do anything clever like in ppaux, it's just used
+/// This collector does not try to do anything clever like in `ty::print`, it's just used
 /// for debug output in tests anyway.
 struct BoundNamesCollector {
     // Just sort by name because `BoundRegion::BrNamed` does not have a `BoundVar` index anyway.
diff --git a/src/librustc/ty/codec.rs b/src/librustc/ty/codec.rs
index 3ab744e..e747434 100644
--- a/src/librustc/ty/codec.rs
+++ b/src/librustc/ty/codec.rs
@@ -247,12 +247,12 @@
 }
 
 #[inline]
-pub fn decode_lazy_const<'a, 'tcx, D>(decoder: &mut D)
-                                 -> Result<&'tcx ty::LazyConst<'tcx>, D::Error>
+pub fn decode_const<'a, 'tcx, D>(decoder: &mut D)
+                                 -> Result<&'tcx ty::Const<'tcx>, D::Error>
     where D: TyDecoder<'a, 'tcx>,
           'tcx: 'a,
 {
-    Ok(decoder.tcx().mk_lazy_const(Decodable::decode(decoder)?))
+    Ok(decoder.tcx().mk_const(Decodable::decode(decoder)?))
 }
 
 #[inline]
@@ -389,10 +389,10 @@
                 }
             }
 
-            impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::ty::LazyConst<'tcx>>
+            impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::ty::Const<'tcx>>
             for $DecoderName<$($typaram),*> {
-                fn specialized_decode(&mut self) -> Result<&'tcx ty::LazyConst<'tcx>, Self::Error> {
-                    decode_lazy_const(self)
+                fn specialized_decode(&mut self) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
+                    decode_const(self)
                 }
             }
 
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index ecf1d8a..6de0a39 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -26,9 +26,9 @@
 use crate::ty::ReprOptions;
 use crate::traits;
 use crate::traits::{Clause, Clauses, GoalKind, Goal, Goals};
-use crate::ty::{self, Ty, TypeAndMut};
+use crate::ty::{self, DefIdTree, Ty, TypeAndMut};
 use crate::ty::{TyS, TyKind, List};
-use crate::ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorSubsts, Region, Const, LazyConst};
+use crate::ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorSubsts, Region, Const};
 use crate::ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate, Predicate};
 use crate::ty::RegionKind;
 use crate::ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid, ConstVid};
@@ -126,7 +126,7 @@
     goal: InternedSet<'tcx, GoalKind<'tcx>>,
     goal_list: InternedSet<'tcx, List<Goal<'tcx>>>,
     projs: InternedSet<'tcx, List<ProjectionKind<'tcx>>>,
-    lazy_const: InternedSet<'tcx, LazyConst<'tcx>>,
+    const_: InternedSet<'tcx, Const<'tcx>>,
 }
 
 impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
@@ -144,7 +144,7 @@
             goal: Default::default(),
             goal_list: Default::default(),
             projs: Default::default(),
-            lazy_const: Default::default(),
+            const_: Default::default(),
         }
     }
 
@@ -874,14 +874,11 @@
                             _ => false,
                         },
 
-                        UnpackedKind::Const(ct) => match ct {
-                            ty::LazyConst::Evaluated(ty::Const {
-                                val: ConstValue::Infer(InferConst::Canonical(debruijn, b)),
-                                ..
-                            }) => {
+                        UnpackedKind::Const(ct) => match ct.val {
+                            ConstValue::Infer(InferConst::Canonical(debruijn, b)) => {
                                 // We only allow a `ty::INNERMOST` index in substitutions.
-                                assert_eq!(*debruijn, ty::INNERMOST);
-                                cvar == *b
+                                assert_eq!(debruijn, ty::INNERMOST);
+                                cvar == b
                             }
                             _ => false,
                         },
@@ -1594,7 +1591,7 @@
         let (suitable_region_binding_scope, bound_region) = match *region {
             ty::ReFree(ref free_region) => (free_region.scope, free_region.bound_region),
             ty::ReEarlyBound(ref ebr) => (
-                self.parent_def_id(ebr.def_id).unwrap(),
+                self.parent(ebr.def_id).unwrap(),
                 ty::BoundRegion::BrNamed(ebr.def_id, ebr.name),
             ),
             _ => return None, // not a free region
@@ -1788,7 +1785,7 @@
 nop_lift!{Ty<'a> => Ty<'tcx>}
 nop_lift!{Region<'a> => Region<'tcx>}
 nop_lift!{Goal<'a> => Goal<'tcx>}
-nop_lift!{&'a LazyConst<'a> => &'tcx LazyConst<'tcx>}
+nop_lift!{&'a Const<'a> => &'tcx Const<'tcx>}
 
 nop_list_lift!{Goal<'a> => Goal<'tcx>}
 nop_list_lift!{Clause<'a> => Clause<'tcx>}
@@ -2274,12 +2271,6 @@
     }
 }
 
-impl<'tcx: 'lcx, 'lcx> Borrow<LazyConst<'lcx>> for Interned<'tcx, LazyConst<'tcx>> {
-    fn borrow<'a>(&'a self) -> &'a LazyConst<'lcx> {
-        &self.0
-    }
-}
-
 impl<'tcx: 'lcx, 'lcx> Borrow<[ExistentialPredicate<'lcx>]>
     for Interned<'tcx, List<ExistentialPredicate<'tcx>>> {
     fn borrow<'a>(&'a self) -> &'a [ExistentialPredicate<'lcx>] {
@@ -2387,7 +2378,7 @@
 direct_interners!('tcx,
     region: mk_region(|r: &RegionKind| r.keep_in_local_tcx()) -> RegionKind,
     goal: mk_goal(|c: &GoalKind<'_>| keep_local(c)) -> GoalKind<'tcx>,
-    lazy_const: mk_lazy_const(|c: &LazyConst<'_>| keep_local(&c)) -> LazyConst<'tcx>
+    const_: mk_const(|c: &Const<'_>| keep_local(&c)) -> Const<'tcx>
 );
 
 macro_rules! slice_interners {
@@ -2575,8 +2566,8 @@
 
     #[inline]
     pub fn mk_array(self, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> {
-        self.mk_ty(Array(ty, self.mk_lazy_const(
-            ty::LazyConst::Evaluated(ty::Const::from_usize(self.global_tcx(), n))
+        self.mk_ty(Array(ty, self.mk_const(
+            ty::Const::from_usize(self.global_tcx(), n)
         )))
     }
 
@@ -2670,11 +2661,11 @@
     }
 
     #[inline]
-    pub fn mk_const_var(self, v: ConstVid<'tcx>, ty: Ty<'tcx>) -> &'tcx LazyConst<'tcx> {
-        self.mk_lazy_const(LazyConst::Evaluated(ty::Const {
+    pub fn mk_const_var(self, v: ConstVid<'tcx>, ty: Ty<'tcx>) -> &'tcx Const<'tcx> {
+        self.mk_const(ty::Const {
             val: ConstValue::Infer(InferConst::Var(v)),
             ty,
-        }))
+        })
     }
 
     #[inline]
@@ -2705,11 +2696,11 @@
         index: u32,
         name: InternedString,
         ty: Ty<'tcx>
-    ) -> &'tcx LazyConst<'tcx> {
-        self.mk_lazy_const(LazyConst::Evaluated(ty::Const {
+    ) -> &'tcx Const<'tcx> {
+        self.mk_const(ty::Const {
             val: ConstValue::Param(ParamConst { index, name }),
             ty,
-        }))
+        })
     }
 
     #[inline]
diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs
index f58e5e4..74d0a29 100644
--- a/src/librustc/ty/error.rs
+++ b/src/librustc/ty/error.rs
@@ -71,6 +71,13 @@
             }
         }
 
+        let br_string = |br: ty::BoundRegion| {
+            match br {
+                ty::BrNamed(_, name) => format!(" {}", name),
+                _ => String::new(),
+            }
+        };
+
         match *self {
             CyclicTy(_) => write!(f, "cyclic type of infinite size"),
             Mismatch => write!(f, "types differ"),
@@ -105,15 +112,13 @@
             }
             RegionsInsufficientlyPolymorphic(br, _) => {
                 write!(f,
-                       "expected bound lifetime parameter{}{}, found concrete lifetime",
-                       if br.is_named() { " " } else { "" },
-                       br)
+                       "expected bound lifetime parameter{}, found concrete lifetime",
+                       br_string(br))
             }
             RegionsOverlyPolymorphic(br, _) => {
                 write!(f,
-                       "expected concrete lifetime, found bound lifetime parameter{}{}",
-                       if br.is_named() { " " } else { "" },
-                       br)
+                       "expected concrete lifetime, found bound lifetime parameter{}",
+                       br_string(br))
             }
             RegionsPlaceholderMismatch => {
                 write!(f, "one type is more general than the other")
@@ -125,9 +130,9 @@
             Traits(values) => ty::tls::with(|tcx| {
                 report_maybe_different(f,
                                        &format!("trait `{}`",
-                                                tcx.item_path_str(values.expected)),
+                                                tcx.def_path_str(values.expected)),
                                        &format!("trait `{}`",
-                                                tcx.item_path_str(values.found)))
+                                                tcx.def_path_str(values.found)))
             }),
             IntMismatch(ref values) => {
                 write!(f, "expected `{:?}`, found `{:?}`",
@@ -146,8 +151,8 @@
             }
             ProjectionMismatched(ref values) => ty::tls::with(|tcx| {
                 write!(f, "expected {}, found {}",
-                       tcx.item_path_str(values.expected),
-                       tcx.item_path_str(values.found))
+                       tcx.def_path_str(values.expected),
+                       tcx.def_path_str(values.found))
             }),
             ProjectionBoundsLength(ref values) => {
                 write!(f, "expected {} associated type bindings, found {}",
@@ -169,14 +174,11 @@
             ty::Uint(_) | ty::Float(_) | ty::Str | ty::Never => self.to_string().into(),
             ty::Tuple(ref tys) if tys.is_empty() => self.to_string().into(),
 
-            ty::Adt(def, _) => format!("{} `{}`", def.descr(), tcx.item_path_str(def.did)).into(),
-            ty::Foreign(def_id) => format!("extern type `{}`", tcx.item_path_str(def_id)).into(),
-            ty::Array(_, n) => match n {
-                ty::LazyConst::Evaluated(n) => match n.assert_usize(tcx) {
-                    Some(n) => format!("array of {} elements", n).into(),
-                    None => "array".into(),
-                },
-                ty::LazyConst::Unevaluated(..) => "array".into(),
+            ty::Adt(def, _) => format!("{} `{}`", def.descr(), tcx.def_path_str(def.did)).into(),
+            ty::Foreign(def_id) => format!("extern type `{}`", tcx.def_path_str(def_id)).into(),
+            ty::Array(_, n) => match n.assert_usize(tcx) {
+                Some(n) => format!("array of {} elements", n).into(),
+                None => "array".into(),
             }
             ty::Slice(_) => "slice".into(),
             ty::RawPtr(_) => "*-ptr".into(),
@@ -185,7 +187,7 @@
                 let tymut_string = tymut.to_string();
                 if tymut_string == "_" ||         //unknown type name,
                    tymut_string.len() > 10 ||     //name longer than saying "reference",
-                   region.to_string() != ""       //... or a complex type
+                   region.to_string() != "'_"     //... or a complex type
                 {
                     format!("{}reference", match mutbl {
                         hir::Mutability::MutMutable => "mutable ",
@@ -199,7 +201,7 @@
             ty::FnPtr(_) => "fn pointer".into(),
             ty::Dynamic(ref inner, ..) => {
                 if let Some(principal) = inner.principal() {
-                    format!("trait {}", tcx.item_path_str(principal.def_id())).into()
+                    format!("trait {}", tcx.def_path_str(principal.def_id())).into()
                 } else {
                     "trait".into()
                 }
diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs
index 64ceb97..7aed2a4 100644
--- a/src/librustc/ty/flags.rs
+++ b/src/librustc/ty/flags.rs
@@ -24,6 +24,12 @@
         result
     }
 
+    pub fn for_const(c: &ty::Const<'_>) -> TypeFlags {
+        let mut result = FlagComputation::new();
+        result.add_const(c);
+        result.flags
+    }
+
     fn add_flags(&mut self, flags: TypeFlags) {
         self.flags = self.flags | (flags & TypeFlags::NOMINAL_FLAGS);
     }
@@ -173,10 +179,7 @@
 
             &ty::Array(tt, len) => {
                 self.add_ty(tt);
-                if let ty::LazyConst::Unevaluated(_, substs) = len {
-                    self.add_flags(TypeFlags::HAS_PROJECTION);
-                    self.add_substs(substs);
-                }
+                self.add_const(len);
             }
 
             &ty::Slice(tt) => {
@@ -233,19 +236,26 @@
         }
     }
 
-    fn add_const(&mut self, c: &ty::LazyConst<'_>) {
-        match c {
-            ty::LazyConst::Unevaluated(_, substs) => self.add_substs(substs),
-            // Only done to add the binder for the type. The type flags are
-            // included in `Const::type_flags`.
-            ty::LazyConst::Evaluated(ty::Const { ty, val }) => {
-                self.add_ty(ty);
-                if let ConstValue::Infer(InferConst::Canonical(debruijn, _)) = val {
-                    self.add_binder(*debruijn)
+    fn add_const(&mut self, c: &ty::Const<'_>) {
+        self.add_ty(c.ty);
+        match c.val {
+            ConstValue::Unevaluated(_, substs) => {
+                self.add_substs(substs);
+                self.add_flags(TypeFlags::HAS_NORMALIZABLE_PROJECTION | TypeFlags::HAS_PROJECTION);
+            },
+            ConstValue::Infer(infer) => {
+                self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES | TypeFlags::HAS_CT_INFER);
+                match infer {
+                    InferConst::Fresh(_) => {}
+                    InferConst::Canonical(debruijn, _) => self.add_binder(debruijn),
+                    InferConst::Var(_) => self.add_flags(TypeFlags::KEEP_IN_LOCAL_TCX),
                 }
             }
+            ConstValue::Param(_) => {
+                self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES | TypeFlags::HAS_PARAMS);
+            }
+            _ => {},
         }
-        self.add_flags(c.type_flags());
     }
 
     fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection<'_>) {
diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs
index 7f77d03..321e552 100644
--- a/src/librustc/ty/fold.rs
+++ b/src/librustc/ty/fold.rs
@@ -32,7 +32,7 @@
 //! looking for, and does not need to visit anything else.
 
 use crate::hir::def_id::DefId;
-use crate::ty::{self, Binder, Ty, TyCtxt, TypeFlags};
+use crate::ty::{self, Binder, Ty, TyCtxt, TypeFlags, flags::FlagComputation};
 
 use std::collections::BTreeMap;
 use std::fmt;
@@ -167,7 +167,7 @@
         r.super_fold_with(self)
     }
 
-    fn fold_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
+    fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
         c.super_fold_with(self)
     }
 }
@@ -185,7 +185,7 @@
         r.super_visit_with(self)
     }
 
-    fn visit_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> bool {
+    fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
         c.super_visit_with(self)
     }
 }
@@ -842,14 +842,10 @@
         flags.intersects(self.flags)
     }
 
-    fn visit_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> bool {
-        let flags = c.type_flags();
+    fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
+        let flags = FlagComputation::for_const(c);
         debug!("HasTypeFlagsVisitor: c={:?} c.flags={:?} self.flags={:?}", c, flags, self.flags);
-        if flags.intersects(self.flags) {
-            true
-        } else {
-            c.super_visit_with(self)
-        }
+        flags.intersects(self.flags) || c.super_visit_with(self)
     }
 }
 
diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs
index 33ec9c8..d732f3f 100644
--- a/src/librustc/ty/inhabitedness/mod.rs
+++ b/src/librustc/ty/inhabitedness/mod.rs
@@ -1,6 +1,6 @@
 use crate::ty::context::TyCtxt;
 use crate::ty::{AdtDef, VariantDef, FieldDef, Ty, TyS};
-use crate::ty::{self, DefId, SubstsRef};
+use crate::ty::{DefId, SubstsRef};
 use crate::ty::{AdtKind, Visibility};
 use crate::ty::TyKind::*;
 
@@ -212,17 +212,12 @@
                 }))
             }
 
-            Array(ty, len) => {
-                match len {
-                    ty::LazyConst::Unevaluated(..) => DefIdForest::empty(),
-                    ty::LazyConst::Evaluated(len) => match len.assert_usize(tcx) {
-                        // If the array is definitely non-empty, it's uninhabited if
-                        // the type of its elements is uninhabited.
-                        Some(n) if n != 0 => ty.uninhabited_from(tcx),
-                        _ => DefIdForest::empty()
-                    },
-                }
-            }
+            Array(ty, len) => match len.assert_usize(tcx) {
+                // If the array is definitely non-empty, it's uninhabited if
+                // the type of its elements is uninhabited.
+                Some(n) if n != 0 => ty.uninhabited_from(tcx),
+                _ => DefIdForest::empty()
+            },
 
             // References to uninitialised memory is valid for any type, including
             // uninhabited types, in unsafe code, so we treat all references as
diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
index e0b7bbc..995e85f 100644
--- a/src/librustc/ty/instance.rs
+++ b/src/librustc/ty/instance.rs
@@ -1,10 +1,11 @@
 use crate::hir::Unsafety;
+use crate::hir::def::Namespace;
 use crate::hir::def_id::DefId;
 use crate::ty::{self, Ty, PolyFnSig, TypeFoldable, SubstsRef, TyCtxt};
+use crate::ty::print::{FmtPrinter, Printer};
 use crate::traits;
 use rustc_target::spec::abi::Abi;
 use rustc_macros::HashStable;
-use crate::util::ppaux;
 
 use std::fmt;
 use std::iter;
@@ -175,7 +176,13 @@
 
 impl<'tcx> fmt::Display for Instance<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        ppaux::parameterized(f, self.substs, self.def_id(), &[])?;
+        ty::tls::with(|tcx| {
+            let substs = tcx.lift(&self.substs).expect("could not lift for printing");
+            FmtPrinter::new(tcx, &mut *f, Namespace::ValueNS)
+                .print_def_path(self.def_id(), substs)?;
+            Ok(())
+        })?;
+
         match self.def {
             InstanceDef::Item(_) => Ok(()),
             InstanceDef::VtableShim(_) => {
diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs
deleted file mode 100644
index 26e2705..0000000
--- a/src/librustc/ty/item_path.rs
+++ /dev/null
@@ -1,573 +0,0 @@
-use crate::hir::map::DefPathData;
-use crate::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
-use crate::ty::{self, DefIdTree, Ty, TyCtxt};
-use crate::middle::cstore::{ExternCrate, ExternCrateSource};
-use syntax::ast;
-use syntax::symbol::{keywords, LocalInternedString, Symbol};
-
-use std::cell::Cell;
-use std::fmt::Debug;
-
-thread_local! {
-    static FORCE_ABSOLUTE: Cell<bool> = Cell::new(false);
-    static FORCE_IMPL_FILENAME_LINE: Cell<bool> = Cell::new(false);
-    static SHOULD_PREFIX_WITH_CRATE: Cell<bool> = Cell::new(false);
-}
-
-/// Enforces that item_path_str always returns an absolute path and
-/// also enables "type-based" impl paths. This is used when building
-/// symbols that contain types, where we want the crate name to be
-/// part of the symbol.
-pub fn with_forced_absolute_paths<F: FnOnce() -> R, R>(f: F) -> R {
-    FORCE_ABSOLUTE.with(|force| {
-        let old = force.get();
-        force.set(true);
-        let result = f();
-        force.set(old);
-        result
-    })
-}
-
-/// Force us to name impls with just the filename/line number. We
-/// normally try to use types. But at some points, notably while printing
-/// cycle errors, this can result in extra or suboptimal error output,
-/// so this variable disables that check.
-pub fn with_forced_impl_filename_line<F: FnOnce() -> R, R>(f: F) -> R {
-    FORCE_IMPL_FILENAME_LINE.with(|force| {
-        let old = force.get();
-        force.set(true);
-        let result = f();
-        force.set(old);
-        result
-    })
-}
-
-/// Adds the `crate::` prefix to paths where appropriate.
-pub fn with_crate_prefix<F: FnOnce() -> R, R>(f: F) -> R {
-    SHOULD_PREFIX_WITH_CRATE.with(|flag| {
-        let old = flag.get();
-        flag.set(true);
-        let result = f();
-        flag.set(old);
-        result
-    })
-}
-
-impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
-    /// Returns a string identifying this `DefId`. This string is
-    /// suitable for user output. It is relative to the current crate
-    /// root, unless with_forced_absolute_paths was used.
-    pub fn item_path_str(self, def_id: DefId) -> String {
-        let mode = FORCE_ABSOLUTE.with(|force| {
-            if force.get() {
-                RootMode::Absolute
-            } else {
-                RootMode::Local
-            }
-        });
-        let mut buffer = LocalPathBuffer::new(mode);
-        debug!("item_path_str: buffer={:?} def_id={:?}", buffer, def_id);
-        self.push_item_path(&mut buffer, def_id, false);
-        buffer.into_string()
-    }
-
-    /// Returns a string identifying this local node-id.
-    pub fn node_path_str(self, id: ast::NodeId) -> String {
-        self.item_path_str(self.hir().local_def_id(id))
-    }
-
-    /// Returns a string identifying this def-id. This string is
-    /// suitable for user output. It always begins with a crate identifier.
-    pub fn absolute_item_path_str(self, def_id: DefId) -> String {
-        let mut buffer = LocalPathBuffer::new(RootMode::Absolute);
-        debug!("absolute_item_path_str: buffer={:?} def_id={:?}", buffer, def_id);
-        self.push_item_path(&mut buffer, def_id, false);
-        buffer.into_string()
-    }
-
-    /// Returns the "path" to a particular crate. This can proceed in
-    /// various ways, depending on the `root_mode` of the `buffer`.
-    /// (See `RootMode` enum for more details.)
-    ///
-    /// `pushed_prelude_crate` argument should be `true` when the buffer
-    /// has had a prelude crate pushed to it. If this is the case, then
-    /// we do not want to prepend `crate::` (as that would not be a valid
-    /// path).
-    pub fn push_krate_path<T>(self, buffer: &mut T, cnum: CrateNum, pushed_prelude_crate: bool)
-        where T: ItemPathBuffer + Debug
-    {
-        debug!(
-            "push_krate_path: buffer={:?} cnum={:?} LOCAL_CRATE={:?}",
-            buffer, cnum, LOCAL_CRATE
-        );
-        match *buffer.root_mode() {
-            RootMode::Local => {
-                // In local mode, when we encounter a crate other than
-                // LOCAL_CRATE, execution proceeds in one of two ways:
-                //
-                // 1. for a direct dependency, where user added an
-                //    `extern crate` manually, we put the `extern
-                //    crate` as the parent. So you wind up with
-                //    something relative to the current crate.
-                // 2. for an extern inferred from a path or an indirect crate,
-                //    where there is no explicit `extern crate`, we just prepend
-                //    the crate name.
-                //
-                // Returns `None` for the local crate.
-                if cnum != LOCAL_CRATE {
-                    let opt_extern_crate = self.extern_crate(cnum.as_def_id());
-                    if let Some(ExternCrate {
-                        src: ExternCrateSource::Extern(def_id),
-                        direct: true,
-                        ..
-                    }) = *opt_extern_crate
-                    {
-                        debug!("push_krate_path: def_id={:?}", def_id);
-                        self.push_item_path(buffer, def_id, pushed_prelude_crate);
-                    } else {
-                        let name = self.crate_name(cnum).as_str();
-                        debug!("push_krate_path: name={:?}", name);
-                        buffer.push(&name);
-                    }
-                } else if self.sess.rust_2018() && !pushed_prelude_crate {
-                    SHOULD_PREFIX_WITH_CRATE.with(|flag| {
-                        // We only add the `crate::` keyword where appropriate. In particular,
-                        // when we've not previously pushed a prelude crate to this path.
-                        if flag.get() {
-                            buffer.push(&keywords::Crate.name().as_str())
-                        }
-                    })
-                }
-            }
-            RootMode::Absolute => {
-                // In absolute mode, just write the crate name
-                // unconditionally.
-                let name = self.original_crate_name(cnum).as_str();
-                debug!("push_krate_path: original_name={:?}", name);
-                buffer.push(&name);
-            }
-        }
-    }
-
-    /// If possible, this pushes a global path resolving to `external_def_id` that is visible
-    /// from at least one local module and returns true. If the crate defining `external_def_id` is
-    /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`.
-    pub fn try_push_visible_item_path<T>(
-        self,
-        buffer: &mut T,
-        external_def_id: DefId,
-        pushed_prelude_crate: bool,
-    ) -> bool
-        where T: ItemPathBuffer + Debug
-    {
-        debug!(
-            "try_push_visible_item_path: buffer={:?} external_def_id={:?}",
-            buffer, external_def_id
-        );
-        let visible_parent_map = self.visible_parent_map(LOCAL_CRATE);
-
-        let (mut cur_def, mut cur_path) = (external_def_id, Vec::<LocalInternedString>::new());
-        loop {
-            debug!(
-                "try_push_visible_item_path: cur_def={:?} cur_path={:?} CRATE_DEF_INDEX={:?}",
-                cur_def, cur_path, CRATE_DEF_INDEX,
-            );
-            // If `cur_def` is a direct or injected extern crate, push the path to the crate
-            // followed by the path to the item within the crate and return.
-            if cur_def.index == CRATE_DEF_INDEX {
-                match *self.extern_crate(cur_def) {
-                    Some(ExternCrate {
-                        src: ExternCrateSource::Extern(def_id),
-                        direct: true,
-                        ..
-                    }) => {
-                        debug!("try_push_visible_item_path: def_id={:?}", def_id);
-                        self.push_item_path(buffer, def_id, pushed_prelude_crate);
-                        cur_path.iter().rev().for_each(|segment| buffer.push(&segment));
-                        return true;
-                    }
-                    None => {
-                        buffer.push(&self.crate_name(cur_def.krate).as_str());
-                        cur_path.iter().rev().for_each(|segment| buffer.push(&segment));
-                        return true;
-                    }
-                    _ => {},
-                }
-            }
-
-            let mut cur_def_key = self.def_key(cur_def);
-            debug!("try_push_visible_item_path: cur_def_key={:?}", cur_def_key);
-
-            // For a UnitStruct or TupleStruct we want the name of its parent rather than <unnamed>.
-            if let DefPathData::StructCtor = cur_def_key.disambiguated_data.data {
-                let parent = DefId {
-                    krate: cur_def.krate,
-                    index: cur_def_key.parent.expect("DefPathData::StructCtor missing a parent"),
-                };
-
-                cur_def_key = self.def_key(parent);
-            }
-
-            let visible_parent = visible_parent_map.get(&cur_def).cloned();
-            let actual_parent = self.parent(cur_def);
-
-            let data = cur_def_key.disambiguated_data.data;
-            debug!(
-                "try_push_visible_item_path: data={:?} visible_parent={:?} actual_parent={:?}",
-                data, visible_parent, actual_parent,
-            );
-            let symbol = match data {
-                // In order to output a path that could actually be imported (valid and visible),
-                // we need to handle re-exports correctly.
-                //
-                // For example, take `std::os::unix::process::CommandExt`, this trait is actually
-                // defined at `std::sys::unix::ext::process::CommandExt` (at time of writing).
-                //
-                // `std::os::unix` rexports the contents of `std::sys::unix::ext`. `std::sys` is
-                // private so the "true" path to `CommandExt` isn't accessible.
-                //
-                // In this case, the `visible_parent_map` will look something like this:
-                //
-                // (child) -> (parent)
-                // `std::sys::unix::ext::process::CommandExt` -> `std::sys::unix::ext::process`
-                // `std::sys::unix::ext::process` -> `std::sys::unix::ext`
-                // `std::sys::unix::ext` -> `std::os`
-                //
-                // This is correct, as the visible parent of `std::sys::unix::ext` is in fact
-                // `std::os`.
-                //
-                // When printing the path to `CommandExt` and looking at the `cur_def_key` that
-                // corresponds to `std::sys::unix::ext`, we would normally print `ext` and then go
-                // to the parent - resulting in a mangled path like
-                // `std::os::ext::process::CommandExt`.
-                //
-                // Instead, we must detect that there was a re-export and instead print `unix`
-                // (which is the name `std::sys::unix::ext` was re-exported as in `std::os`). To
-                // do this, we compare the parent of `std::sys::unix::ext` (`std::sys::unix`) with
-                // the visible parent (`std::os`). If these do not match, then we iterate over
-                // the children of the visible parent (as was done when computing
-                // `visible_parent_map`), looking for the specific child we currently have and then
-                // have access to the re-exported name.
-                DefPathData::Module(actual_name) |
-                DefPathData::TypeNs(actual_name) if visible_parent != actual_parent => {
-                    visible_parent
-                        .and_then(|parent| {
-                            self.item_children(parent)
-                                .iter()
-                                .find(|child| child.def.def_id() == cur_def)
-                                .map(|child| child.ident.as_str())
-                        })
-                        .unwrap_or_else(|| actual_name.as_str())
-                },
-                _ => {
-                    data.get_opt_name().map(|n| n.as_str()).unwrap_or_else(|| {
-                        // Re-exported `extern crate` (#43189).
-                        if let DefPathData::CrateRoot = data {
-                            self.original_crate_name(cur_def.krate).as_str()
-                        } else {
-                            Symbol::intern("<unnamed>").as_str()
-                        }
-                    })
-                },
-            };
-            debug!("try_push_visible_item_path: symbol={:?}", symbol);
-            cur_path.push(symbol);
-
-            match visible_parent {
-                Some(def) => cur_def = def,
-                None => return false,
-            };
-        }
-    }
-
-    pub fn push_item_path<T>(self, buffer: &mut T, def_id: DefId, pushed_prelude_crate: bool)
-        where T: ItemPathBuffer + Debug
-    {
-        debug!(
-            "push_item_path: buffer={:?} def_id={:?} pushed_prelude_crate={:?}",
-            buffer, def_id, pushed_prelude_crate
-        );
-        match *buffer.root_mode() {
-            RootMode::Local if !def_id.is_local() =>
-                if self.try_push_visible_item_path(buffer, def_id, pushed_prelude_crate) { return },
-            _ => {}
-        }
-
-        let key = self.def_key(def_id);
-        debug!("push_item_path: key={:?}", key);
-        match key.disambiguated_data.data {
-            DefPathData::CrateRoot => {
-                assert!(key.parent.is_none());
-                self.push_krate_path(buffer, def_id.krate, pushed_prelude_crate);
-            }
-
-            DefPathData::Impl => {
-                self.push_impl_path(buffer, def_id, pushed_prelude_crate);
-            }
-
-            // Unclear if there is any value in distinguishing these.
-            // Probably eventually (and maybe we would even want
-            // finer-grained distinctions, e.g., between enum/struct).
-            data @ DefPathData::Misc |
-            data @ DefPathData::TypeNs(..) |
-            data @ DefPathData::Trait(..) |
-            data @ DefPathData::TraitAlias(..) |
-            data @ DefPathData::AssocTypeInTrait(..) |
-            data @ DefPathData::AssocTypeInImpl(..) |
-            data @ DefPathData::AssocExistentialInImpl(..) |
-            data @ DefPathData::ValueNs(..) |
-            data @ DefPathData::Module(..) |
-            data @ DefPathData::TypeParam(..) |
-            data @ DefPathData::LifetimeParam(..) |
-            data @ DefPathData::ConstParam(..) |
-            data @ DefPathData::EnumVariant(..) |
-            data @ DefPathData::Field(..) |
-            data @ DefPathData::AnonConst |
-            data @ DefPathData::MacroDef(..) |
-            data @ DefPathData::ClosureExpr |
-            data @ DefPathData::ImplTrait |
-            data @ DefPathData::GlobalMetaData(..) => {
-                let parent_did = self.parent_def_id(def_id).unwrap();
-
-                // Keep track of whether we are one recursion away from the `CrateRoot` and
-                // pushing the name of a prelude crate. If we are, we'll want to know this when
-                // printing the `CrateRoot` so we don't prepend a `crate::` to paths.
-                let mut is_prelude_crate = false;
-                if let DefPathData::CrateRoot = self.def_key(parent_did).disambiguated_data.data {
-                    if self.extern_prelude.contains_key(&data.as_interned_str().as_symbol()) {
-                        is_prelude_crate = true;
-                    }
-                }
-
-                self.push_item_path(
-                    buffer, parent_did, pushed_prelude_crate || is_prelude_crate
-                );
-                buffer.push(&data.as_interned_str().as_symbol().as_str());
-            },
-
-            DefPathData::StructCtor => { // present `X` instead of `X::{{constructor}}`
-                let parent_def_id = self.parent_def_id(def_id).unwrap();
-                self.push_item_path(buffer, parent_def_id, pushed_prelude_crate);
-            }
-        }
-    }
-
-    fn push_impl_path<T>(
-        self,
-         buffer: &mut T,
-         impl_def_id: DefId,
-         pushed_prelude_crate: bool,
-    )
-        where T: ItemPathBuffer + Debug
-    {
-        debug!("push_impl_path: buffer={:?} impl_def_id={:?}", buffer, impl_def_id);
-        let parent_def_id = self.parent_def_id(impl_def_id).unwrap();
-
-        // Always use types for non-local impls, where types are always
-        // available, and filename/line-number is mostly uninteresting.
-        let use_types = !impl_def_id.is_local() || {
-            // Otherwise, use filename/line-number if forced.
-            let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get());
-            !force_no_types
-        };
-
-        if !use_types {
-            return self.push_impl_path_fallback(buffer, impl_def_id, pushed_prelude_crate);
-        }
-
-        // Decide whether to print the parent path for the impl.
-        // Logically, since impls are global, it's never needed, but
-        // users may find it useful. Currently, we omit the parent if
-        // the impl is either in the same module as the self-type or
-        // as the trait.
-        let self_ty = self.type_of(impl_def_id);
-        let in_self_mod = match characteristic_def_id_of_type(self_ty) {
-            None => false,
-            Some(ty_def_id) => self.parent_def_id(ty_def_id) == Some(parent_def_id),
-        };
-
-        let impl_trait_ref = self.impl_trait_ref(impl_def_id);
-        let in_trait_mod = match impl_trait_ref {
-            None => false,
-            Some(trait_ref) => self.parent_def_id(trait_ref.def_id) == Some(parent_def_id),
-        };
-
-        if !in_self_mod && !in_trait_mod {
-            // If the impl is not co-located with either self-type or
-            // trait-type, then fallback to a format that identifies
-            // the module more clearly.
-            self.push_item_path(buffer, parent_def_id, pushed_prelude_crate);
-            if let Some(trait_ref) = impl_trait_ref {
-                buffer.push(&format!("<impl {} for {}>", trait_ref, self_ty));
-            } else {
-                buffer.push(&format!("<impl {}>", self_ty));
-            }
-            return;
-        }
-
-        // Otherwise, try to give a good form that would be valid language
-        // syntax. Preferably using associated item notation.
-
-        if let Some(trait_ref) = impl_trait_ref {
-            // Trait impls.
-            buffer.push(&format!("<{} as {}>", self_ty, trait_ref));
-            return;
-        }
-
-        // Inherent impls. Try to print `Foo::bar` for an inherent
-        // impl on `Foo`, but fallback to `<Foo>::bar` if self-type is
-        // anything other than a simple path.
-        match self_ty.sty {
-            ty::Adt(adt_def, substs) => {
-                if substs.types().next().is_none() { // ignore regions
-                    self.push_item_path(buffer, adt_def.did, pushed_prelude_crate);
-                } else {
-                    buffer.push(&format!("<{}>", self_ty));
-                }
-            }
-
-            ty::Foreign(did) => self.push_item_path(buffer, did, pushed_prelude_crate),
-
-            ty::Bool |
-            ty::Char |
-            ty::Int(_) |
-            ty::Uint(_) |
-            ty::Float(_) |
-            ty::Str => {
-                buffer.push(&self_ty.to_string());
-            }
-
-            _ => {
-                buffer.push(&format!("<{}>", self_ty));
-            }
-        }
-    }
-
-    fn push_impl_path_fallback<T>(
-        self,
-        buffer: &mut T,
-        impl_def_id: DefId,
-        pushed_prelude_crate: bool,
-    )
-        where T: ItemPathBuffer + Debug
-    {
-        // If no type info is available, fall back to
-        // pretty printing some span information. This should
-        // only occur very early in the compiler pipeline.
-        let parent_def_id = self.parent_def_id(impl_def_id).unwrap();
-        self.push_item_path(buffer, parent_def_id, pushed_prelude_crate);
-        let hir_id = self.hir().as_local_hir_id(impl_def_id).unwrap();
-        let item = self.hir().expect_item_by_hir_id(hir_id);
-        let span_str = self.sess.source_map().span_to_string(item.span);
-        buffer.push(&format!("<impl at {}>", span_str));
-    }
-
-    /// Returns the `DefId` of `def_id`'s parent in the def tree. If
-    /// this returns `None`, then `def_id` represents a crate root or
-    /// inlined root.
-    pub fn parent_def_id(self, def_id: DefId) -> Option<DefId> {
-        let key = self.def_key(def_id);
-        key.parent.map(|index| DefId { krate: def_id.krate, index: index })
-    }
-}
-
-/// As a heuristic, when we see an impl, if we see that the
-/// 'self type' is a type defined in the same module as the impl,
-/// we can omit including the path to the impl itself. This
-/// function tries to find a "characteristic `DefId`" for a
-/// type. It's just a heuristic so it makes some questionable
-/// decisions and we may want to adjust it later.
-pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
-    match ty.sty {
-        ty::Adt(adt_def, _) => Some(adt_def.did),
-
-        ty::Dynamic(data, ..) => data.principal_def_id(),
-
-        ty::Array(subty, _) |
-        ty::Slice(subty) => characteristic_def_id_of_type(subty),
-
-        ty::RawPtr(mt) => characteristic_def_id_of_type(mt.ty),
-
-        ty::Ref(_, ty, _) => characteristic_def_id_of_type(ty),
-
-        ty::Tuple(ref tys) => tys.iter()
-                                   .filter_map(|ty| characteristic_def_id_of_type(ty))
-                                   .next(),
-
-        ty::FnDef(def_id, _) |
-        ty::Closure(def_id, _) |
-        ty::Generator(def_id, _, _) |
-        ty::Foreign(def_id) => Some(def_id),
-
-        ty::Bool |
-        ty::Char |
-        ty::Int(_) |
-        ty::Uint(_) |
-        ty::Str |
-        ty::FnPtr(_) |
-        ty::Projection(_) |
-        ty::Placeholder(..) |
-        ty::UnnormalizedProjection(..) |
-        ty::Param(_) |
-        ty::Opaque(..) |
-        ty::Infer(_) |
-        ty::Bound(..) |
-        ty::Error |
-        ty::GeneratorWitness(..) |
-        ty::Never |
-        ty::Float(_) => None,
-    }
-}
-
-/// Unifying Trait for different kinds of item paths we might
-/// construct. The basic interface is that components get pushed: the
-/// instance can also customize how we handle the root of a crate.
-pub trait ItemPathBuffer {
-    fn root_mode(&self) -> &RootMode;
-    fn push(&mut self, text: &str);
-}
-
-#[derive(Debug)]
-pub enum RootMode {
-    /// Try to make a path relative to the local crate. In
-    /// particular, local paths have no prefix, and if the path comes
-    /// from an extern crate, start with the path to the `extern
-    /// crate` declaration.
-    Local,
-
-    /// Always prepend the crate name to the path, forming an absolute
-    /// path from within a given set of crates.
-    Absolute,
-}
-
-#[derive(Debug)]
-struct LocalPathBuffer {
-    root_mode: RootMode,
-    str: String,
-}
-
-impl LocalPathBuffer {
-    fn new(root_mode: RootMode) -> LocalPathBuffer {
-        LocalPathBuffer {
-            root_mode,
-            str: String::new(),
-        }
-    }
-
-    fn into_string(self) -> String {
-        self.str
-    }
-}
-
-impl ItemPathBuffer for LocalPathBuffer {
-    fn root_mode(&self) -> &RootMode {
-        &self.root_mode
-    }
-
-    fn push(&mut self, text: &str) {
-        if !self.str.is_empty() {
-            self.str.push_str("::");
-        }
-        self.str.push_str(text);
-    }
-}
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 68bdae7..298af1d 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -59,7 +59,7 @@
 pub use self::sty::{ClosureSubsts, GeneratorSubsts, UpvarSubsts, TypeAndMut};
 pub use self::sty::{TraitRef, TyKind, PolyTraitRef};
 pub use self::sty::{ExistentialTraitRef, PolyExistentialTraitRef};
-pub use self::sty::{ExistentialProjection, PolyExistentialProjection, Const, LazyConst};
+pub use self::sty::{ExistentialProjection, PolyExistentialProjection, Const};
 pub use self::sty::{BoundRegion, EarlyBoundRegion, FreeRegion, Region};
 pub use self::sty::RegionKind;
 pub use self::sty::{TyVid, IntVid, FloatVid, ConstVid, RegionVid};
@@ -95,10 +95,10 @@
 pub mod fast_reject;
 pub mod fold;
 pub mod inhabitedness;
-pub mod item_path;
 pub mod layout;
 pub mod _match;
 pub mod outlives;
+pub mod print;
 pub mod query;
 pub mod relate;
 pub mod steal;
@@ -1000,7 +1000,7 @@
 }
 
 /// Bounds on generics.
-#[derive(Clone, Default, HashStable)]
+#[derive(Clone, Default, Debug, HashStable)]
 pub struct GenericPredicates<'tcx> {
     pub parent: Option<DefId>,
     pub predicates: Vec<(Predicate<'tcx>, Span)>,
@@ -1505,7 +1505,7 @@
 /// `[[], [U:Bar<T>]]`. Now if there were some particular reference
 /// like `Foo<isize,usize>`, then the `InstantiatedPredicates` would be `[[],
 /// [usize:Bar<isize>]]`.
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 pub struct InstantiatedPredicates<'tcx> {
     pub predicates: Vec<Predicate<'tcx>>,
 }
@@ -2055,7 +2055,7 @@
         }
 
         // This is here instead of layout because the choice must make it into metadata.
-        if !tcx.consider_optimizing(|| format!("Reorder fields of {:?}", tcx.item_path_str(did))) {
+        if !tcx.consider_optimizing(|| format!("Reorder fields of {:?}", tcx.def_path_str(did))) {
             flags.insert(ReprFlags::IS_LINEAR);
         }
         ReprOptions { int: size, align: max_align, pack: min_pack, flags: flags }
@@ -2892,14 +2892,14 @@
     pub fn expect_variant_def(self, def: Def) -> &'tcx VariantDef {
         match def {
             Def::Variant(did) | Def::VariantCtor(did, ..) => {
-                let enum_did = self.parent_def_id(did).unwrap();
+                let enum_did = self.parent(did).unwrap();
                 self.adt_def(enum_did).variant_with_id(did)
             }
             Def::Struct(did) | Def::Union(did) => {
                 self.adt_def(did).non_enum_variant()
             }
             Def::StructCtor(ctor_did, ..) => {
-                let did = self.parent_def_id(ctor_did).expect("struct ctor has no parent");
+                let did = self.parent(ctor_did).expect("struct ctor has no parent");
                 self.adt_def(did).non_enum_variant()
             }
             _ => bug!("expect_variant_def used with unexpected def {:?}", def)
diff --git a/src/librustc/ty/print/mod.rs b/src/librustc/ty/print/mod.rs
new file mode 100644
index 0000000..ef30a403
--- /dev/null
+++ b/src/librustc/ty/print/mod.rs
@@ -0,0 +1,327 @@
+use crate::hir::map::{DefPathData, DisambiguatedDefPathData};
+use crate::hir::def_id::{CrateNum, DefId};
+use crate::ty::{self, DefIdTree, Ty, TyCtxt};
+use crate::ty::subst::{Kind, Subst};
+
+use rustc_data_structures::fx::FxHashSet;
+
+// `pretty` is a separate module only for organization.
+mod pretty;
+pub use self::pretty::*;
+
+pub trait Print<'gcx, 'tcx, P> {
+    type Output;
+    type Error;
+
+    fn print(&self, cx: P) -> Result<Self::Output, Self::Error>;
+}
+
+/// Interface for outputting user-facing "type-system entities"
+/// (paths, types, lifetimes, constants, etc.) as a side-effect
+/// (e.g. formatting, like `PrettyPrinter` implementors do) or by
+/// constructing some alternative representation (e.g. an AST),
+/// which the associated types allow passing through the methods.
+///
+/// For pretty-printing/formatting in particular, see `PrettyPrinter`.
+// FIXME(eddyb) find a better name, this is more general than "printing".
+pub trait Printer<'gcx: 'tcx, 'tcx>: Sized {
+    type Error;
+
+    type Path;
+    type Region;
+    type Type;
+    type DynExistential;
+
+    fn tcx(&'a self) -> TyCtxt<'a, 'gcx, 'tcx>;
+
+    fn print_def_path(
+        self,
+        def_id: DefId,
+        substs: &'tcx [Kind<'tcx>],
+    ) -> Result<Self::Path, Self::Error> {
+        self.default_print_def_path(def_id, substs)
+    }
+    fn print_impl_path(
+        self,
+        impl_def_id: DefId,
+        substs: &'tcx [Kind<'tcx>],
+        self_ty: Ty<'tcx>,
+        trait_ref: Option<ty::TraitRef<'tcx>>,
+    ) -> Result<Self::Path, Self::Error> {
+        self.default_print_impl_path(impl_def_id, substs, self_ty, trait_ref)
+    }
+
+    fn print_region(
+        self,
+        region: ty::Region<'_>,
+    ) -> Result<Self::Region, Self::Error>;
+
+    fn print_type(
+        self,
+        ty: Ty<'tcx>,
+    ) -> Result<Self::Type, Self::Error>;
+
+    fn print_dyn_existential(
+        self,
+        predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
+    ) -> Result<Self::DynExistential, Self::Error>;
+
+    fn path_crate(
+        self,
+        cnum: CrateNum,
+    ) -> Result<Self::Path, Self::Error>;
+    fn path_qualified(
+        self,
+        self_ty: Ty<'tcx>,
+        trait_ref: Option<ty::TraitRef<'tcx>>,
+    ) -> Result<Self::Path, Self::Error>;
+
+    fn path_append_impl(
+        self,
+        print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+        disambiguated_data: &DisambiguatedDefPathData,
+        self_ty: Ty<'tcx>,
+        trait_ref: Option<ty::TraitRef<'tcx>>,
+    ) -> Result<Self::Path, Self::Error>;
+    fn path_append(
+        self,
+        print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+        disambiguated_data: &DisambiguatedDefPathData,
+    ) -> Result<Self::Path, Self::Error>;
+    fn path_generic_args(
+        self,
+        print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+        args: &[Kind<'tcx>],
+    ) -> Result<Self::Path, Self::Error>;
+
+    // Defaults (should not be overriden):
+
+    fn default_print_def_path(
+        self,
+        def_id: DefId,
+        substs: &'tcx [Kind<'tcx>],
+    ) -> Result<Self::Path, Self::Error> {
+        debug!("default_print_def_path: def_id={:?}, substs={:?}", def_id, substs);
+        let key = self.tcx().def_key(def_id);
+        debug!("default_print_def_path: key={:?}", key);
+
+        match key.disambiguated_data.data {
+            DefPathData::CrateRoot => {
+                assert!(key.parent.is_none());
+                self.path_crate(def_id.krate)
+            }
+
+            DefPathData::Impl => {
+                let generics = self.tcx().generics_of(def_id);
+                let mut self_ty = self.tcx().type_of(def_id);
+                let mut impl_trait_ref = self.tcx().impl_trait_ref(def_id);
+                if substs.len() >= generics.count() {
+                    self_ty = self_ty.subst(self.tcx(), substs);
+                    impl_trait_ref = impl_trait_ref.subst(self.tcx(), substs);
+                }
+                self.print_impl_path(def_id, substs, self_ty, impl_trait_ref)
+            }
+
+            _ => {
+                let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id };
+
+                let mut parent_substs = substs;
+                let mut trait_qualify_parent = false;
+                if !substs.is_empty() {
+                    let generics = self.tcx().generics_of(def_id);
+                    parent_substs = &substs[..generics.parent_count.min(substs.len())];
+
+                    match key.disambiguated_data.data {
+                        // Closures' own generics are only captures, don't print them.
+                        DefPathData::ClosureExpr => {}
+
+                        // If we have any generic arguments to print, we do that
+                        // on top of the same path, but without its own generics.
+                        _ => if !generics.params.is_empty() && substs.len() >= generics.count() {
+                            let args = self.generic_args_to_print(generics, substs);
+                            return self.path_generic_args(
+                                |cx| cx.print_def_path(def_id, parent_substs),
+                                args,
+                            );
+                        }
+                    }
+
+                    // FIXME(eddyb) try to move this into the parent's printing
+                    // logic, instead of doing it when printing the child.
+                    trait_qualify_parent =
+                        generics.has_self &&
+                        generics.parent == Some(parent_def_id) &&
+                        parent_substs.len() == generics.parent_count &&
+                        self.tcx().generics_of(parent_def_id).parent_count == 0;
+                }
+
+                self.path_append(
+                    |cx: Self| if trait_qualify_parent {
+                        let trait_ref = ty::TraitRef::new(
+                            parent_def_id,
+                            cx.tcx().intern_substs(parent_substs),
+                        );
+                        cx.path_qualified(trait_ref.self_ty(), Some(trait_ref))
+                    } else {
+                        cx.print_def_path(parent_def_id, parent_substs)
+                    },
+                    &key.disambiguated_data,
+                )
+            }
+        }
+    }
+
+    fn generic_args_to_print(
+        &self,
+        generics: &'tcx ty::Generics,
+        substs: &'tcx [Kind<'tcx>],
+    ) -> &'tcx [Kind<'tcx>] {
+        let mut own_params = generics.parent_count..generics.count();
+
+        // Don't print args for `Self` parameters (of traits).
+        if generics.has_self && own_params.start == 0 {
+            own_params.start = 1;
+        }
+
+        // Don't print args that are the defaults of their respective parameters.
+        own_params.end -= generics.params.iter().rev().take_while(|param| {
+            match param.kind {
+                ty::GenericParamDefKind::Lifetime => false,
+                ty::GenericParamDefKind::Type { has_default, .. } => {
+                    has_default && substs[param.index as usize] == Kind::from(
+                        self.tcx().type_of(param.def_id).subst(self.tcx(), substs)
+                    )
+                }
+                ty::GenericParamDefKind::Const => false, // FIXME(const_generics:defaults)
+            }
+        }).count();
+
+        &substs[own_params]
+    }
+
+    fn default_print_impl_path(
+        self,
+        impl_def_id: DefId,
+        _substs: &'tcx [Kind<'tcx>],
+        self_ty: Ty<'tcx>,
+        impl_trait_ref: Option<ty::TraitRef<'tcx>>,
+    ) -> Result<Self::Path, Self::Error> {
+        debug!("default_print_impl_path: impl_def_id={:?}, self_ty={}, impl_trait_ref={:?}",
+               impl_def_id, self_ty, impl_trait_ref);
+
+        let key = self.tcx().def_key(impl_def_id);
+        let parent_def_id = DefId { index: key.parent.unwrap(), ..impl_def_id };
+
+        // Decide whether to print the parent path for the impl.
+        // Logically, since impls are global, it's never needed, but
+        // users may find it useful. Currently, we omit the parent if
+        // the impl is either in the same module as the self-type or
+        // as the trait.
+        let in_self_mod = match characteristic_def_id_of_type(self_ty) {
+            None => false,
+            Some(ty_def_id) => self.tcx().parent(ty_def_id) == Some(parent_def_id),
+        };
+        let in_trait_mod = match impl_trait_ref {
+            None => false,
+            Some(trait_ref) => self.tcx().parent(trait_ref.def_id) == Some(parent_def_id),
+        };
+
+        if !in_self_mod && !in_trait_mod {
+            // If the impl is not co-located with either self-type or
+            // trait-type, then fallback to a format that identifies
+            // the module more clearly.
+            self.path_append_impl(
+                |cx| cx.print_def_path(parent_def_id, &[]),
+                &key.disambiguated_data,
+                self_ty,
+                impl_trait_ref,
+            )
+        } else {
+            // Otherwise, try to give a good form that would be valid language
+            // syntax. Preferably using associated item notation.
+            self.path_qualified(self_ty, impl_trait_ref)
+        }
+    }
+}
+
+/// As a heuristic, when we see an impl, if we see that the
+/// 'self type' is a type defined in the same module as the impl,
+/// we can omit including the path to the impl itself. This
+/// function tries to find a "characteristic `DefId`" for a
+/// type. It's just a heuristic so it makes some questionable
+/// decisions and we may want to adjust it later.
+pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
+    match ty.sty {
+        ty::Adt(adt_def, _) => Some(adt_def.did),
+
+        ty::Dynamic(data, ..) => data.principal_def_id(),
+
+        ty::Array(subty, _) |
+        ty::Slice(subty) => characteristic_def_id_of_type(subty),
+
+        ty::RawPtr(mt) => characteristic_def_id_of_type(mt.ty),
+
+        ty::Ref(_, ty, _) => characteristic_def_id_of_type(ty),
+
+        ty::Tuple(ref tys) => tys.iter()
+                                   .filter_map(|ty| characteristic_def_id_of_type(ty))
+                                   .next(),
+
+        ty::FnDef(def_id, _) |
+        ty::Closure(def_id, _) |
+        ty::Generator(def_id, _, _) |
+        ty::Foreign(def_id) => Some(def_id),
+
+        ty::Bool |
+        ty::Char |
+        ty::Int(_) |
+        ty::Uint(_) |
+        ty::Str |
+        ty::FnPtr(_) |
+        ty::Projection(_) |
+        ty::Placeholder(..) |
+        ty::UnnormalizedProjection(..) |
+        ty::Param(_) |
+        ty::Opaque(..) |
+        ty::Infer(_) |
+        ty::Bound(..) |
+        ty::Error |
+        ty::GeneratorWitness(..) |
+        ty::Never |
+        ty::Float(_) => None,
+    }
+}
+
+impl<'gcx: 'tcx, 'tcx, P: Printer<'gcx, 'tcx>> Print<'gcx, 'tcx, P> for ty::RegionKind {
+    type Output = P::Region;
+    type Error = P::Error;
+    fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
+        cx.print_region(self)
+    }
+}
+
+impl<'gcx: 'tcx, 'tcx, P: Printer<'gcx, 'tcx>> Print<'gcx, 'tcx, P> for ty::Region<'_> {
+    type Output = P::Region;
+    type Error = P::Error;
+    fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
+        cx.print_region(self)
+    }
+}
+
+impl<'gcx: 'tcx, 'tcx, P: Printer<'gcx, 'tcx>> Print<'gcx, 'tcx, P> for Ty<'tcx> {
+    type Output = P::Type;
+    type Error = P::Error;
+    fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
+        cx.print_type(self)
+    }
+}
+
+impl<'gcx: 'tcx, 'tcx, P: Printer<'gcx, 'tcx>> Print<'gcx, 'tcx, P>
+    for &'tcx ty::List<ty::ExistentialPredicate<'tcx>>
+{
+    type Output = P::DynExistential;
+    type Error = P::Error;
+    fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
+        cx.print_dyn_existential(self)
+    }
+}
diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs
new file mode 100644
index 0000000..7701a10
--- /dev/null
+++ b/src/librustc/ty/print/pretty.rs
@@ -0,0 +1,1604 @@
+use crate::hir;
+use crate::hir::def::Namespace;
+use crate::hir::map::{DefPathData, DisambiguatedDefPathData};
+use crate::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use crate::middle::cstore::{ExternCrate, ExternCrateSource};
+use crate::middle::region;
+use crate::ty::{self, DefIdTree, ParamConst, Ty, TyCtxt, TypeFoldable};
+use crate::ty::subst::{Kind, Subst, UnpackedKind};
+use crate::mir::interpret::ConstValue;
+use syntax::symbol::{keywords, Symbol};
+
+use rustc_target::spec::abi::Abi;
+use syntax::symbol::InternedString;
+
+use std::cell::Cell;
+use std::fmt::{self, Write as _};
+use std::ops::{Deref, DerefMut};
+
+// `pretty` is a separate module only for organization.
+use super::*;
+
+macro_rules! p {
+    (@write($($data:expr),+)) => {
+        write!(scoped_cx!(), $($data),+)?
+    };
+    (@print($x:expr)) => {
+        scoped_cx!() = $x.print(scoped_cx!())?
+    };
+    (@$method:ident($($arg:expr),*)) => {
+        scoped_cx!() = scoped_cx!().$method($($arg),*)?
+    };
+    ($($kind:ident $data:tt),+) => {{
+        $(p!(@$kind $data);)+
+    }};
+}
+macro_rules! define_scoped_cx {
+    ($cx:ident) => {
+        #[allow(unused_macros)]
+        macro_rules! scoped_cx {
+            () => ($cx)
+        }
+    };
+}
+
+thread_local! {
+    static FORCE_IMPL_FILENAME_LINE: Cell<bool> = Cell::new(false);
+    static SHOULD_PREFIX_WITH_CRATE: Cell<bool> = Cell::new(false);
+}
+
+/// Force us to name impls with just the filename/line number. We
+/// normally try to use types. But at some points, notably while printing
+/// cycle errors, this can result in extra or suboptimal error output,
+/// so this variable disables that check.
+pub fn with_forced_impl_filename_line<F: FnOnce() -> R, R>(f: F) -> R {
+    FORCE_IMPL_FILENAME_LINE.with(|force| {
+        let old = force.get();
+        force.set(true);
+        let result = f();
+        force.set(old);
+        result
+    })
+}
+
+/// Adds the `crate::` prefix to paths where appropriate.
+pub fn with_crate_prefix<F: FnOnce() -> R, R>(f: F) -> R {
+    SHOULD_PREFIX_WITH_CRATE.with(|flag| {
+        let old = flag.get();
+        flag.set(true);
+        let result = f();
+        flag.set(old);
+        result
+    })
+}
+
+/// The "region highlights" are used to control region printing during
+/// specific error messages. When a "region highlight" is enabled, it
+/// gives an alternate way to print specific regions. For now, we
+/// always print those regions using a number, so something like "`'0`".
+///
+/// Regions not selected by the region highlight mode are presently
+/// unaffected.
+#[derive(Copy, Clone, Default)]
+pub struct RegionHighlightMode {
+    /// If enabled, when we see the selected region, use "`'N`"
+    /// instead of the ordinary behavior.
+    highlight_regions: [Option<(ty::RegionKind, usize)>; 3],
+
+    /// If enabled, when printing a "free region" that originated from
+    /// the given `ty::BoundRegion`, print it as "`'1`". Free regions that would ordinarily
+    /// have names print as normal.
+    ///
+    /// This is used when you have a signature like `fn foo(x: &u32,
+    /// y: &'a u32)` and we want to give a name to the region of the
+    /// reference `x`.
+    highlight_bound_region: Option<(ty::BoundRegion, usize)>,
+}
+
+impl RegionHighlightMode {
+    /// If `region` and `number` are both `Some`, invokes
+    /// `highlighting_region`.
+    pub fn maybe_highlighting_region(
+        &mut self,
+        region: Option<ty::Region<'_>>,
+        number: Option<usize>,
+    ) {
+        if let Some(k) = region {
+            if let Some(n) = number {
+                self.highlighting_region(k, n);
+            }
+        }
+    }
+
+    /// Highlights the region inference variable `vid` as `'N`.
+    pub fn highlighting_region(
+        &mut self,
+        region: ty::Region<'_>,
+        number: usize,
+    ) {
+        let num_slots = self.highlight_regions.len();
+        let first_avail_slot = self.highlight_regions.iter_mut()
+            .filter(|s| s.is_none())
+            .next()
+            .unwrap_or_else(|| {
+                bug!(
+                    "can only highlight {} placeholders at a time",
+                    num_slots,
+                )
+            });
+        *first_avail_slot = Some((*region, number));
+    }
+
+    /// Convenience wrapper for `highlighting_region`.
+    pub fn highlighting_region_vid(
+        &mut self,
+        vid: ty::RegionVid,
+        number: usize,
+    ) {
+        self.highlighting_region(&ty::ReVar(vid), number)
+    }
+
+    /// Returns `Some(n)` with the number to use for the given region, if any.
+    fn region_highlighted(&self, region: ty::Region<'_>) -> Option<usize> {
+        self
+            .highlight_regions
+            .iter()
+            .filter_map(|h| match h {
+                Some((r, n)) if r == region => Some(*n),
+                _ => None,
+            })
+            .next()
+    }
+
+    /// Highlight the given bound region.
+    /// We can only highlight one bound region at a time. See
+    /// the field `highlight_bound_region` for more detailed notes.
+    pub fn highlighting_bound_region(
+        &mut self,
+        br: ty::BoundRegion,
+        number: usize,
+    ) {
+        assert!(self.highlight_bound_region.is_none());
+        self.highlight_bound_region = Some((br, number));
+    }
+}
+
+/// Trait for printers that pretty-print using `fmt::Write` to the printer.
+pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>:
+    Printer<'gcx, 'tcx,
+        Error = fmt::Error,
+        Path = Self,
+        Region = Self,
+        Type = Self,
+        DynExistential = Self,
+    > +
+    fmt::Write
+{
+    /// Like `print_def_path` but for value paths.
+    fn print_value_path(
+        self,
+        def_id: DefId,
+        substs: &'tcx [Kind<'tcx>],
+    ) -> Result<Self::Path, Self::Error> {
+        self.print_def_path(def_id, substs)
+    }
+
+    fn in_binder<T>(
+        self,
+        value: &ty::Binder<T>,
+    ) -> Result<Self, Self::Error>
+        where T: Print<'gcx, 'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx>
+    {
+        value.skip_binder().print(self)
+    }
+
+    /// Print comma-separated elements.
+    fn comma_sep<T>(
+        mut self,
+        mut elems: impl Iterator<Item = T>,
+    ) -> Result<Self, Self::Error>
+        where T: Print<'gcx, 'tcx, Self, Output = Self, Error = Self::Error>
+    {
+        if let Some(first) = elems.next() {
+            self = first.print(self)?;
+            for elem in elems {
+                self.write_str(", ")?;
+                self = elem.print(self)?;
+            }
+        }
+        Ok(self)
+    }
+
+    /// Print `<...>` around what `f` prints.
+    fn generic_delimiters(
+        self,
+        f: impl FnOnce(Self) -> Result<Self, Self::Error>,
+    ) -> Result<Self, Self::Error>;
+
+    /// Return `true` if the region should be printed in
+    /// optional positions, e.g. `&'a T` or `dyn Tr + 'b`.
+    /// This is typically the case for all non-`'_` regions.
+    fn region_should_not_be_omitted(
+        &self,
+        region: ty::Region<'_>,
+    ) -> bool;
+
+    // Defaults (should not be overriden):
+
+    /// If possible, this returns a global path resolving to `def_id` that is visible
+    /// from at least one local module and returns true. If the crate defining `def_id` is
+    /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`.
+    fn try_print_visible_def_path(
+        mut self,
+        def_id: DefId,
+    ) -> Result<(Self, bool), Self::Error> {
+        define_scoped_cx!(self);
+
+        debug!("try_print_visible_def_path: def_id={:?}", def_id);
+
+        // If `def_id` is a direct or injected extern crate, return the
+        // path to the crate followed by the path to the item within the crate.
+        if def_id.index == CRATE_DEF_INDEX {
+            let cnum = def_id.krate;
+
+            if cnum == LOCAL_CRATE {
+                return Ok((self.path_crate(cnum)?, true));
+            }
+
+            // In local mode, when we encounter a crate other than
+            // LOCAL_CRATE, execution proceeds in one of two ways:
+            //
+            // 1. for a direct dependency, where user added an
+            //    `extern crate` manually, we put the `extern
+            //    crate` as the parent. So you wind up with
+            //    something relative to the current crate.
+            // 2. for an extern inferred from a path or an indirect crate,
+            //    where there is no explicit `extern crate`, we just prepend
+            //    the crate name.
+            match *self.tcx().extern_crate(def_id) {
+                Some(ExternCrate {
+                    src: ExternCrateSource::Extern(def_id),
+                    direct: true,
+                    span,
+                    ..
+                }) => {
+                    debug!("try_print_visible_def_path: def_id={:?}", def_id);
+                    return Ok((if !span.is_dummy() {
+                        self.print_def_path(def_id, &[])?
+                    } else {
+                        self.path_crate(cnum)?
+                    }, true));
+                }
+                None => {
+                    return Ok((self.path_crate(cnum)?, true));
+                }
+                _ => {},
+            }
+        }
+
+        if def_id.is_local() {
+            return Ok((self, false));
+        }
+
+        let visible_parent_map = self.tcx().visible_parent_map(LOCAL_CRATE);
+
+        let mut cur_def_key = self.tcx().def_key(def_id);
+        debug!("try_print_visible_def_path: cur_def_key={:?}", cur_def_key);
+
+        // For a UnitStruct or TupleStruct we want the name of its parent rather than <unnamed>.
+        if let DefPathData::StructCtor = cur_def_key.disambiguated_data.data {
+            let parent = DefId {
+                krate: def_id.krate,
+                index: cur_def_key.parent.expect("DefPathData::StructCtor missing a parent"),
+            };
+
+            cur_def_key = self.tcx().def_key(parent);
+        }
+
+        let visible_parent = match visible_parent_map.get(&def_id).cloned() {
+            Some(parent) => parent,
+            None => return Ok((self, false)),
+        };
+        // HACK(eddyb) this bypasses `path_append`'s prefix printing to avoid
+        // knowing ahead of time whether the entire path will succeed or not.
+        // To support printers that do not implement `PrettyPrinter`, a `Vec` or
+        // linked list on the stack would need to be built, before any printing.
+        match self.try_print_visible_def_path(visible_parent)? {
+            (cx, false) => return Ok((cx, false)),
+            (cx, true) => self = cx,
+        }
+        let actual_parent = self.tcx().parent(def_id);
+        debug!(
+            "try_print_visible_def_path: visible_parent={:?} actual_parent={:?}",
+            visible_parent, actual_parent,
+        );
+
+        let mut data = cur_def_key.disambiguated_data.data;
+        debug!(
+            "try_print_visible_def_path: data={:?} visible_parent={:?} actual_parent={:?}",
+            data, visible_parent, actual_parent,
+        );
+
+        match data {
+            // In order to output a path that could actually be imported (valid and visible),
+            // we need to handle re-exports correctly.
+            //
+            // For example, take `std::os::unix::process::CommandExt`, this trait is actually
+            // defined at `std::sys::unix::ext::process::CommandExt` (at time of writing).
+            //
+            // `std::os::unix` rexports the contents of `std::sys::unix::ext`. `std::sys` is
+            // private so the "true" path to `CommandExt` isn't accessible.
+            //
+            // In this case, the `visible_parent_map` will look something like this:
+            //
+            // (child) -> (parent)
+            // `std::sys::unix::ext::process::CommandExt` -> `std::sys::unix::ext::process`
+            // `std::sys::unix::ext::process` -> `std::sys::unix::ext`
+            // `std::sys::unix::ext` -> `std::os`
+            //
+            // This is correct, as the visible parent of `std::sys::unix::ext` is in fact
+            // `std::os`.
+            //
+            // When printing the path to `CommandExt` and looking at the `cur_def_key` that
+            // corresponds to `std::sys::unix::ext`, we would normally print `ext` and then go
+            // to the parent - resulting in a mangled path like
+            // `std::os::ext::process::CommandExt`.
+            //
+            // Instead, we must detect that there was a re-export and instead print `unix`
+            // (which is the name `std::sys::unix::ext` was re-exported as in `std::os`). To
+            // do this, we compare the parent of `std::sys::unix::ext` (`std::sys::unix`) with
+            // the visible parent (`std::os`). If these do not match, then we iterate over
+            // the children of the visible parent (as was done when computing
+            // `visible_parent_map`), looking for the specific child we currently have and then
+            // have access to the re-exported name.
+            DefPathData::Module(ref mut name) |
+            DefPathData::TypeNs(ref mut name) if Some(visible_parent) != actual_parent => {
+                let reexport = self.tcx().item_children(visible_parent)
+                    .iter()
+                    .find(|child| child.def.def_id() == def_id)
+                    .map(|child| child.ident.as_interned_str());
+                if let Some(reexport) = reexport {
+                    *name = reexport;
+                }
+            }
+            // Re-exported `extern crate` (#43189).
+            DefPathData::CrateRoot => {
+                data = DefPathData::Module(
+                    self.tcx().original_crate_name(def_id.krate).as_interned_str(),
+                );
+            }
+            _ => {}
+        }
+        debug!("try_print_visible_def_path: data={:?}", data);
+
+        Ok((self.path_append(Ok, &DisambiguatedDefPathData {
+            data,
+            disambiguator: 0,
+        })?, true))
+    }
+
+    fn pretty_path_qualified(
+        self,
+        self_ty: Ty<'tcx>,
+        trait_ref: Option<ty::TraitRef<'tcx>>,
+    ) -> Result<Self::Path, Self::Error> {
+        if trait_ref.is_none() {
+            // Inherent impls. Try to print `Foo::bar` for an inherent
+            // impl on `Foo`, but fallback to `<Foo>::bar` if self-type is
+            // anything other than a simple path.
+            match self_ty.sty {
+                ty::Adt(..) | ty::Foreign(_) |
+                ty::Bool | ty::Char | ty::Str |
+                ty::Int(_) | ty::Uint(_) | ty::Float(_) => {
+                    return self_ty.print(self);
+                }
+
+                _ => {}
+            }
+        }
+
+        self.generic_delimiters(|mut cx| {
+            define_scoped_cx!(cx);
+
+            p!(print(self_ty));
+            if let Some(trait_ref) = trait_ref {
+                p!(write(" as "), print(trait_ref));
+            }
+            Ok(cx)
+        })
+    }
+
+    fn pretty_path_append_impl(
+        mut self,
+        print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+        self_ty: Ty<'tcx>,
+        trait_ref: Option<ty::TraitRef<'tcx>>,
+    ) -> Result<Self::Path, Self::Error> {
+        self = print_prefix(self)?;
+
+        self.generic_delimiters(|mut cx| {
+            define_scoped_cx!(cx);
+
+            p!(write("impl "));
+            if let Some(trait_ref) = trait_ref {
+                p!(print(trait_ref), write(" for "));
+            }
+            p!(print(self_ty));
+
+            Ok(cx)
+        })
+    }
+
+    fn pretty_print_type(
+        mut self,
+        ty: Ty<'tcx>,
+    ) -> Result<Self::Type, Self::Error> {
+        define_scoped_cx!(self);
+
+        match ty.sty {
+            ty::Bool => p!(write("bool")),
+            ty::Char => p!(write("char")),
+            ty::Int(t) => p!(write("{}", t.ty_to_string())),
+            ty::Uint(t) => p!(write("{}", t.ty_to_string())),
+            ty::Float(t) => p!(write("{}", t.ty_to_string())),
+            ty::RawPtr(ref tm) => {
+                p!(write("*{} ", match tm.mutbl {
+                    hir::MutMutable => "mut",
+                    hir::MutImmutable => "const",
+                }));
+                p!(print(tm.ty))
+            }
+            ty::Ref(r, ty, mutbl) => {
+                p!(write("&"));
+                if self.region_should_not_be_omitted(r) {
+                    p!(print(r), write(" "));
+                }
+                p!(print(ty::TypeAndMut { ty, mutbl }))
+            }
+            ty::Never => p!(write("!")),
+            ty::Tuple(ref tys) => {
+                p!(write("("));
+                let mut tys = tys.iter();
+                if let Some(&ty) = tys.next() {
+                    p!(print(ty), write(","));
+                    if let Some(&ty) = tys.next() {
+                        p!(write(" "), print(ty));
+                        for &ty in tys {
+                            p!(write(", "), print(ty));
+                        }
+                    }
+                }
+                p!(write(")"))
+            }
+            ty::FnDef(def_id, substs) => {
+                let sig = self.tcx().fn_sig(def_id).subst(self.tcx(), substs);
+                p!(print(sig), write(" {{"), print_value_path(def_id, substs), write("}}"));
+            }
+            ty::FnPtr(ref bare_fn) => {
+                p!(print(bare_fn))
+            }
+            ty::Infer(infer_ty) => p!(write("{}", infer_ty)),
+            ty::Error => p!(write("[type error]")),
+            ty::Param(ref param_ty) => p!(write("{}", param_ty)),
+            ty::Bound(debruijn, bound_ty) => {
+                match bound_ty.kind {
+                    ty::BoundTyKind::Anon => {
+                        if debruijn == ty::INNERMOST {
+                            p!(write("^{}", bound_ty.var.index()))
+                        } else {
+                            p!(write("^{}_{}", debruijn.index(), bound_ty.var.index()))
+                        }
+                    }
+
+                    ty::BoundTyKind::Param(p) => p!(write("{}", p)),
+                }
+            }
+            ty::Adt(def, substs) => {
+                p!(print_def_path(def.did, substs));
+            }
+            ty::Dynamic(data, r) => {
+                let print_r = self.region_should_not_be_omitted(r);
+                if print_r {
+                    p!(write("("));
+                }
+                p!(write("dyn "), print(data));
+                if print_r {
+                    p!(write(" + "), print(r), write(")"));
+                }
+            }
+            ty::Foreign(def_id) => {
+                p!(print_def_path(def_id, &[]));
+            }
+            ty::Projection(ref data) => p!(print(data)),
+            ty::UnnormalizedProjection(ref data) => {
+                p!(write("Unnormalized("), print(data), write(")"))
+            }
+            ty::Placeholder(placeholder) => {
+                p!(write("Placeholder({:?})", placeholder))
+            }
+            ty::Opaque(def_id, substs) => {
+                // FIXME(eddyb) print this with `print_def_path`.
+                if self.tcx().sess.verbose() {
+                    p!(write("Opaque({:?}, {:?})", def_id, substs));
+                    return Ok(self);
+                }
+
+                let def_key = self.tcx().def_key(def_id);
+                if let Some(name) = def_key.disambiguated_data.data.get_opt_name() {
+                    p!(write("{}", name));
+                    let mut substs = substs.iter();
+                    // FIXME(eddyb) print this with `print_def_path`.
+                    if let Some(first) = substs.next() {
+                        p!(write("::<"));
+                        p!(print(first));
+                        for subst in substs {
+                            p!(write(", "), print(subst));
+                        }
+                        p!(write(">"));
+                    }
+                    return Ok(self);
+                }
+                // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
+                // by looking up the projections associated with the def_id.
+                let bounds = self.tcx().predicates_of(def_id).instantiate(self.tcx(), substs);
+
+                let mut first = true;
+                let mut is_sized = false;
+                p!(write("impl"));
+                for predicate in bounds.predicates {
+                    if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() {
+                        // Don't print +Sized, but rather +?Sized if absent.
+                        if Some(trait_ref.def_id()) == self.tcx().lang_items().sized_trait() {
+                            is_sized = true;
+                            continue;
+                        }
+
+                        p!(
+                                write("{}", if first { " " } else { "+" }),
+                                print(trait_ref));
+                        first = false;
+                    }
+                }
+                if !is_sized {
+                    p!(write("{}?Sized", if first { " " } else { "+" }));
+                } else if first {
+                    p!(write(" Sized"));
+                }
+            }
+            ty::Str => p!(write("str")),
+            ty::Generator(did, substs, movability) => {
+                let upvar_tys = substs.upvar_tys(did, self.tcx());
+                let witness = substs.witness(did, self.tcx());
+                if movability == hir::GeneratorMovability::Movable {
+                    p!(write("[generator"));
+                } else {
+                    p!(write("[static generator"));
+                }
+
+                // FIXME(eddyb) should use `def_span`.
+                if let Some(hir_id) = self.tcx().hir().as_local_hir_id(did) {
+                    p!(write("@{:?}", self.tcx().hir().span_by_hir_id(hir_id)));
+                    let mut sep = " ";
+                    for (freevar, upvar_ty) in self.tcx().freevars(did)
+                        .as_ref()
+                        .map_or(&[][..], |fv| &fv[..])
+                        .iter()
+                        .zip(upvar_tys)
+                    {
+                        p!(
+                            write("{}{}:",
+                                    sep,
+                                    self.tcx().hir().name(freevar.var_id())),
+                            print(upvar_ty));
+                        sep = ", ";
+                    }
+                } else {
+                    // cross-crate closure types should only be
+                    // visible in codegen bug reports, I imagine.
+                    p!(write("@{:?}", did));
+                    let mut sep = " ";
+                    for (index, upvar_ty) in upvar_tys.enumerate() {
+                        p!(
+                                write("{}{}:", sep, index),
+                                print(upvar_ty));
+                        sep = ", ";
+                    }
+                }
+
+                p!(write(" "), print(witness), write("]"))
+            },
+            ty::GeneratorWitness(types) => {
+                p!(in_binder(&types));
+            }
+            ty::Closure(did, substs) => {
+                let upvar_tys = substs.upvar_tys(did, self.tcx());
+                p!(write("[closure"));
+
+                // FIXME(eddyb) should use `def_span`.
+                if let Some(hir_id) = self.tcx().hir().as_local_hir_id(did) {
+                    if self.tcx().sess.opts.debugging_opts.span_free_formats {
+                        p!(write("@{:?}", hir_id));
+                    } else {
+                        p!(write("@{:?}", self.tcx().hir().span_by_hir_id(hir_id)));
+                    }
+                    let mut sep = " ";
+                    for (freevar, upvar_ty) in self.tcx().freevars(did)
+                        .as_ref()
+                        .map_or(&[][..], |fv| &fv[..])
+                        .iter()
+                        .zip(upvar_tys)
+                    {
+                        p!(
+                            write("{}{}:",
+                                    sep,
+                                    self.tcx().hir().name(freevar.var_id())),
+                            print(upvar_ty));
+                        sep = ", ";
+                    }
+                } else {
+                    // cross-crate closure types should only be
+                    // visible in codegen bug reports, I imagine.
+                    p!(write("@{:?}", did));
+                    let mut sep = " ";
+                    for (index, upvar_ty) in upvar_tys.enumerate() {
+                        p!(
+                                write("{}{}:", sep, index),
+                                print(upvar_ty));
+                        sep = ", ";
+                    }
+                }
+
+                if self.tcx().sess.verbose() {
+                    p!(write(
+                        " closure_kind_ty={:?} closure_sig_ty={:?}",
+                        substs.closure_kind_ty(did, self.tcx()),
+                        substs.closure_sig_ty(did, self.tcx())
+                    ));
+                }
+
+                p!(write("]"))
+            },
+            ty::Array(ty, sz) => {
+                p!(write("["), print(ty), write("; "));
+                match sz.val {
+                    ConstValue::Unevaluated(..) |
+                    ConstValue::Infer(..) => p!(write("_")),
+                    ConstValue::Param(ParamConst { name, .. }) =>
+                        p!(write("{}", name)),
+                    _ => p!(write("{}", sz.unwrap_usize(self.tcx()))),
+                }
+                p!(write("]"))
+            }
+            ty::Slice(ty) => {
+                p!(write("["), print(ty), write("]"))
+            }
+        }
+
+        Ok(self)
+    }
+
+    fn pretty_print_dyn_existential(
+        mut self,
+        predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
+    ) -> Result<Self::DynExistential, Self::Error> {
+        define_scoped_cx!(self);
+
+        // Generate the main trait ref, including associated types.
+        let mut first = true;
+
+        if let Some(principal) = predicates.principal() {
+            p!(print_def_path(principal.def_id, &[]));
+
+            let mut resugared = false;
+
+            // Special-case `Fn(...) -> ...` and resugar it.
+            let fn_trait_kind = self.tcx().lang_items().fn_trait_kind(principal.def_id);
+            if !self.tcx().sess.verbose() && fn_trait_kind.is_some() {
+                if let ty::Tuple(ref args) = principal.substs.type_at(0).sty {
+                    let mut projections = predicates.projection_bounds();
+                    if let (Some(proj), None) = (projections.next(), projections.next()) {
+                        p!(pretty_fn_sig(args, false, proj.ty));
+                        resugared = true;
+                    }
+                }
+            }
+
+            // HACK(eddyb) this duplicates `FmtPrinter`'s `path_generic_args`,
+            // in order to place the projections inside the `<...>`.
+            if !resugared {
+                // Use a type that can't appear in defaults of type parameters.
+                let dummy_self = self.tcx().mk_infer(ty::FreshTy(0));
+                let principal = principal.with_self_ty(self.tcx(), dummy_self);
+
+                let args = self.generic_args_to_print(
+                    self.tcx().generics_of(principal.def_id),
+                    principal.substs,
+                );
+
+                // Don't print `'_` if there's no unerased regions.
+                let print_regions = args.iter().any(|arg| {
+                    match arg.unpack() {
+                        UnpackedKind::Lifetime(r) => *r != ty::ReErased,
+                        _ => false,
+                    }
+                });
+                let mut args = args.iter().cloned().filter(|arg| {
+                    match arg.unpack() {
+                        UnpackedKind::Lifetime(_) => print_regions,
+                        _ => true,
+                    }
+                });
+                let mut projections = predicates.projection_bounds();
+
+                let arg0 = args.next();
+                let projection0 = projections.next();
+                if arg0.is_some() || projection0.is_some() {
+                    let args = arg0.into_iter().chain(args);
+                    let projections = projection0.into_iter().chain(projections);
+
+                    p!(generic_delimiters(|mut cx| {
+                        cx = cx.comma_sep(args)?;
+                        if arg0.is_some() && projection0.is_some() {
+                            write!(cx, ", ")?;
+                        }
+                        cx.comma_sep(projections)
+                    }));
+                }
+            }
+            first = false;
+        }
+
+        // Builtin bounds.
+        // FIXME(eddyb) avoid printing twice (needed to ensure
+        // that the auto traits are sorted *and* printed via cx).
+        let mut auto_traits: Vec<_> = predicates.auto_traits().map(|did| {
+            (self.tcx().def_path_str(did), did)
+        }).collect();
+
+        // The auto traits come ordered by `DefPathHash`. While
+        // `DefPathHash` is *stable* in the sense that it depends on
+        // neither the host nor the phase of the moon, it depends
+        // "pseudorandomly" on the compiler version and the target.
+        //
+        // To avoid that causing instabilities in compiletest
+        // output, sort the auto-traits alphabetically.
+        auto_traits.sort();
+
+        for (_, def_id) in auto_traits {
+            if !first {
+                p!(write(" + "));
+            }
+            first = false;
+
+            p!(print_def_path(def_id, &[]));
+        }
+
+        Ok(self)
+    }
+
+    fn pretty_fn_sig(
+        mut self,
+        inputs: &[Ty<'tcx>],
+        c_variadic: bool,
+        output: Ty<'tcx>,
+    ) -> Result<Self, Self::Error> {
+        define_scoped_cx!(self);
+
+        p!(write("("));
+        let mut inputs = inputs.iter();
+        if let Some(&ty) = inputs.next() {
+            p!(print(ty));
+            for &ty in inputs {
+                p!(write(", "), print(ty));
+            }
+            if c_variadic {
+                p!(write(", ..."));
+            }
+        }
+        p!(write(")"));
+        if !output.is_unit() {
+            p!(write(" -> "), print(output));
+        }
+
+        Ok(self)
+    }
+}
+
+// HACK(eddyb) boxed to avoid moving around a large struct by-value.
+pub struct FmtPrinter<'a, 'gcx, 'tcx, F>(Box<FmtPrinterData<'a, 'gcx, 'tcx, F>>);
+
+pub struct FmtPrinterData<'a, 'gcx, 'tcx, F> {
+    tcx: TyCtxt<'a, 'gcx, 'tcx>,
+    fmt: F,
+
+    empty_path: bool,
+    in_value: bool,
+
+    used_region_names: FxHashSet<InternedString>,
+    region_index: usize,
+    binder_depth: usize,
+
+    pub region_highlight_mode: RegionHighlightMode,
+}
+
+impl<F> Deref for FmtPrinter<'a, 'gcx, 'tcx, F> {
+    type Target = FmtPrinterData<'a, 'gcx, 'tcx, F>;
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+impl<F> DerefMut for FmtPrinter<'_, '_, '_, F> {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.0
+    }
+}
+
+impl<F> FmtPrinter<'a, 'gcx, 'tcx, F> {
+    pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, fmt: F, ns: Namespace) -> Self {
+        FmtPrinter(Box::new(FmtPrinterData {
+            tcx,
+            fmt,
+            empty_path: false,
+            in_value: ns == Namespace::ValueNS,
+            used_region_names: Default::default(),
+            region_index: 0,
+            binder_depth: 0,
+            region_highlight_mode: RegionHighlightMode::default(),
+        }))
+    }
+}
+
+impl TyCtxt<'_, '_, '_> {
+    // HACK(eddyb) get rid of `def_path_str` and/or pass `Namespace` explicitly always
+    // (but also some things just print a `DefId` generally so maybe we need this?)
+    fn guess_def_namespace(self, def_id: DefId) -> Namespace {
+        match self.def_key(def_id).disambiguated_data.data {
+            DefPathData::ValueNs(..) |
+            DefPathData::EnumVariant(..) |
+            DefPathData::Field(..) |
+            DefPathData::AnonConst |
+            DefPathData::ConstParam(..) |
+            DefPathData::ClosureExpr |
+            DefPathData::StructCtor => Namespace::ValueNS,
+
+            DefPathData::MacroDef(..) => Namespace::MacroNS,
+
+            _ => Namespace::TypeNS,
+        }
+    }
+
+    /// Returns a string identifying this `DefId`. This string is
+    /// suitable for user output.
+    pub fn def_path_str(self, def_id: DefId) -> String {
+        let ns = self.guess_def_namespace(def_id);
+        debug!("def_path_str: def_id={:?}, ns={:?}", def_id, ns);
+        let mut s = String::new();
+        let _ = FmtPrinter::new(self, &mut s, ns)
+            .print_def_path(def_id, &[]);
+        s
+    }
+}
+
+impl<F: fmt::Write> fmt::Write for FmtPrinter<'_, '_, '_, F> {
+    fn write_str(&mut self, s: &str) -> fmt::Result {
+        self.fmt.write_str(s)
+    }
+}
+
+impl<F: fmt::Write> Printer<'gcx, 'tcx> for FmtPrinter<'_, 'gcx, 'tcx, F> {
+    type Error = fmt::Error;
+
+    type Path = Self;
+    type Region = Self;
+    type Type = Self;
+    type DynExistential = Self;
+
+    fn tcx(&'a self) -> TyCtxt<'a, 'gcx, 'tcx> {
+        self.tcx
+    }
+
+    fn print_def_path(
+        mut self,
+        def_id: DefId,
+        substs: &'tcx [Kind<'tcx>],
+    ) -> Result<Self::Path, Self::Error> {
+        define_scoped_cx!(self);
+
+        if substs.is_empty() {
+            match self.try_print_visible_def_path(def_id)? {
+                (cx, true) => return Ok(cx),
+                (cx, false) => self = cx,
+            }
+        }
+
+        let key = self.tcx.def_key(def_id);
+        if let DefPathData::Impl = key.disambiguated_data.data {
+            // Always use types for non-local impls, where types are always
+            // available, and filename/line-number is mostly uninteresting.
+            let use_types =
+                !def_id.is_local() || {
+                    // Otherwise, use filename/line-number if forced.
+                    let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get());
+                    !force_no_types
+                };
+
+            if !use_types {
+                // If no type info is available, fall back to
+                // pretty printing some span information. This should
+                // only occur very early in the compiler pipeline.
+                let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id };
+                let span = self.tcx.def_span(def_id);
+
+                self = self.print_def_path(parent_def_id, &[])?;
+
+                // HACK(eddyb) copy of `path_append` to avoid
+                // constructing a `DisambiguatedDefPathData`.
+                if !self.empty_path {
+                    write!(self, "::")?;
+                }
+                write!(self, "<impl at {:?}>", span)?;
+                self.empty_path = false;
+
+                return Ok(self);
+            }
+        }
+
+        self.default_print_def_path(def_id, substs)
+    }
+
+    fn print_region(
+        self,
+        region: ty::Region<'_>,
+    ) -> Result<Self::Region, Self::Error> {
+        self.pretty_print_region(region)
+    }
+
+    fn print_type(
+        self,
+        ty: Ty<'tcx>,
+    ) -> Result<Self::Type, Self::Error> {
+        self.pretty_print_type(ty)
+    }
+
+    fn print_dyn_existential(
+        self,
+        predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
+    ) -> Result<Self::DynExistential, Self::Error> {
+        self.pretty_print_dyn_existential(predicates)
+    }
+
+    fn path_crate(
+        mut self,
+        cnum: CrateNum,
+    ) -> Result<Self::Path, Self::Error> {
+        self.empty_path = true;
+        if cnum == LOCAL_CRATE {
+            if self.tcx.sess.rust_2018() {
+                // We add the `crate::` keyword on Rust 2018, only when desired.
+                if SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get()) {
+                    write!(self, "{}", keywords::Crate.name())?;
+                    self.empty_path = false;
+                }
+            }
+        } else {
+            write!(self, "{}", self.tcx.crate_name(cnum))?;
+            self.empty_path = false;
+        }
+        Ok(self)
+    }
+    fn path_qualified(
+        mut self,
+        self_ty: Ty<'tcx>,
+        trait_ref: Option<ty::TraitRef<'tcx>>,
+    ) -> Result<Self::Path, Self::Error> {
+        self = self.pretty_path_qualified(self_ty, trait_ref)?;
+        self.empty_path = false;
+        Ok(self)
+    }
+
+    fn path_append_impl(
+        mut self,
+        print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+        _disambiguated_data: &DisambiguatedDefPathData,
+        self_ty: Ty<'tcx>,
+        trait_ref: Option<ty::TraitRef<'tcx>>,
+    ) -> Result<Self::Path, Self::Error> {
+        self = self.pretty_path_append_impl(|mut cx| {
+            cx = print_prefix(cx)?;
+            if !cx.empty_path {
+                write!(cx, "::")?;
+            }
+
+            Ok(cx)
+        }, self_ty, trait_ref)?;
+        self.empty_path = false;
+        Ok(self)
+    }
+    fn path_append(
+        mut self,
+        print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+        disambiguated_data: &DisambiguatedDefPathData,
+    ) -> Result<Self::Path, Self::Error> {
+        self = print_prefix(self)?;
+
+        // Skip `::{{constructor}}` on tuple/unit structs.
+        match disambiguated_data.data {
+            DefPathData::StructCtor => return Ok(self),
+            _ => {}
+        }
+
+        // FIXME(eddyb) `name` should never be empty, but it
+        // currently is for `extern { ... }` "foreign modules".
+        let name = disambiguated_data.data.as_interned_str().as_str();
+        if !name.is_empty() {
+            if !self.empty_path {
+                write!(self, "::")?;
+            }
+            write!(self, "{}", name)?;
+
+            // FIXME(eddyb) this will print e.g. `{{closure}}#3`, but it
+            // might be nicer to use something else, e.g. `{closure#3}`.
+            let dis = disambiguated_data.disambiguator;
+            let print_dis =
+                disambiguated_data.data.get_opt_name().is_none() ||
+                dis != 0 && self.tcx.sess.verbose();
+            if print_dis {
+                write!(self, "#{}", dis)?;
+            }
+
+            self.empty_path = false;
+        }
+
+        Ok(self)
+    }
+    fn path_generic_args(
+        mut self,
+        print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+        args: &[Kind<'tcx>],
+    ) -> Result<Self::Path, Self::Error> {
+        self = print_prefix(self)?;
+
+        // Don't print `'_` if there's no unerased regions.
+        let print_regions = args.iter().any(|arg| {
+            match arg.unpack() {
+                UnpackedKind::Lifetime(r) => *r != ty::ReErased,
+                _ => false,
+            }
+        });
+        let args = args.iter().cloned().filter(|arg| {
+            match arg.unpack() {
+                UnpackedKind::Lifetime(_) => print_regions,
+                _ => true,
+            }
+        });
+
+        if args.clone().next().is_some() {
+            if self.in_value {
+                write!(self, "::")?;
+            }
+            self.generic_delimiters(|cx| cx.comma_sep(args))
+        } else {
+            Ok(self)
+        }
+    }
+}
+
+impl<F: fmt::Write> PrettyPrinter<'gcx, 'tcx> for FmtPrinter<'_, 'gcx, 'tcx, F> {
+    fn print_value_path(
+        mut self,
+        def_id: DefId,
+        substs: &'tcx [Kind<'tcx>],
+    ) -> Result<Self::Path, Self::Error> {
+        let was_in_value = std::mem::replace(&mut self.in_value, true);
+        self = self.print_def_path(def_id, substs)?;
+        self.in_value = was_in_value;
+
+        Ok(self)
+    }
+
+    fn in_binder<T>(
+        self,
+        value: &ty::Binder<T>,
+    ) -> Result<Self, Self::Error>
+        where T: Print<'gcx, 'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx>
+    {
+        self.pretty_in_binder(value)
+    }
+
+    fn generic_delimiters(
+        mut self,
+        f: impl FnOnce(Self) -> Result<Self, Self::Error>,
+    ) -> Result<Self, Self::Error> {
+        write!(self, "<")?;
+
+        let was_in_value = std::mem::replace(&mut self.in_value, false);
+        let mut inner = f(self)?;
+        inner.in_value = was_in_value;
+
+        write!(inner, ">")?;
+        Ok(inner)
+    }
+
+    fn region_should_not_be_omitted(
+        &self,
+        region: ty::Region<'_>,
+    ) -> bool {
+        let highlight = self.region_highlight_mode;
+        if highlight.region_highlighted(region).is_some() {
+            return true;
+        }
+
+        if self.tcx.sess.verbose() {
+            return true;
+        }
+
+        let identify_regions = self.tcx.sess.opts.debugging_opts.identify_regions;
+
+        match *region {
+            ty::ReEarlyBound(ref data) => {
+                data.name != "" && data.name != "'_"
+            }
+
+            ty::ReLateBound(_, br) |
+            ty::ReFree(ty::FreeRegion { bound_region: br, .. }) |
+            ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
+                if let ty::BrNamed(_, name) = br {
+                    if name != "" && name != "'_" {
+                        return true;
+                    }
+                }
+
+                if let Some((region, _)) = highlight.highlight_bound_region {
+                    if br == region {
+                        return true;
+                    }
+                }
+
+                false
+            }
+
+            ty::ReScope(_) |
+            ty::ReVar(_) if identify_regions => true,
+
+            ty::ReVar(_) |
+            ty::ReScope(_) |
+            ty::ReErased => false,
+
+            ty::ReStatic |
+            ty::ReEmpty |
+            ty::ReClosureBound(_) => true,
+        }
+    }
+}
+
+// HACK(eddyb) limited to `FmtPrinter` because of `region_highlight_mode`.
+impl<F: fmt::Write> FmtPrinter<'_, '_, '_, F> {
+    pub fn pretty_print_region(
+        mut self,
+        region: ty::Region<'_>,
+    ) -> Result<Self, fmt::Error> {
+        define_scoped_cx!(self);
+
+        // Watch out for region highlights.
+        let highlight = self.region_highlight_mode;
+        if let Some(n) = highlight.region_highlighted(region) {
+            p!(write("'{}", n));
+            return Ok(self);
+        }
+
+        if self.tcx.sess.verbose() {
+            p!(write("{:?}", region));
+            return Ok(self);
+        }
+
+        let identify_regions = self.tcx.sess.opts.debugging_opts.identify_regions;
+
+        // These printouts are concise.  They do not contain all the information
+        // the user might want to diagnose an error, but there is basically no way
+        // to fit that into a short string.  Hence the recommendation to use
+        // `explain_region()` or `note_and_explain_region()`.
+        match *region {
+            ty::ReEarlyBound(ref data) => {
+                if data.name != "" {
+                    p!(write("{}", data.name));
+                    return Ok(self);
+                }
+            }
+            ty::ReLateBound(_, br) |
+            ty::ReFree(ty::FreeRegion { bound_region: br, .. }) |
+            ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
+                if let ty::BrNamed(_, name) = br {
+                    if name != "" && name != "'_" {
+                        p!(write("{}", name));
+                        return Ok(self);
+                    }
+                }
+
+                if let Some((region, counter)) = highlight.highlight_bound_region {
+                    if br == region {
+                        p!(write("'{}", counter));
+                        return Ok(self);
+                    }
+                }
+            }
+            ty::ReScope(scope) if identify_regions => {
+                match scope.data {
+                    region::ScopeData::Node =>
+                        p!(write("'{}s", scope.item_local_id().as_usize())),
+                    region::ScopeData::CallSite =>
+                        p!(write("'{}cs", scope.item_local_id().as_usize())),
+                    region::ScopeData::Arguments =>
+                        p!(write("'{}as", scope.item_local_id().as_usize())),
+                    region::ScopeData::Destruction =>
+                        p!(write("'{}ds", scope.item_local_id().as_usize())),
+                    region::ScopeData::Remainder(first_statement_index) => p!(write(
+                        "'{}_{}rs",
+                        scope.item_local_id().as_usize(),
+                        first_statement_index.index()
+                    )),
+                }
+                return Ok(self);
+            }
+            ty::ReVar(region_vid) if identify_regions => {
+                p!(write("{:?}", region_vid));
+                return Ok(self);
+            }
+            ty::ReVar(_) => {}
+            ty::ReScope(_) |
+            ty::ReErased => {}
+            ty::ReStatic => {
+                p!(write("'static"));
+                return Ok(self);
+            }
+            ty::ReEmpty => {
+                p!(write("'<empty>"));
+                return Ok(self);
+            }
+
+            // The user should never encounter these in unsubstituted form.
+            ty::ReClosureBound(vid) => {
+                p!(write("{:?}", vid));
+                return Ok(self);
+            }
+        }
+
+        p!(write("'_"));
+
+        Ok(self)
+    }
+}
+
+// HACK(eddyb) limited to `FmtPrinter` because of `binder_depth`,
+// `region_index` and `used_region_names`.
+impl<F: fmt::Write> FmtPrinter<'_, 'gcx, 'tcx, F> {
+    pub fn pretty_in_binder<T>(
+        mut self,
+        value: &ty::Binder<T>,
+    ) -> Result<Self, fmt::Error>
+        where T: Print<'gcx, 'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>
+    {
+        fn name_by_region_index(index: usize) -> InternedString {
+            match index {
+                0 => Symbol::intern("'r"),
+                1 => Symbol::intern("'s"),
+                i => Symbol::intern(&format!("'t{}", i-2)),
+            }.as_interned_str()
+        }
+
+        // Replace any anonymous late-bound regions with named
+        // variants, using gensym'd identifiers, so that we can
+        // clearly differentiate between named and unnamed regions in
+        // the output. We'll probably want to tweak this over time to
+        // decide just how much information to give.
+        if self.binder_depth == 0 {
+            self.prepare_late_bound_region_info(value);
+        }
+
+        let mut empty = true;
+        let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| {
+            write!(cx, "{}", if empty {
+                empty = false;
+                start
+            } else {
+                cont
+            })
+        };
+
+        define_scoped_cx!(self);
+
+        let old_region_index = self.region_index;
+        let mut region_index = old_region_index;
+        let new_value = self.tcx.replace_late_bound_regions(value, |br| {
+            let _ = start_or_continue(&mut self, "for<", ", ");
+            let br = match br {
+                ty::BrNamed(_, name) => {
+                    let _ = write!(self, "{}", name);
+                    br
+                }
+                ty::BrAnon(_) |
+                ty::BrFresh(_) |
+                ty::BrEnv => {
+                    let name = loop {
+                        let name = name_by_region_index(region_index);
+                        region_index += 1;
+                        if !self.used_region_names.contains(&name) {
+                            break name;
+                        }
+                    };
+                    let _ = write!(self, "{}", name);
+                    ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name)
+                }
+            };
+            self.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br))
+        }).0;
+        start_or_continue(&mut self, "", "> ")?;
+
+        self.binder_depth += 1;
+        self.region_index = region_index;
+        let mut inner = new_value.print(self)?;
+        inner.region_index = old_region_index;
+        inner.binder_depth -= 1;
+        Ok(inner)
+    }
+
+    fn prepare_late_bound_region_info<T>(&mut self, value: &ty::Binder<T>)
+        where T: TypeFoldable<'tcx>
+    {
+
+        struct LateBoundRegionNameCollector<'a>(&'a mut FxHashSet<InternedString>);
+        impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_> {
+            fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
+                match *r {
+                    ty::ReLateBound(_, ty::BrNamed(_, name)) => {
+                        self.0.insert(name);
+                    },
+                    _ => {},
+                }
+                r.super_visit_with(self)
+            }
+        }
+
+        self.used_region_names.clear();
+        let mut collector = LateBoundRegionNameCollector(&mut self.used_region_names);
+        value.visit_with(&mut collector);
+        self.region_index = 0;
+    }
+}
+
+impl<'gcx: 'tcx, 'tcx, T, P: PrettyPrinter<'gcx, 'tcx>> Print<'gcx, 'tcx, P>
+    for ty::Binder<T>
+    where T: Print<'gcx, 'tcx, P, Output = P, Error = P::Error> + TypeFoldable<'tcx>
+{
+    type Output = P;
+    type Error = P::Error;
+    fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
+        cx.in_binder(self)
+    }
+}
+
+impl<'gcx: 'tcx, 'tcx, T, U, P: PrettyPrinter<'gcx, 'tcx>> Print<'gcx, 'tcx, P>
+    for ty::OutlivesPredicate<T, U>
+    where T: Print<'gcx, 'tcx, P, Output = P, Error = P::Error>,
+          U: Print<'gcx, 'tcx, P, Output = P, Error = P::Error>,
+{
+    type Output = P;
+    type Error = P::Error;
+    fn print(&self, mut cx: P) -> Result<Self::Output, Self::Error> {
+        define_scoped_cx!(cx);
+        p!(print(self.0), write(" : "), print(self.1));
+        Ok(cx)
+    }
+}
+
+macro_rules! forward_display_to_print {
+    ($($ty:ty),+) => {
+        $(impl fmt::Display for $ty {
+            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                ty::tls::with(|tcx| {
+                    tcx.lift(self)
+                        .expect("could not lift for printing")
+                        .print(FmtPrinter::new(tcx, f, Namespace::TypeNS))?;
+                    Ok(())
+                })
+            }
+        })+
+    };
+}
+
+macro_rules! define_print_and_forward_display {
+    (($self:ident, $cx:ident): $($ty:ty $print:block)+) => {
+        $(impl<'gcx: 'tcx, 'tcx, P: PrettyPrinter<'gcx, 'tcx>> Print<'gcx, 'tcx, P> for $ty {
+            type Output = P;
+            type Error = fmt::Error;
+            fn print(&$self, $cx: P) -> Result<Self::Output, Self::Error> {
+                #[allow(unused_mut)]
+                let mut $cx = $cx;
+                define_scoped_cx!($cx);
+                let _: () = $print;
+                #[allow(unreachable_code)]
+                Ok($cx)
+            }
+        })+
+
+        forward_display_to_print!($($ty),+);
+    };
+}
+
+// HACK(eddyb) this is separate because `ty::RegionKind` doesn't need lifting.
+impl fmt::Display for ty::RegionKind {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        ty::tls::with(|tcx| {
+            self.print(FmtPrinter::new(tcx, f, Namespace::TypeNS))?;
+            Ok(())
+        })
+    }
+}
+
+forward_display_to_print! {
+    Ty<'tcx>,
+    &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
+
+    // HACK(eddyb) these are exhaustive instead of generic,
+    // because `for<'gcx: 'tcx, 'tcx>` isn't possible yet.
+    ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
+    ty::Binder<ty::TraitRef<'tcx>>,
+    ty::Binder<ty::FnSig<'tcx>>,
+    ty::Binder<ty::TraitPredicate<'tcx>>,
+    ty::Binder<ty::SubtypePredicate<'tcx>>,
+    ty::Binder<ty::ProjectionPredicate<'tcx>>,
+    ty::Binder<ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>,
+    ty::Binder<ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>>,
+
+    ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>,
+    ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>
+}
+
+define_print_and_forward_display! {
+    (self, cx):
+
+    &'tcx ty::List<Ty<'tcx>> {
+        p!(write("{{"));
+        let mut tys = self.iter();
+        if let Some(&ty) = tys.next() {
+            p!(print(ty));
+            for &ty in tys {
+                p!(write(", "), print(ty));
+            }
+        }
+        p!(write("}}"))
+    }
+
+    ty::TypeAndMut<'tcx> {
+        p!(write("{}", if self.mutbl == hir::MutMutable { "mut " } else { "" }),
+            print(self.ty))
+    }
+
+    ty::ExistentialTraitRef<'tcx> {
+        // Use a type that can't appear in defaults of type parameters.
+        let dummy_self = cx.tcx().mk_infer(ty::FreshTy(0));
+        let trait_ref = self.with_self_ty(cx.tcx(), dummy_self);
+        p!(print(trait_ref))
+    }
+
+    ty::ExistentialProjection<'tcx> {
+        let name = cx.tcx().associated_item(self.item_def_id).ident;
+        p!(write("{} = ", name), print(self.ty))
+    }
+
+    ty::ExistentialPredicate<'tcx> {
+        match *self {
+            ty::ExistentialPredicate::Trait(x) => p!(print(x)),
+            ty::ExistentialPredicate::Projection(x) => p!(print(x)),
+            ty::ExistentialPredicate::AutoTrait(def_id) => {
+                p!(print_def_path(def_id, &[]));
+            }
+        }
+    }
+
+    ty::FnSig<'tcx> {
+        if self.unsafety == hir::Unsafety::Unsafe {
+            p!(write("unsafe "));
+        }
+
+        if self.abi != Abi::Rust {
+            p!(write("extern {} ", self.abi));
+        }
+
+        p!(write("fn"), pretty_fn_sig(self.inputs(), self.c_variadic, self.output()));
+    }
+
+    ty::InferTy {
+        if cx.tcx().sess.verbose() {
+            p!(write("{:?}", self));
+            return Ok(cx);
+        }
+        match *self {
+            ty::TyVar(_) => p!(write("_")),
+            ty::IntVar(_) => p!(write("{}", "{integer}")),
+            ty::FloatVar(_) => p!(write("{}", "{float}")),
+            ty::FreshTy(v) => p!(write("FreshTy({})", v)),
+            ty::FreshIntTy(v) => p!(write("FreshIntTy({})", v)),
+            ty::FreshFloatTy(v) => p!(write("FreshFloatTy({})", v))
+        }
+    }
+
+    ty::TraitRef<'tcx> {
+        p!(print_def_path(self.def_id, self.substs));
+    }
+
+    &'tcx ty::Const<'tcx> {
+        match self.val {
+            ConstValue::Unevaluated(..) |
+            ConstValue::Infer(..) => p!(write("_")),
+            ConstValue::Param(ParamConst { name, .. }) => p!(write("{}", name)),
+            _ => p!(write("{:?}", self)),
+        }
+    }
+
+    ty::ParamTy {
+        p!(write("{}", self.name))
+    }
+
+    ty::ParamConst {
+        p!(write("{}", self.name))
+    }
+
+    ty::SubtypePredicate<'tcx> {
+        p!(print(self.a), write(" <: "), print(self.b))
+    }
+
+    ty::TraitPredicate<'tcx> {
+        p!(print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref))
+    }
+
+    ty::ProjectionPredicate<'tcx> {
+        p!(print(self.projection_ty), write(" == "), print(self.ty))
+    }
+
+    ty::ProjectionTy<'tcx> {
+        p!(print_def_path(self.item_def_id, self.substs));
+    }
+
+    ty::ClosureKind {
+        match *self {
+            ty::ClosureKind::Fn => p!(write("Fn")),
+            ty::ClosureKind::FnMut => p!(write("FnMut")),
+            ty::ClosureKind::FnOnce => p!(write("FnOnce")),
+        }
+    }
+
+    ty::Predicate<'tcx> {
+        match *self {
+            ty::Predicate::Trait(ref data) => p!(print(data)),
+            ty::Predicate::Subtype(ref predicate) => p!(print(predicate)),
+            ty::Predicate::RegionOutlives(ref predicate) => p!(print(predicate)),
+            ty::Predicate::TypeOutlives(ref predicate) => p!(print(predicate)),
+            ty::Predicate::Projection(ref predicate) => p!(print(predicate)),
+            ty::Predicate::WellFormed(ty) => p!(print(ty), write(" well-formed")),
+            ty::Predicate::ObjectSafe(trait_def_id) => {
+                p!(write("the trait `"),
+                   print_def_path(trait_def_id, &[]),
+                   write("` is object-safe"))
+            }
+            ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) => {
+                p!(write("the closure `"),
+                   print_value_path(closure_def_id, &[]),
+                   write("` implements the trait `{}`", kind))
+            }
+            ty::Predicate::ConstEvaluatable(def_id, substs) => {
+                p!(write("the constant `"),
+                   print_value_path(def_id, substs),
+                   write("` can be evaluated"))
+            }
+        }
+    }
+
+    Kind<'tcx> {
+        match self.unpack() {
+            UnpackedKind::Lifetime(lt) => p!(print(lt)),
+            UnpackedKind::Type(ty) => p!(print(ty)),
+            UnpackedKind::Const(ct) => p!(print(ct)),
+        }
+    }
+}
diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs
index 6488c0d..d8159f1 100644
--- a/src/librustc/ty/query/config.rs
+++ b/src/librustc/ty/query/config.rs
@@ -34,7 +34,7 @@
     type Value: Clone;
 }
 
-pub(super) trait QueryAccessors<'tcx>: QueryConfig<'tcx> {
+pub(crate) trait QueryAccessors<'tcx>: QueryConfig<'tcx> {
     fn query(key: Self::Key) -> Query<'tcx>;
 
     // Don't use this method to access query results, instead use the methods on TyCtxt
@@ -53,7 +53,7 @@
     fn handle_cycle_error(tcx: TyCtxt<'_, 'tcx, '_>, error: CycleError<'tcx>) -> Self::Value;
 }
 
-pub(super) trait QueryDescription<'tcx>: QueryAccessors<'tcx> {
+pub(crate) trait QueryDescription<'tcx>: QueryAccessors<'tcx> {
     fn describe(tcx: TyCtxt<'_, '_, '_>, key: Self::Key) -> Cow<'static, str>;
 
     #[inline]
@@ -71,7 +71,7 @@
 impl<'tcx, M: QueryAccessors<'tcx, Key=DefId>> QueryDescription<'tcx> for M {
     default fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> {
         if !tcx.sess.verbose() {
-            format!("processing `{}`", tcx.item_path_str(def_id)).into()
+            format!("processing `{}`", tcx.def_path_str(def_id)).into()
         } else {
             let name = unsafe { ::std::intrinsics::type_name::<M>() };
             format!("processing {:?} with query `{}`", def_id, name).into()
@@ -301,7 +301,7 @@
 impl<'tcx> QueryDescription<'tcx> for queries::super_predicates_of<'tcx> {
     fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> {
         format!("computing the supertraits of `{}`",
-                tcx.item_path_str(def_id)).into()
+                tcx.def_path_str(def_id)).into()
     }
 }
 
@@ -322,7 +322,7 @@
 impl<'tcx> QueryDescription<'tcx> for queries::coherent_trait<'tcx> {
     fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> {
         format!("coherence checking all impls of trait `{}`",
-                tcx.item_path_str(def_id)).into()
+                tcx.def_path_str(def_id)).into()
     }
 }
 
@@ -359,7 +359,7 @@
 impl<'tcx> QueryDescription<'tcx> for queries::mir_shims<'tcx> {
     fn describe(tcx: TyCtxt<'_, '_, '_>, def: ty::InstanceDef<'tcx>) -> Cow<'static, str> {
         format!("generating MIR shim for `{}`",
-                tcx.item_path_str(def.def_id())).into()
+                tcx.def_path_str(def.def_id())).into()
     }
 }
 
@@ -394,7 +394,7 @@
     ) -> Cow<'static, str> {
         format!(
             "const-evaluating + checking `{}`",
-            tcx.item_path_str(key.value.instance.def.def_id()),
+            tcx.def_path_str(key.value.instance.def.def_id()),
         ).into()
     }
 
@@ -415,7 +415,7 @@
     fn describe(tcx: TyCtxt<'_, '_, '_>, key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
         -> Cow<'static, str>
     {
-        format!("const-evaluating `{}`", tcx.item_path_str(key.value.instance.def.def_id())).into()
+        format!("const-evaluating `{}`", tcx.def_path_str(key.value.instance.def.def_id())).into()
     }
 
     #[inline]
@@ -513,7 +513,7 @@
 impl<'tcx> QueryDescription<'tcx> for queries::const_is_rvalue_promotable_to_static<'tcx> {
     fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> {
         format!("const checking if rvalue is promotable to static `{}`",
-            tcx.item_path_str(def_id)).into()
+            tcx.def_path_str(def_id)).into()
     }
 
     #[inline]
@@ -532,21 +532,21 @@
 impl<'tcx> QueryDescription<'tcx> for queries::rvalue_promotable_map<'tcx> {
     fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> {
         format!("checking which parts of `{}` are promotable to static",
-                tcx.item_path_str(def_id)).into()
+                tcx.def_path_str(def_id)).into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::is_mir_available<'tcx> {
     fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> {
         format!("checking if item is mir available: `{}`",
-                tcx.item_path_str(def_id)).into()
+                tcx.def_path_str(def_id)).into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::codegen_fulfill_obligation<'tcx> {
     fn describe(tcx: TyCtxt<'_, '_, '_>,
                 key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)) -> Cow<'static, str> {
-        format!("checking if `{}` fulfills its obligations", tcx.item_path_str(key.1.def_id()))
+        format!("checking if `{}` fulfills its obligations", tcx.def_path_str(key.1.def_id()))
             .into()
     }
 
@@ -565,19 +565,19 @@
 
 impl<'tcx> QueryDescription<'tcx> for queries::trait_impls_of<'tcx> {
     fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> {
-        format!("trait impls of `{}`", tcx.item_path_str(def_id)).into()
+        format!("trait impls of `{}`", tcx.def_path_str(def_id)).into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::is_object_safe<'tcx> {
     fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> {
-        format!("determine object safety of trait `{}`", tcx.item_path_str(def_id)).into()
+        format!("determine object safety of trait `{}`", tcx.def_path_str(def_id)).into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::is_const_fn_raw<'tcx> {
     fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> {
-        format!("checking if item is const fn: `{}`", tcx.item_path_str(def_id)).into()
+        format!("checking if item is const fn: `{}`", tcx.def_path_str(def_id)).into()
     }
 }
 
@@ -587,12 +587,6 @@
     }
 }
 
-impl<'tcx> QueryDescription<'tcx> for queries::is_panic_runtime<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "checking if the crate is_panic_runtime".into()
-    }
-}
-
 impl<'tcx> QueryDescription<'tcx> for queries::is_compiler_builtins<'tcx> {
     fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
         "checking if the crate is_compiler_builtins".into()
@@ -671,12 +665,6 @@
     }
 }
 
-impl<'tcx> QueryDescription<'tcx> for queries::native_libraries<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "looking up the native libraries of a linked crate".into()
-    }
-}
-
 impl<'tcx> QueryDescription<'tcx> for queries::foreign_modules<'tcx> {
     fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
         "looking up the foreign modules of a linked crate".into()
@@ -883,7 +871,7 @@
 
 impl<'tcx> QueryDescription<'tcx> for queries::vtable_methods<'tcx> {
     fn describe(tcx: TyCtxt<'_, '_, '_>, key: ty::PolyTraitRef<'tcx> ) -> Cow<'static, str> {
-        format!("finding all methods for trait {}", tcx.item_path_str(key.def_id())).into()
+        format!("finding all methods for trait {}", tcx.def_path_str(key.def_id())).into()
     }
 }
 
@@ -927,7 +915,7 @@
 
 impl<'tcx> QueryDescription<'tcx> for queries::substitute_normalize_and_test_predicates<'tcx> {
     fn describe(tcx: TyCtxt<'_, '_, '_>, key: (DefId, SubstsRef<'tcx>)) -> Cow<'static, str> {
-        format!("testing substituted normalized predicates:`{}`", tcx.item_path_str(key.0)).into()
+        format!("testing substituted normalized predicates:`{}`", tcx.def_path_str(key.0)).into()
     }
 }
 
@@ -945,22 +933,7 @@
 
 impl<'tcx> QueryDescription<'tcx> for queries::instance_def_size_estimate<'tcx> {
     fn describe(tcx: TyCtxt<'_, '_, '_>, def: ty::InstanceDef<'tcx>) -> Cow<'static, str> {
-        format!("estimating size for `{}`", tcx.item_path_str(def.def_id())).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::generics_of<'tcx> {
-    #[inline]
-    fn cache_on_disk(_: TyCtxt<'_, 'tcx, 'tcx>, def_id: Self::Key) -> bool {
-        def_id.is_local()
-    }
-
-    fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                              id: SerializedDepNodeIndex)
-                              -> Option<Self::Value> {
-        let generics: Option<ty::Generics> = tcx.queries.on_disk_cache
-                                                .try_load_query_result(tcx, id);
-        generics.map(|x| tcx.alloc_generics(x))
+        format!("estimating size for `{}`", tcx.def_path_str(def.def_id())).into()
     }
 }
 
@@ -1027,7 +1000,6 @@
 impl_disk_cacheable_query!(mir_const_qualif, |_, def_id| def_id.is_local());
 impl_disk_cacheable_query!(check_match, |_, def_id| def_id.is_local());
 impl_disk_cacheable_query!(def_symbol_name, |_, _| true);
-impl_disk_cacheable_query!(type_of, |_, def_id| def_id.is_local());
 impl_disk_cacheable_query!(predicates_of, |_, def_id| def_id.is_local());
 impl_disk_cacheable_query!(used_trait_imports, |_, def_id| def_id.is_local());
 impl_disk_cacheable_query!(codegen_fn_attrs, |_, _| true);
diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs
index 8804ed2..2f085a9 100644
--- a/src/librustc/ty/query/mod.rs
+++ b/src/librustc/ty/query/mod.rs
@@ -80,13 +80,14 @@
 use self::values::Value;
 
 mod config;
+pub(crate) use self::config::QueryDescription;
 pub use self::config::QueryConfig;
-use self::config::{QueryAccessors, QueryDescription};
+use self::config::QueryAccessors;
 
 mod on_disk_cache;
 pub use self::on_disk_cache::OnDiskCache;
 
-// Each of these quries corresponds to a function pointer field in the
+// Each of these queries corresponds to a function pointer field in the
 // `Providers` struct for requesting a value of that type, and a method
 // on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way
 // which memoizes and does dep-graph tracking, wrapping around the actual
@@ -97,35 +98,12 @@
 // (error) value if the query resulted in a query cycle.
 // Queries marked with `fatal_cycle` do not need the latter implementation,
 // as they will raise an fatal error on query cycles instead.
-define_queries! { <'tcx>
+
+rustc_query_append! { [define_queries!][ <'tcx>
     Other {
         /// Run analysis passes on the crate
         [] fn analysis: Analysis(CrateNum) -> Result<(), ErrorReported>,
 
-        /// Records the type of every item.
-        [] fn type_of: TypeOfItem(DefId) -> Ty<'tcx>,
-
-        /// Maps from the `DefId` of an item (trait/struct/enum/fn) to its
-        /// associated generics.
-        [] fn generics_of: GenericsOfItem(DefId) -> &'tcx ty::Generics,
-
-        /// Maps from the `DefId` of an item (trait/struct/enum/fn) to the
-        /// predicates (where-clauses) that must be proven true in order
-        /// to reference it. This is almost always the "predicates query"
-        /// that you want.
-        ///
-        /// `predicates_of` builds on `predicates_defined_on` -- in fact,
-        /// it is almost always the same as that query, except for the
-        /// case of traits. For traits, `predicates_of` contains
-        /// an additional `Self: Trait<...>` predicate that users don't
-        /// actually write. This reflects the fact that to invoke the
-        /// trait (e.g., via `Default::default`) you must supply types
-        /// that actually implement the trait. (However, this extra
-        /// predicate gets in the way of some checks, which are intended
-        /// to operate over only the actual where-clauses written by the
-        /// user.)
-        [] fn predicates_of: PredicatesOfItem(DefId) -> Lrc<ty::GenericPredicates<'tcx>>,
-
         /// Maps from the `DefId` of an item (trait/struct/enum/fn) to the
         /// predicates (where-clauses) directly defined on it. This is
         /// equal to the `explicit_predicates_of` predicates plus the
@@ -446,7 +424,6 @@
     },
 
     Codegen {
-        [fatal_cycle] fn is_panic_runtime: IsPanicRuntime(CrateNum) -> bool,
         [fatal_cycle] fn is_compiler_builtins: IsCompilerBuiltins(CrateNum) -> bool,
         [fatal_cycle] fn has_global_allocator: HasGlobalAllocator(CrateNum) -> bool,
         [fatal_cycle] fn has_panic_handler: HasPanicHandler(CrateNum) -> bool,
@@ -504,8 +481,6 @@
     },
 
     Other {
-        [] fn native_libraries: NativeLibraries(CrateNum) -> Lrc<Vec<NativeLibrary>>,
-
         [] fn foreign_modules: ForeignModules(CrateNum) -> Lrc<Vec<ForeignModule>>,
 
         /// Identifies the entry-point (e.g., the `main` function) for a given
@@ -752,7 +727,7 @@
         [] fn wasm_import_module_map: WasmImportModuleMap(CrateNum)
             -> Lrc<FxHashMap<DefId, String>>,
     },
-}
+]}
 
 //////////////////////////////////////////////////////////////////////
 // These functions are little shims used to find the dep-node for a
diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs
index e3276ba..e82e09c 100644
--- a/src/librustc/ty/query/plumbing.rs
+++ b/src/librustc/ty/query/plumbing.rs
@@ -4,11 +4,10 @@
 
 use crate::dep_graph::{DepNodeIndex, DepNode, DepKind, SerializedDepNodeIndex};
 use crate::ty::tls;
-use crate::ty::{TyCtxt};
+use crate::ty::{self, TyCtxt};
 use crate::ty::query::Query;
 use crate::ty::query::config::{QueryConfig, QueryDescription};
 use crate::ty::query::job::{QueryJob, QueryResult, QueryInfo};
-use crate::ty::item_path;
 
 use crate::util::common::{profq_msg, ProfileQueriesMsg, QueryMsg};
 
@@ -299,7 +298,7 @@
         // sometimes cycles itself, leading to extra cycle errors.
         // (And cycle errors around impls tend to occur during the
         // collect/coherence phases anyhow.)
-        item_path::with_forced_impl_filename_line(|| {
+        ty::print::with_forced_impl_filename_line(|| {
             let span = fix_span(stack[1 % stack.len()].span, &stack[0].query);
             let mut err = struct_span_err!(self.sess,
                                            span,
@@ -1132,10 +1131,12 @@
 /// then `force_from_dep_node()` should not fail for it. Otherwise, you can just
 /// add it to the "We don't have enough information to reconstruct..." group in
 /// the match below.
-pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
-                                           dep_node: &DepNode)
-                                           -> bool {
+pub fn force_from_dep_node<'tcx>(
+    tcx: TyCtxt<'_, 'tcx, 'tcx>,
+    dep_node: &DepNode
+) -> bool {
     use crate::hir::def_id::LOCAL_CRATE;
+    use crate::dep_graph::RecoverKey;
 
     // We must avoid ever having to call force_from_dep_node() for a
     // DepNode::CodegenUnit:
@@ -1172,17 +1173,26 @@
         () => { (def_id!()).krate }
     };
 
-    macro_rules! force {
-        ($query:ident, $key:expr) => {
+    macro_rules! force_ex {
+        ($tcx:expr, $query:ident, $key:expr) => {
             {
-                tcx.force_query::<crate::ty::query::queries::$query<'_>>($key, DUMMY_SP, *dep_node);
+                $tcx.force_query::<crate::ty::query::queries::$query<'_>>(
+                    $key,
+                    DUMMY_SP,
+                    *dep_node
+                );
             }
         }
     };
 
+    macro_rules! force {
+        ($query:ident, $key:expr) => { force_ex!(tcx, $query, $key) }
+    };
+
     // FIXME(#45015): We should try move this boilerplate code into a macro
     //                somehow.
-    match dep_node.kind {
+
+    rustc_dep_node_force!([dep_node, tcx]
         // These are inputs that are expected to be pre-allocated and that
         // should therefore always be red or green already
         DepKind::AllLocalTraitImpls |
@@ -1275,9 +1285,6 @@
         DepKind::MirKeys => { force!(mir_keys, LOCAL_CRATE); }
         DepKind::CrateVariances => { force!(crate_variances, LOCAL_CRATE); }
         DepKind::AssociatedItems => { force!(associated_item, def_id!()); }
-        DepKind::TypeOfItem => { force!(type_of, def_id!()); }
-        DepKind::GenericsOfItem => { force!(generics_of, def_id!()); }
-        DepKind::PredicatesOfItem => { force!(predicates_of, def_id!()); }
         DepKind::PredicatesDefinedOnItem => { force!(predicates_defined_on, def_id!()); }
         DepKind::ExplicitPredicatesOfItem => { force!(explicit_predicates_of, def_id!()); }
         DepKind::InferredOutlivesOf => { force!(inferred_outlives_of, def_id!()); }
@@ -1333,7 +1340,6 @@
         DepKind::FnArgNames => { force!(fn_arg_names, def_id!()); }
         DepKind::RenderedConst => { force!(rendered_const, def_id!()); }
         DepKind::DylibDepFormats => { force!(dylib_dependency_formats, krate!()); }
-        DepKind::IsPanicRuntime => { force!(is_panic_runtime, krate!()); }
         DepKind::IsCompilerBuiltins => { force!(is_compiler_builtins, krate!()); }
         DepKind::HasGlobalAllocator => { force!(has_global_allocator, krate!()); }
         DepKind::HasPanicHandler => { force!(has_panic_handler, krate!()); }
@@ -1350,7 +1356,6 @@
         DepKind::CheckTraitItemWellFormed => { force!(check_trait_item_well_formed, def_id!()); }
         DepKind::CheckImplItemWellFormed => { force!(check_impl_item_well_formed, def_id!()); }
         DepKind::ReachableNonGenerics => { force!(reachable_non_generics, krate!()); }
-        DepKind::NativeLibraries => { force!(native_libraries, krate!()); }
         DepKind::EntryFn => { force!(entry_fn, krate!()); }
         DepKind::PluginRegistrarFn => { force!(plugin_registrar_fn, krate!()); }
         DepKind::ProcMacroDeclsStatic => { force!(proc_macro_decls_static, krate!()); }
@@ -1433,7 +1438,7 @@
         DepKind::BackendOptimizationLevel => {
             force!(backend_optimization_level, krate!());
         }
-    }
+    );
 
     true
 }
@@ -1494,9 +1499,9 @@
     SymbolName => def_symbol_name,
     ConstIsRvaluePromotableToStatic => const_is_rvalue_promotable_to_static,
     CheckMatch => check_match,
-    TypeOfItem => type_of,
-    GenericsOfItem => generics_of,
-    PredicatesOfItem => predicates_of,
+    type_of => type_of,
+    generics_of => generics_of,
+    predicates_of => predicates_of,
     UsedTraitImports => used_trait_imports,
     CodegenFnAttrs => codegen_fn_attrs,
     SpecializationGraph => specialization_graph_of,
diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs
index 3a31801..810bd10 100644
--- a/src/librustc/ty/relate.rs
+++ b/src/librustc/ty/relate.rs
@@ -8,7 +8,7 @@
 use crate::ty::subst::{Kind, UnpackedKind, SubstsRef};
 use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
 use crate::ty::error::{ExpectedFound, TypeError};
-use crate::mir::interpret::GlobalId;
+use crate::mir::interpret::{GlobalId, ConstValue};
 use crate::util::common::ErrorReported;
 use syntax_pos::DUMMY_SP;
 use std::rc::Rc;
@@ -351,10 +351,8 @@
     where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
 {
     let tcx = relation.tcx();
-    let a_sty = &a.sty;
-    let b_sty = &b.sty;
-    debug!("super_relate_tys: a_sty={:?} b_sty={:?}", a_sty, b_sty);
-    match (a_sty, b_sty) {
+    debug!("super_relate_tys: a={:?} b={:?}", a, b);
+    match (&a.sty, &b.sty) {
         (&ty::Infer(_), _) |
         (_, &ty::Infer(_)) =>
         {
@@ -468,9 +466,9 @@
         (&ty::Array(a_t, sz_a), &ty::Array(b_t, sz_b)) =>
         {
             let t = relation.relate(&a_t, &b_t)?;
-            let to_u64 = |x: ty::LazyConst<'tcx>| -> Result<u64, ErrorReported> {
-                match x {
-                    ty::LazyConst::Unevaluated(def_id, substs) => {
+            let to_u64 = |x: ty::Const<'tcx>| -> Result<u64, ErrorReported> {
+                match x.val {
+                    ConstValue::Unevaluated(def_id, substs) => {
                         // FIXME(eddyb) get the right param_env.
                         let param_env = ty::ParamEnv::empty();
                         if let Some(substs) = tcx.lift_to_global(&substs) {
@@ -496,7 +494,7 @@
                             "array length could not be evaluated");
                         Err(ErrorReported)
                     }
-                    ty::LazyConst::Evaluated(c) => c.assert_usize(tcx).ok_or_else(|| {
+                    _ => x.assert_usize(tcx).ok_or_else(|| {
                         tcx.sess.delay_span_bug(DUMMY_SP,
                             "array length could not be evaluated");
                         ErrorReported
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index f9eb336..cbdda73 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -3,17 +3,288 @@
 //! hand, though we've recently added some macros (e.g.,
 //! `BraceStructLiftImpl!`) to help with the tedium.
 
+use crate::hir::def::Namespace;
 use crate::mir::ProjectionKind;
 use crate::mir::interpret::ConstValue;
-use crate::ty::{self, Lift, Ty, TyCtxt, ConstVid, InferConst};
+use crate::ty::{self, Lift, Ty, TyCtxt, ConstVid};
 use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
+use crate::ty::print::{FmtPrinter, Printer};
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
 use smallvec::SmallVec;
 use crate::mir::interpret;
 
+use std::fmt;
 use std::marker::PhantomData;
 use std::rc::Rc;
 
+impl fmt::Debug for ty::GenericParamDef {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let type_name = match self.kind {
+            ty::GenericParamDefKind::Lifetime => "Lifetime",
+            ty::GenericParamDefKind::Type {..} => "Type",
+            ty::GenericParamDefKind::Const => "Const",
+        };
+        write!(f, "{}({}, {:?}, {})",
+               type_name,
+               self.name,
+               self.def_id,
+               self.index)
+    }
+}
+
+impl fmt::Debug for ty::TraitDef {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        ty::tls::with(|tcx| {
+            FmtPrinter::new(tcx, f, Namespace::TypeNS)
+                .print_def_path(self.def_id, &[])?;
+            Ok(())
+        })
+    }
+}
+
+impl fmt::Debug for ty::AdtDef {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        ty::tls::with(|tcx| {
+            FmtPrinter::new(tcx, f, Namespace::TypeNS)
+                .print_def_path(self.did, &[])?;
+            Ok(())
+        })
+    }
+}
+
+impl fmt::Debug for ty::ClosureUpvar<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "ClosureUpvar({:?},{:?})",
+               self.def,
+               self.ty)
+    }
+}
+
+impl fmt::Debug for ty::UpvarId {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let name = ty::tls::with(|tcx| {
+            tcx.hir().name_by_hir_id(self.var_path.hir_id)
+        });
+        write!(f, "UpvarId({:?};`{}`;{:?})",
+            self.var_path.hir_id,
+            name,
+            self.closure_expr_id)
+    }
+}
+
+impl fmt::Debug for ty::UpvarBorrow<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "UpvarBorrow({:?}, {:?})",
+               self.kind, self.region)
+    }
+}
+
+impl fmt::Debug for ty::ExistentialTraitRef<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Display::fmt(self, f)
+    }
+}
+
+impl fmt::Debug for ty::adjustment::Adjustment<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?} -> {}", self.kind, self.target)
+    }
+}
+
+impl fmt::Debug for ty::BoundRegion {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match *self {
+            ty::BrAnon(n) => write!(f, "BrAnon({:?})", n),
+            ty::BrFresh(n) => write!(f, "BrFresh({:?})", n),
+            ty::BrNamed(did, name) => {
+                write!(f, "BrNamed({:?}:{:?}, {})",
+                        did.krate, did.index, name)
+            }
+            ty::BrEnv => write!(f, "BrEnv"),
+        }
+    }
+}
+
+impl fmt::Debug for ty::RegionKind {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match *self {
+            ty::ReEarlyBound(ref data) => {
+                write!(f, "ReEarlyBound({}, {})",
+                        data.index,
+                        data.name)
+            }
+
+            ty::ReClosureBound(ref vid) => {
+                write!(f, "ReClosureBound({:?})", vid)
+            }
+
+            ty::ReLateBound(binder_id, ref bound_region) => {
+                write!(f, "ReLateBound({:?}, {:?})", binder_id, bound_region)
+            }
+
+            ty::ReFree(ref fr) => fr.fmt(f),
+
+            ty::ReScope(id) => write!(f, "ReScope({:?})", id),
+
+            ty::ReStatic => write!(f, "ReStatic"),
+
+            ty::ReVar(ref vid) => vid.fmt(f),
+
+            ty::RePlaceholder(placeholder) => {
+                write!(f, "RePlaceholder({:?})", placeholder)
+            }
+
+            ty::ReEmpty => write!(f, "ReEmpty"),
+
+            ty::ReErased => write!(f, "ReErased"),
+        }
+    }
+}
+
+impl fmt::Debug for ty::FreeRegion {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "ReFree({:?}, {:?})", self.scope, self.bound_region)
+    }
+}
+
+impl fmt::Debug for ty::Variance {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.write_str(match *self {
+            ty::Covariant => "+",
+            ty::Contravariant => "-",
+            ty::Invariant => "o",
+            ty::Bivariant => "*",
+        })
+    }
+}
+
+impl fmt::Debug for ty::FnSig<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "({:?}; c_variadic: {})->{:?}",
+                self.inputs(), self.c_variadic, self.output())
+    }
+}
+
+impl fmt::Debug for ty::TyVid {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "_#{}t", self.index)
+    }
+}
+
+impl<'tcx> fmt::Debug for ty::ConstVid<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "_#{}c", self.index)
+    }
+}
+
+impl fmt::Debug for ty::IntVid {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "_#{}i", self.index)
+    }
+}
+
+impl fmt::Debug for ty::FloatVid {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "_#{}f", self.index)
+    }
+}
+
+impl fmt::Debug for ty::RegionVid {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "'_#{}r", self.index())
+    }
+}
+
+impl fmt::Debug for ty::InferTy {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match *self {
+            ty::TyVar(ref v) => v.fmt(f),
+            ty::IntVar(ref v) => v.fmt(f),
+            ty::FloatVar(ref v) => v.fmt(f),
+            ty::FreshTy(v) => write!(f, "FreshTy({:?})", v),
+            ty::FreshIntTy(v) => write!(f, "FreshIntTy({:?})", v),
+            ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({:?})", v),
+        }
+    }
+}
+
+impl fmt::Debug for ty::IntVarValue {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match *self {
+            ty::IntType(ref v) => v.fmt(f),
+            ty::UintType(ref v) => v.fmt(f),
+        }
+    }
+}
+
+impl fmt::Debug for ty::FloatVarValue {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
+impl fmt::Debug for ty::TraitRef<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        // FIXME(#59188) this is used across the compiler to print
+        // a `TraitRef` qualified (with the Self type explicit),
+        // instead of having a different way to make that choice.
+        write!(f, "<{} as {}>", self.self_ty(), self)
+    }
+}
+
+impl fmt::Debug for Ty<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Display::fmt(self, f)
+    }
+}
+
+impl fmt::Debug for ty::ParamTy {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{}/#{}", self.name, self.idx)
+    }
+}
+
+impl fmt::Debug for ty::ParamConst {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{}/#{}", self.name, self.index)
+    }
+}
+
+impl fmt::Debug for ty::TraitPredicate<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "TraitPredicate({:?})", self.trait_ref)
+    }
+}
+
+impl fmt::Debug for ty::ProjectionPredicate<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "ProjectionPredicate({:?}, {:?})", self.projection_ty, self.ty)
+    }
+}
+
+impl fmt::Debug for ty::Predicate<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match *self {
+            ty::Predicate::Trait(ref a) => a.fmt(f),
+            ty::Predicate::Subtype(ref pair) => pair.fmt(f),
+            ty::Predicate::RegionOutlives(ref pair) => pair.fmt(f),
+            ty::Predicate::TypeOutlives(ref pair) => pair.fmt(f),
+            ty::Predicate::Projection(ref pair) => pair.fmt(f),
+            ty::Predicate::WellFormed(ty) => write!(f, "WellFormed({:?})", ty),
+            ty::Predicate::ObjectSafe(trait_def_id) => {
+                write!(f, "ObjectSafe({:?})", trait_def_id)
+            }
+            ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
+                write!(f, "ClosureKind({:?}, {:?}, {:?})",
+                    closure_def_id, closure_substs, kind)
+            }
+            ty::Predicate::ConstEvaluatable(def_id, substs) => {
+                write!(f, "ConstEvaluatable({:?}, {:?})", def_id, substs)
+            }
+        }
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // Atomic structs
 //
@@ -48,10 +319,14 @@
     // really meant to be folded. In general, we can only fold a fully
     // general `Region`.
     crate::ty::BoundRegion,
+    crate::ty::Placeholder<crate::ty::BoundRegion>,
     crate::ty::ClosureKind,
+    crate::ty::FreeRegion,
+    crate::ty::InferTy,
     crate::ty::IntVarValue,
     crate::ty::ParamConst,
     crate::ty::ParamTy,
+    crate::ty::RegionVid,
     crate::ty::UniverseIndex,
     crate::ty::Variance,
     ::syntax_pos::Span,
@@ -60,6 +335,7 @@
 ///////////////////////////////////////////////////////////////////////////
 // Lift implementations
 
+// FIXME(eddyb) replace all the uses of `Option::map` with `?`.
 impl<'tcx, A: Lift<'tcx>, B: Lift<'tcx>> Lift<'tcx> for (A, B) {
     type Lifted = (A::Lifted, B::Lifted);
     fn lift_to_tcx<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Self::Lifted> {
@@ -156,6 +432,23 @@
     }
 }
 
+impl<'a, 'tcx> Lift<'tcx> for ty::ExistentialPredicate<'a> {
+    type Lifted = ty::ExistentialPredicate<'tcx>;
+    fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
+        match self {
+            ty::ExistentialPredicate::Trait(x) => {
+                tcx.lift(x).map(ty::ExistentialPredicate::Trait)
+            }
+            ty::ExistentialPredicate::Projection(x) => {
+                tcx.lift(x).map(ty::ExistentialPredicate::Projection)
+            }
+            ty::ExistentialPredicate::AutoTrait(def_id) => {
+                Some(ty::ExistentialPredicate::AutoTrait(*def_id))
+            }
+        }
+    }
+}
+
 impl<'a, 'tcx> Lift<'tcx> for ty::TraitPredicate<'a> {
     type Lifted = ty::TraitPredicate<'tcx>;
     fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>)
@@ -481,6 +774,13 @@
 }
 
 BraceStructLiftImpl! {
+    impl<'a, 'tcx> Lift<'tcx> for ty::TypeAndMut<'a> {
+        type Lifted = ty::TypeAndMut<'tcx>;
+        ty, mutbl
+    }
+}
+
+BraceStructLiftImpl! {
     impl<'a, 'tcx> Lift<'tcx> for ty::Instance<'a> {
         type Lifted = ty::Instance<'tcx>;
         def, substs
@@ -494,34 +794,6 @@
     }
 }
 
-BraceStructLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for ty::Const<'a> {
-        type Lifted = ty::Const<'tcx>;
-        val, ty
-    }
-}
-
-impl<'a, 'tcx> Lift<'tcx> for ConstValue<'a> {
-    type Lifted = ConstValue<'tcx>;
-    fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
-        match *self {
-            ConstValue::Param(param) => Some(ConstValue::Param(param)),
-            ConstValue::Infer(infer) => {
-                Some(ConstValue::Infer(match infer {
-                    InferConst::Var(vid) => InferConst::Var(vid.lift_to_tcx(tcx)?),
-                    InferConst::Fresh(i) => InferConst::Fresh(i),
-                    InferConst::Canonical(debrujin, var) => InferConst::Canonical(debrujin, var),
-                }))
-            }
-            ConstValue::Scalar(x) => Some(ConstValue::Scalar(x)),
-            ConstValue::Slice(x, y) => Some(ConstValue::Slice(x, y)),
-            ConstValue::ByRef(ptr, alloc) => Some(ConstValue::ByRef(
-                ptr, alloc.lift_to_tcx(tcx)?,
-            )),
-        }
-    }
-}
-
 impl<'a, 'tcx> Lift<'tcx> for ConstVid<'a> {
     type Lifted = ConstVid<'tcx>;
     fn lift_to_tcx<'b, 'gcx>(&self, _: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
@@ -1062,15 +1334,14 @@
     }
 }
 
-impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::LazyConst<'tcx> {
+impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Const<'tcx> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
-        let new = match self {
-            ty::LazyConst::Evaluated(v) => ty::LazyConst::Evaluated(v.fold_with(folder)),
-            ty::LazyConst::Unevaluated(def_id, substs) => {
-                ty::LazyConst::Unevaluated(*def_id, substs.fold_with(folder))
-            }
-        };
-        folder.tcx().mk_lazy_const(new)
+        let ty = self.ty.fold_with(folder);
+        let val = self.val.fold_with(folder);
+        folder.tcx().mk_const(ty::Const {
+            ty,
+            val
+        })
     }
 
     fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
@@ -1078,10 +1349,7 @@
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
-        match *self {
-            ty::LazyConst::Evaluated(c) => c.visit_with(visitor),
-            ty::LazyConst::Unevaluated(_, substs) => substs.visit_with(visitor),
-        }
+        self.ty.visit_with(visitor) || self.val.visit_with(visitor)
     }
 
     fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
@@ -1089,27 +1357,29 @@
     }
 }
 
-impl<'tcx> TypeFoldable<'tcx> for ty::Const<'tcx> {
+impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
-        let ty = self.ty.fold_with(folder);
-        let val = self.val.fold_with(folder);
-        ty::Const {
-            ty,
-            val
+        match *self {
+            ConstValue::ByRef(ptr, alloc) => ConstValue::ByRef(ptr, alloc),
+            // FIXME(const_generics): implement TypeFoldable for InferConst
+            ConstValue::Infer(ic) => ConstValue::Infer(ic),
+            ConstValue::Param(p) => ConstValue::Param(p.fold_with(folder)),
+            ConstValue::Scalar(a) => ConstValue::Scalar(a),
+            ConstValue::Slice(a, b) => ConstValue::Slice(a, b),
+            ConstValue::Unevaluated(did, substs)
+                => ConstValue::Unevaluated(did, substs.fold_with(folder)),
         }
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
-        self.ty.visit_with(visitor) || self.val.visit_with(visitor)
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> {
-    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _folder: &mut F) -> Self {
-        *self
-    }
-
-    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> bool {
-        false
+        match *self {
+            ConstValue::ByRef(..) => false,
+            // FIXME(const_generics): implement TypeFoldable for InferConst
+            ConstValue::Infer(_ic) => false,
+            ConstValue::Param(p) => p.visit_with(visitor),
+            ConstValue::Scalar(_) => false,
+            ConstValue::Slice(..) => false,
+            ConstValue::Unevaluated(_, substs) => substs.visit_with(visitor),
+        }
     }
 }
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 39728cc..df76e61 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -9,7 +9,7 @@
 use rustc_data_structures::indexed_vec::Idx;
 use rustc_macros::HashStable;
 use crate::ty::subst::{InternalSubsts, Subst, SubstsRef, Kind, UnpackedKind};
-use crate::ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable};
+use crate::ty::{self, AdtDef, DefIdTree, TypeFlags, Ty, TyCtxt, TypeFoldable};
 use crate::ty::{List, TyS, ParamEnvAnd, ParamEnv};
 use crate::util::captures::Captures;
 use crate::mir::interpret::{Scalar, Pointer};
@@ -84,7 +84,7 @@
 
 /// N.B., if you change this, you'll probably want to change the corresponding
 /// AST structure in `libsyntax/ast.rs` as well.
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug,
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash,
          RustcEncodable, RustcDecodable, HashStable)]
 pub enum TyKind<'tcx> {
     /// The primitive boolean type. Written as `bool`.
@@ -118,7 +118,7 @@
     Str,
 
     /// An array with the given length. Written as `[T; n]`.
-    Array(Ty<'tcx>, &'tcx ty::LazyConst<'tcx>),
+    Array(Ty<'tcx>, &'tcx ty::Const<'tcx>),
 
     /// The pointee of an array slice. Written as `[T]`.
     Slice(Ty<'tcx>),
@@ -383,9 +383,10 @@
     ///
     /// If you have an inference context, use `infcx.closure_sig()`.
     pub fn closure_sig(self, def_id: DefId, tcx: TyCtxt<'_, 'tcx, 'tcx>) -> ty::PolyFnSig<'tcx> {
-        match self.closure_sig_ty(def_id, tcx).sty {
+        let ty = self.closure_sig_ty(def_id, tcx);
+        match ty.sty {
             ty::FnPtr(sig) => sig,
-            ref t => bug!("closure_sig_ty is not a fn-ptr: {:?}", t),
+            _ => bug!("closure_sig_ty is not a fn-ptr: {:?}", ty),
         }
     }
 }
@@ -1088,7 +1089,7 @@
         ParamConst::new(def.index, def.name)
     }
 
-    pub fn to_const(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, ty: Ty<'tcx>) -> &'tcx LazyConst<'tcx> {
+    pub fn to_const(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, ty: Ty<'tcx>) -> &'tcx Const<'tcx> {
         tcx.mk_const_param(self.index, self.name, ty)
     }
 }
@@ -1590,7 +1591,7 @@
     pub fn free_region_binding_scope(&self, tcx: TyCtxt<'_, '_, '_>) -> DefId {
         match self {
             ty::ReEarlyBound(br) => {
-                tcx.parent_def_id(br.def_id).unwrap()
+                tcx.parent(br.def_id).unwrap()
             }
             ty::ReFree(fr) => fr.scope,
             _ => bug!("free_region_binding_scope invoked on inappropriate region: {:?}", self),
@@ -1910,7 +1911,6 @@
 
     pub fn is_machine(&self) -> bool {
         match self.sty {
-            Int(ast::IntTy::Isize) | Uint(ast::UintTy::Usize) => false,
             Int(..) | Uint(..) | Float(..) => true,
             _ => false,
         }
@@ -2096,52 +2096,6 @@
     }
 }
 
-#[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable,
-         Eq, PartialEq, Ord, PartialOrd, HashStable)]
-/// Used in the HIR by using `Unevaluated` everywhere and later normalizing to `Evaluated` if the
-/// code is monomorphic enough for that.
-pub enum LazyConst<'tcx> {
-    Unevaluated(DefId, SubstsRef<'tcx>),
-    Evaluated(Const<'tcx>),
-}
-
-#[cfg(target_arch = "x86_64")]
-static_assert!(LAZY_CONST_SIZE: ::std::mem::size_of::<LazyConst<'static>>() == 56);
-
-impl<'tcx> LazyConst<'tcx> {
-    pub fn map_evaluated<R>(self, f: impl FnOnce(Const<'tcx>) -> Option<R>) -> Option<R> {
-        match self {
-            LazyConst::Evaluated(c) => f(c),
-            LazyConst::Unevaluated(..) => None,
-        }
-    }
-
-    pub fn assert_usize(self, tcx: TyCtxt<'_, '_, '_>) -> Option<u64> {
-        self.map_evaluated(|c| c.assert_usize(tcx))
-    }
-
-    #[inline]
-    pub fn unwrap_usize(&self, tcx: TyCtxt<'_, '_, '_>) -> u64 {
-        self.assert_usize(tcx).expect("expected `LazyConst` to contain a usize")
-    }
-
-    pub fn type_flags(&self) -> TypeFlags {
-        // FIXME(const_generics): incorporate substs flags.
-        let flags = match self {
-            LazyConst::Unevaluated(..) => {
-                TypeFlags::HAS_NORMALIZABLE_PROJECTION | TypeFlags::HAS_PROJECTION
-            }
-            LazyConst::Evaluated(c) => {
-                c.type_flags()
-            }
-        };
-
-        debug!("type_flags({:?}) = {:?}", self, flags);
-
-        flags
-    }
-}
-
 /// Typed constant value.
 #[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable,
          Eq, PartialEq, Ord, PartialOrd, HashStable)]
@@ -2256,36 +2210,9 @@
         self.assert_usize(tcx).unwrap_or_else(||
             bug!("expected constant usize, got {:#?}", self))
     }
-
-    pub fn type_flags(&self) -> TypeFlags {
-        let mut flags = self.ty.flags;
-
-        match self.val {
-            ConstValue::Param(_) => {
-                flags |= TypeFlags::HAS_FREE_LOCAL_NAMES;
-                flags |= TypeFlags::HAS_PARAMS;
-            }
-            ConstValue::Infer(infer) => {
-                flags |= TypeFlags::HAS_FREE_LOCAL_NAMES;
-                flags |= TypeFlags::HAS_CT_INFER;
-                match infer {
-                    InferConst::Fresh(_) |
-                    InferConst::Canonical(_, _) => {}
-                    InferConst::Var(_) => {
-                        flags |= TypeFlags::KEEP_IN_LOCAL_TCX;
-                    }
-                }
-            }
-            _ => {}
-        }
-
-        debug!("type_flags({:?}) = {:?}", self, flags);
-
-        flags
-    }
 }
 
-impl<'tcx> serialize::UseSpecializedDecodable for &'tcx LazyConst<'tcx> {}
+impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Const<'tcx> {}
 
 /// An inference variable for a const, for use in const generics.
 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd,
diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs
index 38be19a..3ba2c4c 100644
--- a/src/librustc/ty/subst.rs
+++ b/src/librustc/ty/subst.rs
@@ -12,8 +12,8 @@
 use rustc_macros::HashStable;
 
 use core::intrinsics;
-use std::cmp::Ordering;
 use std::fmt;
+use std::cmp::Ordering;
 use std::marker::PhantomData;
 use std::mem;
 use std::num::NonZeroUsize;
@@ -26,7 +26,7 @@
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 pub struct Kind<'tcx> {
     ptr: NonZeroUsize,
-    marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>, &'tcx ty::LazyConst<'tcx>)>
+    marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>, &'tcx ty::Const<'tcx>)>
 }
 
 const TAG_MASK: usize = 0b11;
@@ -38,7 +38,7 @@
 pub enum UnpackedKind<'tcx> {
     Lifetime(ty::Region<'tcx>),
     Type(Ty<'tcx>),
-    Const(&'tcx ty::LazyConst<'tcx>),
+    Const(&'tcx ty::Const<'tcx>),
 }
 
 impl<'tcx> UnpackedKind<'tcx> {
@@ -70,6 +70,16 @@
     }
 }
 
+impl fmt::Debug for Kind<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self.unpack() {
+            UnpackedKind::Lifetime(lt) => lt.fmt(f),
+            UnpackedKind::Type(ty) => ty.fmt(f),
+            UnpackedKind::Const(ct) => ct.fmt(f),
+        }
+    }
+}
+
 impl<'tcx> Ord for Kind<'tcx> {
     fn cmp(&self, other: &Kind<'_>) -> Ordering {
         self.unpack().cmp(&other.unpack())
@@ -94,8 +104,8 @@
     }
 }
 
-impl<'tcx> From<&'tcx ty::LazyConst<'tcx>> for Kind<'tcx> {
-    fn from(c: &'tcx ty::LazyConst<'tcx>) -> Kind<'tcx> {
+impl<'tcx> From<&'tcx ty::Const<'tcx>> for Kind<'tcx> {
+    fn from(c: &'tcx ty::Const<'tcx>) -> Kind<'tcx> {
         UnpackedKind::Const(c).pack()
     }
 }
@@ -115,34 +125,14 @@
     }
 }
 
-impl<'tcx> fmt::Debug for Kind<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.unpack() {
-            UnpackedKind::Lifetime(lt) => write!(f, "{:?}", lt),
-            UnpackedKind::Type(ty) => write!(f, "{:?}", ty),
-            UnpackedKind::Const(ct) => write!(f, "{:?}", ct),
-        }
-    }
-}
-
-impl<'tcx> fmt::Display for Kind<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.unpack() {
-            UnpackedKind::Lifetime(lt) => write!(f, "{}", lt),
-            UnpackedKind::Type(ty) => write!(f, "{}", ty),
-            UnpackedKind::Const(ct) => write!(f, "{}", ct),
-        }
-    }
-}
-
 impl<'a, 'tcx> Lift<'tcx> for Kind<'a> {
     type Lifted = Kind<'tcx>;
 
     fn lift_to_tcx<'cx, 'gcx>(&self, tcx: TyCtxt<'cx, 'gcx, 'tcx>) -> Option<Self::Lifted> {
         match self.unpack() {
-            UnpackedKind::Lifetime(lt) => lt.lift_to_tcx(tcx).map(|lt| lt.into()),
-            UnpackedKind::Type(ty) => ty.lift_to_tcx(tcx).map(|ty| ty.into()),
-            UnpackedKind::Const(ct) => ct.lift_to_tcx(tcx).map(|ct| ct.into()),
+            UnpackedKind::Lifetime(lt) => tcx.lift(&lt).map(|lt| lt.into()),
+            UnpackedKind::Type(ty) => tcx.lift(&ty).map(|ty| ty.into()),
+            UnpackedKind::Const(ct) => tcx.lift(&ct).map(|ct| ct.into()),
         }
     }
 }
@@ -218,12 +208,12 @@
                 }
 
                 ty::GenericParamDefKind::Const => {
-                    tcx.mk_lazy_const(ty::LazyConst::Evaluated(ty::Const {
+                    tcx.mk_const(ty::Const {
                         val: ConstValue::Infer(
                             InferConst::Canonical(ty::INNERMOST, ty::BoundVar::from(param.index))
                         ),
                         ty: tcx.type_of(def_id),
-                    })).into()
+                    }).into()
                 }
             }
         })
@@ -314,7 +304,7 @@
     }
 
     #[inline]
-    pub fn consts(&'a self) -> impl DoubleEndedIterator<Item = &'tcx ty::LazyConst<'tcx>> + 'a {
+    pub fn consts(&'a self) -> impl DoubleEndedIterator<Item = &'tcx ty::Const<'tcx>> + 'a {
         self.iter().filter_map(|k| {
             if let UnpackedKind::Const(ct) = k.unpack() {
                 Some(ct)
@@ -355,7 +345,7 @@
     }
 
     #[inline]
-    pub fn const_at(&self, i: usize) -> &'tcx ty::LazyConst<'tcx> {
+    pub fn const_at(&self, i: usize) -> &'tcx ty::Const<'tcx> {
         if let UnpackedKind::Const(ct) = self[i].unpack() {
             ct
         } else {
@@ -532,16 +522,13 @@
         return t1;
     }
 
-    fn fold_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
+    fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
         if !c.needs_subst() {
             return c;
         }
 
-        if let ty::LazyConst::Evaluated(ty::Const {
-            val: ConstValue::Param(p),
-            ..
-        }) = c {
-            self.const_for_param(*p, c)
+        if let ConstValue::Param(p) = c.val {
+            self.const_for_param(p, c)
         } else {
             c.super_fold_with(self)
         }
@@ -574,8 +561,8 @@
     fn const_for_param(
         &self,
         p: ParamConst,
-        source_cn: &'tcx ty::LazyConst<'tcx>
-    ) -> &'tcx ty::LazyConst<'tcx> {
+        source_cn: &'tcx ty::Const<'tcx>
+    ) -> &'tcx ty::Const<'tcx> {
         // Look up the const in the substitutions. It really should be in there.
         let opt_cn = self.substs.get(p.index as usize).map(|k| k.unpack());
         let cn = match opt_cn {
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 422f97b..4fb2bfb 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -7,7 +7,7 @@
 use crate::mir::interpret::{sign_extend, truncate};
 use crate::ich::NodeIdHashingMode;
 use crate::traits::{self, ObligationCause};
-use crate::ty::{self, Ty, TyCtxt, GenericParamDefKind, TypeFoldable};
+use crate::ty::{self, DefIdTree, Ty, TyCtxt, GenericParamDefKind, TypeFoldable};
 use crate::ty::subst::{Subst, InternalSubsts, SubstsRef, UnpackedKind};
 use crate::ty::query::TyCtxtAt;
 use crate::ty::TyKind::*;
@@ -497,10 +497,10 @@
                     }) => {
                         !impl_generics.type_param(pt, self).pure_wrt_drop
                     }
-                    UnpackedKind::Const(&ty::LazyConst::Evaluated(ty::Const {
+                    UnpackedKind::Const(&ty::Const {
                         val: ConstValue::Param(ref pc),
                         ..
-                    })) => {
+                    }) => {
                         !impl_generics.const_param(pc, self).pure_wrt_drop
                     }
                     UnpackedKind::Lifetime(_) |
@@ -563,7 +563,7 @@
     pub fn closure_base_def_id(self, def_id: DefId) -> DefId {
         let mut def_id = def_id;
         while self.is_closure(def_id) {
-            def_id = self.parent_def_id(def_id).unwrap_or_else(|| {
+            def_id = self.parent(def_id).unwrap_or_else(|| {
                 bug!("closure {:?} has no parent", def_id);
             });
         }
diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs
index d9f309a..fa1eadf 100644
--- a/src/librustc/ty/walk.rs
+++ b/src/librustc/ty/walk.rs
@@ -3,6 +3,7 @@
 
 use crate::ty::{self, Ty};
 use smallvec::{self, SmallVec};
+use crate::mir::interpret::ConstValue;
 
 // The TypeWalker's stack is hot enough that it's worth going to some effort to
 // avoid heap allocations.
@@ -74,9 +75,10 @@
         ty::Placeholder(..) | ty::Bound(..) | ty::Foreign(..) => {
         }
         ty::Array(ty, len) => {
-            if let ty::LazyConst::Unevaluated(_, substs) = len {
+            if let ConstValue::Unevaluated(_, substs) = len.val {
                 stack.extend(substs.types().rev());
             }
+            stack.push(len.ty);
             stack.push(ty);
         }
         ty::Slice(ty) => {
diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs
index fa35416..7bfda6a 100644
--- a/src/librustc/ty/wf.rs
+++ b/src/librustc/ty/wf.rs
@@ -7,6 +7,7 @@
 use std::iter::once;
 use syntax_pos::Span;
 use crate::middle::lang_items;
+use crate::mir::interpret::ConstValue;
 
 /// Returns the set of obligations needed to make `ty` well-formed.
 /// If `ty` contains unresolved inference variables, this may include
@@ -203,8 +204,8 @@
 
     /// Pushes the obligations required for an array length to be WF
     /// into `self.out`.
-    fn compute_array_len(&mut self, constant: ty::LazyConst<'tcx>) {
-        if let ty::LazyConst::Unevaluated(def_id, substs) = constant {
+    fn compute_array_len(&mut self, constant: ty::Const<'tcx>) {
+        if let ConstValue::Unevaluated(def_id, substs) = constant.val {
             let obligations = self.nominal_obligations(def_id, substs);
             self.out.extend(obligations);
 
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
deleted file mode 100644
index a1398c6..0000000
--- a/src/librustc/util/ppaux.rs
+++ /dev/null
@@ -1,1667 +0,0 @@
-use crate::hir::def_id::DefId;
-use crate::hir::map::definitions::DefPathData;
-use crate::middle::region;
-use crate::ty::subst::{self, Subst, SubstsRef};
-use crate::ty::{BrAnon, BrEnv, BrFresh, BrNamed};
-use crate::ty::{Bool, Char, Adt};
-use crate::ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr};
-use crate::ty::{Param, Bound, RawPtr, Ref, Never, Tuple};
-use crate::ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque};
-use crate::ty::{Placeholder, UnnormalizedProjection, Dynamic, Int, Uint, Infer};
-use crate::ty::{self, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind, ParamConst};
-use crate::mir::interpret::ConstValue;
-use crate::util::nodemap::FxHashSet;
-
-use std::cell::Cell;
-use std::fmt;
-use std::usize;
-
-use rustc_target::spec::abi::Abi;
-use syntax::ast::CRATE_NODE_ID;
-use syntax::symbol::{Symbol, InternedString};
-use crate::hir;
-
-/// The "region highlights" are used to control region printing during
-/// specific error messages. When a "region highlight" is enabled, it
-/// gives an alternate way to print specific regions. For now, we
-/// always print those regions using a number, so something like "`'0`".
-///
-/// Regions not selected by the region highlight mode are presently
-/// unaffected.
-#[derive(Copy, Clone, Default)]
-pub struct RegionHighlightMode {
-    /// If enabled, when we see the selected region, use "`'N`"
-    /// instead of the ordinary behavior.
-    highlight_regions: [Option<(ty::RegionKind, usize)>; 3],
-
-    /// If enabled, when printing a "free region" that originated from
-    /// the given `ty::BoundRegion`, print it as "`'1`". Free regions that would ordinarily
-    /// have names print as normal.
-    ///
-    /// This is used when you have a signature like `fn foo(x: &u32,
-    /// y: &'a u32)` and we want to give a name to the region of the
-    /// reference `x`.
-    highlight_bound_region: Option<(ty::BoundRegion, usize)>,
-}
-
-thread_local! {
-    /// Mechanism for highlighting of specific regions for display in NLL region inference errors.
-    /// Contains region to highlight and counter for number to use when highlighting.
-    static REGION_HIGHLIGHT_MODE: Cell<RegionHighlightMode> =
-        Cell::new(RegionHighlightMode::default())
-}
-
-impl RegionHighlightMode {
-    /// Reads and returns the current region highlight settings (accesses thread-local state).
-    pub fn get() -> Self {
-        REGION_HIGHLIGHT_MODE.with(|c| c.get())
-    }
-
-    // Internal helper to update current settings during the execution of `op`.
-    fn set<R>(
-        old_mode: Self,
-        new_mode: Self,
-        op: impl FnOnce() -> R,
-    ) -> R {
-        REGION_HIGHLIGHT_MODE.with(|c| {
-            c.set(new_mode);
-            let result = op();
-            c.set(old_mode);
-            result
-        })
-    }
-
-    /// If `region` and `number` are both `Some`, invokes
-    /// `highlighting_region`; otherwise, just invokes `op` directly.
-    pub fn maybe_highlighting_region<R>(
-        region: Option<ty::Region<'_>>,
-        number: Option<usize>,
-        op: impl FnOnce() -> R,
-    ) -> R {
-        if let Some(k) = region {
-            if let Some(n) = number {
-                return Self::highlighting_region(k, n, op);
-            }
-        }
-
-        op()
-    }
-
-    /// During the execution of `op`, highlights the region inference
-    /// variable `vid` as `'N`. We can only highlight one region `vid`
-    /// at a time.
-    pub fn highlighting_region<R>(
-        region: ty::Region<'_>,
-        number: usize,
-        op: impl FnOnce() -> R,
-    ) -> R {
-        let old_mode = Self::get();
-        let mut new_mode = old_mode;
-        let first_avail_slot = new_mode.highlight_regions.iter_mut()
-            .filter(|s| s.is_none())
-            .next()
-            .unwrap_or_else(|| {
-                panic!(
-                    "can only highlight {} placeholders at a time",
-                    old_mode.highlight_regions.len(),
-                )
-            });
-        *first_avail_slot = Some((*region, number));
-        Self::set(old_mode, new_mode, op)
-    }
-
-    /// Convenience wrapper for `highlighting_region`.
-    pub fn highlighting_region_vid<R>(
-        vid: ty::RegionVid,
-        number: usize,
-        op: impl FnOnce() -> R,
-    ) -> R {
-        Self::highlighting_region(&ty::ReVar(vid), number, op)
-    }
-
-    /// Returns `true` if any placeholders are highlighted, and `false` otherwise.
-    fn any_region_vids_highlighted(&self) -> bool {
-        Self::get()
-            .highlight_regions
-            .iter()
-            .any(|h| match h {
-                Some((ty::ReVar(_), _)) => true,
-                _ => false,
-            })
-    }
-
-    /// Returns `Some(n)` with the number to use for the given region, if any.
-    fn region_highlighted(&self, region: ty::Region<'_>) -> Option<usize> {
-        Self::get()
-            .highlight_regions
-            .iter()
-            .filter_map(|h| match h {
-                Some((r, n)) if r == region => Some(*n),
-                _ => None,
-            })
-            .next()
-    }
-
-    /// During the execution of `op`, highlight the given bound
-    /// region. We can only highlight one bound region at a time. See
-    /// the field `highlight_bound_region` for more detailed notes.
-    pub fn highlighting_bound_region<R>(
-        br: ty::BoundRegion,
-        number: usize,
-        op: impl FnOnce() -> R,
-    ) -> R {
-        let old_mode = Self::get();
-        assert!(old_mode.highlight_bound_region.is_none());
-        Self::set(
-            old_mode,
-            Self {
-                highlight_bound_region: Some((br, number)),
-                ..old_mode
-            },
-            op,
-        )
-    }
-
-    /// Returns `true` if any placeholders are highlighted, and `false` otherwise.
-    pub fn any_placeholders_highlighted(&self) -> bool {
-        Self::get()
-            .highlight_regions
-            .iter()
-            .any(|h| match h {
-                Some((ty::RePlaceholder(_), _)) => true,
-                _ => false,
-            })
-    }
-
-    /// Returns `Some(N)` if the placeholder `p` is highlighted to print as "`'N`".
-    pub fn placeholder_highlight(&self, p: ty::PlaceholderRegion) -> Option<usize> {
-        self.region_highlighted(&ty::RePlaceholder(p))
-    }
-}
-
-macro_rules! gen_display_debug_body {
-    ( $with:path ) => {
-        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-            let mut cx = PrintContext::new();
-            $with(self, f, &mut cx)
-        }
-    };
-}
-macro_rules! gen_display_debug {
-    ( ($($x:tt)+) $target:ty, display yes ) => {
-        impl<$($x)+> fmt::Display for $target {
-            gen_display_debug_body! { Print::print_display }
-        }
-    };
-    ( () $target:ty, display yes ) => {
-        impl fmt::Display for $target {
-            gen_display_debug_body! { Print::print_display }
-        }
-    };
-    ( ($($x:tt)+) $target:ty, debug yes ) => {
-        impl<$($x)+> fmt::Debug for $target {
-            gen_display_debug_body! { Print::print_debug }
-        }
-    };
-    ( () $target:ty, debug yes ) => {
-        impl fmt::Debug for $target {
-            gen_display_debug_body! { Print::print_debug }
-        }
-    };
-    ( $generic:tt $target:ty, $t:ident no ) => {};
-}
-macro_rules! gen_print_impl {
-    ( ($($x:tt)+) $target:ty, ($self:ident, $f:ident, $cx:ident) $disp:block $dbg:block ) => {
-        impl<$($x)+> Print for $target {
-            fn print<F: fmt::Write>(&$self, $f: &mut F, $cx: &mut PrintContext) -> fmt::Result {
-                if $cx.is_debug $dbg
-                else $disp
-            }
-        }
-    };
-    ( () $target:ty, ($self:ident, $f:ident, $cx:ident) $disp:block $dbg:block ) => {
-        impl Print for $target {
-            fn print<F: fmt::Write>(&$self, $f: &mut F, $cx: &mut PrintContext) -> fmt::Result {
-                if $cx.is_debug $dbg
-                else $disp
-            }
-        }
-    };
-    ( $generic:tt $target:ty,
-      $vars:tt $gendisp:ident $disp:block $gendbg:ident $dbg:block ) => {
-        gen_print_impl! { $generic $target, $vars $disp $dbg }
-        gen_display_debug! { $generic $target, display $gendisp }
-        gen_display_debug! { $generic $target, debug $gendbg }
-    }
-}
-macro_rules! define_print {
-    ( $generic:tt $target:ty,
-      $vars:tt { display $disp:block debug $dbg:block } ) => {
-        gen_print_impl! { $generic $target, $vars yes $disp yes $dbg }
-    };
-    ( $generic:tt $target:ty,
-      $vars:tt { debug $dbg:block display $disp:block } ) => {
-        gen_print_impl! { $generic $target, $vars yes $disp yes $dbg }
-    };
-    ( $generic:tt $target:ty,
-      $vars:tt { debug $dbg:block } ) => {
-        gen_print_impl! { $generic $target, $vars no {
-            bug!(concat!("display not implemented for ", stringify!($target)));
-        } yes $dbg }
-    };
-    ( $generic:tt $target:ty,
-      ($self:ident, $f:ident, $cx:ident) { display $disp:block } ) => {
-        gen_print_impl! { $generic $target, ($self, $f, $cx) yes $disp no {
-            write!($f, "{:?}", $self)
-        } }
-    };
-}
-macro_rules! define_print_multi {
-    ( [ $($generic:tt $target:ty),* ] $vars:tt $def:tt ) => {
-        $(define_print! { $generic $target, $vars $def })*
-    };
-}
-macro_rules! print_inner {
-    ( $f:expr, $cx:expr, write ($($data:expr),+) ) => {
-        write!($f, $($data),+)
-    };
-    ( $f:expr, $cx:expr, $kind:ident ($data:expr) ) => {
-        $data.$kind($f, $cx)
-    };
-}
-macro_rules! print {
-    ( $f:expr, $cx:expr $(, $kind:ident $data:tt)+ ) => {
-        Ok(())$(.and_then(|_| print_inner!($f, $cx, $kind $data)))+
-    };
-}
-
-
-struct LateBoundRegionNameCollector(FxHashSet<InternedString>);
-impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector {
-    fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
-        match *r {
-            ty::ReLateBound(_, ty::BrNamed(_, name)) => {
-                self.0.insert(name);
-            },
-            _ => {},
-        }
-        r.super_visit_with(self)
-    }
-}
-
-#[derive(Debug)]
-pub struct PrintContext {
-    is_debug: bool,
-    is_verbose: bool,
-    identify_regions: bool,
-    used_region_names: Option<FxHashSet<InternedString>>,
-    region_index: usize,
-    binder_depth: usize,
-}
-impl PrintContext {
-    fn new() -> Self {
-        ty::tls::with_opt(|tcx| {
-            let (is_verbose, identify_regions) = tcx.map(
-                |tcx| (tcx.sess.verbose(), tcx.sess.opts.debugging_opts.identify_regions)
-            ).unwrap_or((false, false));
-            PrintContext {
-                is_debug: false,
-                is_verbose: is_verbose,
-                identify_regions: identify_regions,
-                used_region_names: None,
-                region_index: 0,
-                binder_depth: 0,
-            }
-        })
-    }
-    fn prepare_late_bound_region_info<'tcx, T>(&mut self, value: &ty::Binder<T>)
-    where T: TypeFoldable<'tcx>
-    {
-        let mut collector = LateBoundRegionNameCollector(Default::default());
-        value.visit_with(&mut collector);
-        self.used_region_names = Some(collector.0);
-        self.region_index = 0;
-    }
-}
-
-pub trait Print {
-    fn print<F: fmt::Write>(&self, f: &mut F, cx: &mut PrintContext) -> fmt::Result;
-    fn print_to_string(&self, cx: &mut PrintContext) -> String {
-        let mut result = String::new();
-        let _ = self.print(&mut result, cx);
-        result
-    }
-    fn print_display<F: fmt::Write>(&self, f: &mut F, cx: &mut PrintContext) -> fmt::Result {
-        let old_debug = cx.is_debug;
-        cx.is_debug = false;
-        let result = self.print(f, cx);
-        cx.is_debug = old_debug;
-        result
-    }
-    fn print_display_to_string(&self, cx: &mut PrintContext) -> String {
-        let mut result = String::new();
-        let _ = self.print_display(&mut result, cx);
-        result
-    }
-    fn print_debug<F: fmt::Write>(&self, f: &mut F, cx: &mut PrintContext) -> fmt::Result {
-        let old_debug = cx.is_debug;
-        cx.is_debug = true;
-        let result = self.print(f, cx);
-        cx.is_debug = old_debug;
-        result
-    }
-    fn print_debug_to_string(&self, cx: &mut PrintContext) -> String {
-        let mut result = String::new();
-        let _ = self.print_debug(&mut result, cx);
-        result
-    }
-}
-
-impl PrintContext {
-    fn fn_sig<F: fmt::Write>(&mut self,
-                             f: &mut F,
-                             inputs: &[Ty<'_>],
-                             c_variadic: bool,
-                             output: Ty<'_>)
-                             -> fmt::Result {
-        write!(f, "(")?;
-        let mut inputs = inputs.iter();
-        if let Some(&ty) = inputs.next() {
-            print!(f, self, print_display(ty))?;
-            for &ty in inputs {
-                print!(f, self, write(", "), print_display(ty))?;
-            }
-            if c_variadic {
-                write!(f, ", ...")?;
-            }
-        }
-        write!(f, ")")?;
-        if !output.is_unit() {
-            print!(f, self, write(" -> "), print_display(output))?;
-        }
-
-        Ok(())
-    }
-
-    fn parameterized<F: fmt::Write>(&mut self,
-                                    f: &mut F,
-                                    substs: SubstsRef<'_>,
-                                    did: DefId,
-                                    projections: &[ty::ProjectionPredicate<'_>])
-                                    -> fmt::Result {
-        let key = ty::tls::with(|tcx| tcx.def_key(did));
-
-        let verbose = self.is_verbose;
-        let mut num_supplied_defaults = 0;
-        let mut has_self = false;
-        let mut own_counts: GenericParamCount = Default::default();
-        let mut is_value_path = false;
-        let mut item_name = Some(key.disambiguated_data.data.as_interned_str());
-        let fn_trait_kind = ty::tls::with(|tcx| {
-            // Unfortunately, some kinds of items (e.g., closures) don't have
-            // generics. So walk back up the find the closest parent that DOES
-            // have them.
-            let mut item_def_id = did;
-            loop {
-                let key = tcx.def_key(item_def_id);
-                match key.disambiguated_data.data {
-                    DefPathData::AssocTypeInTrait(_) |
-                    DefPathData::AssocTypeInImpl(_) |
-                    DefPathData::AssocExistentialInImpl(_) |
-                    DefPathData::Trait(_) |
-                    DefPathData::TraitAlias(_) |
-                    DefPathData::Impl |
-                    DefPathData::TypeNs(_) => {
-                        break;
-                    }
-                    DefPathData::ValueNs(_) |
-                    DefPathData::EnumVariant(_) => {
-                        is_value_path = true;
-                        break;
-                    }
-                    DefPathData::CrateRoot |
-                    DefPathData::Misc |
-                    DefPathData::Module(_) |
-                    DefPathData::MacroDef(_) |
-                    DefPathData::ClosureExpr |
-                    DefPathData::TypeParam(_) |
-                    DefPathData::LifetimeParam(_) |
-                    DefPathData::ConstParam(_) |
-                    DefPathData::Field(_) |
-                    DefPathData::StructCtor |
-                    DefPathData::AnonConst |
-                    DefPathData::ImplTrait |
-                    DefPathData::GlobalMetaData(_) => {
-                        // if we're making a symbol for something, there ought
-                        // to be a value or type-def or something in there
-                        // *somewhere*
-                        item_def_id.index = key.parent.unwrap_or_else(|| {
-                            bug!("finding type for {:?}, encountered def-id {:?} with no \
-                                 parent", did, item_def_id);
-                        });
-                    }
-                }
-            }
-            let mut generics = tcx.generics_of(item_def_id);
-            let child_own_counts = generics.own_counts();
-            let mut path_def_id = did;
-            has_self = generics.has_self;
-
-            let mut child_types = 0;
-            if let Some(def_id) = generics.parent {
-                // Methods.
-                assert!(is_value_path);
-                child_types = child_own_counts.types;
-                generics = tcx.generics_of(def_id);
-                own_counts = generics.own_counts();
-
-                if has_self {
-                    print!(f, self, write("<"), print_display(substs.type_at(0)), write(" as "))?;
-                }
-
-                path_def_id = def_id;
-            } else {
-                item_name = None;
-
-                if is_value_path {
-                    // Functions.
-                    assert_eq!(has_self, false);
-                } else {
-                    // Types and traits.
-                    own_counts = child_own_counts;
-                }
-            }
-
-            if !verbose {
-                let mut type_params =
-                    generics.params.iter().rev().filter_map(|param| match param.kind {
-                        GenericParamDefKind::Lifetime => None,
-                        GenericParamDefKind::Type { has_default, .. } => {
-                            Some((param.def_id, has_default))
-                        }
-                        GenericParamDefKind::Const => None, // FIXME(const_generics:defaults)
-                    }).peekable();
-                let has_default = {
-                    let has_default = type_params.peek().map(|(_, has_default)| has_default);
-                    *has_default.unwrap_or(&false)
-                };
-                if has_default {
-                    if let Some(substs) = tcx.lift(&substs) {
-                        let types = substs.types().rev().skip(child_types);
-                        for ((def_id, has_default), actual) in type_params.zip(types) {
-                            if !has_default {
-                                break;
-                            }
-                            if tcx.type_of(def_id).subst(tcx, substs) != actual {
-                                break;
-                            }
-                            num_supplied_defaults += 1;
-                        }
-                    }
-                }
-            }
-
-            print!(f, self, write("{}", tcx.item_path_str(path_def_id)))?;
-            Ok(tcx.lang_items().fn_trait_kind(path_def_id))
-        })?;
-
-        if !verbose && fn_trait_kind.is_some() && projections.len() == 1 {
-            let projection_ty = projections[0].ty;
-            if let Tuple(ref args) = substs.type_at(1).sty {
-                return self.fn_sig(f, args, false, projection_ty);
-            }
-        }
-
-        let empty = Cell::new(true);
-        let start_or_continue = |f: &mut F, start: &str, cont: &str| {
-            if empty.get() {
-                empty.set(false);
-                write!(f, "{}", start)
-            } else {
-                write!(f, "{}", cont)
-            }
-        };
-
-        let print_regions = |f: &mut F, start: &str, skip, count| {
-            // Don't print any regions if they're all erased.
-            let regions = || substs.regions().skip(skip).take(count);
-            if regions().all(|r: ty::Region<'_>| *r == ty::ReErased) {
-                return Ok(());
-            }
-
-            for region in regions() {
-                let region: ty::Region<'_> = region;
-                start_or_continue(f, start, ", ")?;
-                if verbose {
-                    write!(f, "{:?}", region)?;
-                } else {
-                    let s = region.to_string();
-                    if s.is_empty() {
-                        // This happens when the value of the region
-                        // parameter is not easily serialized. This may be
-                        // because the user omitted it in the first place,
-                        // or because it refers to some block in the code,
-                        // etc. I'm not sure how best to serialize this.
-                        write!(f, "'_")?;
-                    } else {
-                        write!(f, "{}", s)?;
-                    }
-                }
-            }
-
-            Ok(())
-        };
-
-        print_regions(f, "<", 0, own_counts.lifetimes)?;
-
-        let tps = substs.types()
-                        .take(own_counts.types - num_supplied_defaults)
-                        .skip(has_self as usize);
-
-        for ty in tps {
-            start_or_continue(f, "<", ", ")?;
-            ty.print_display(f, self)?;
-        }
-
-        for projection in projections {
-            start_or_continue(f, "<", ", ")?;
-            ty::tls::with(|tcx|
-                print!(f, self,
-                       write("{}=",
-                             tcx.associated_item(projection.projection_ty.item_def_id).ident),
-                       print_display(projection.ty))
-            )?;
-        }
-
-        // FIXME(const_generics::defaults)
-        let consts = substs.consts();
-
-        for ct in consts {
-            start_or_continue(f, "<", ", ")?;
-            ct.print_display(f, self)?;
-        }
-
-        start_or_continue(f, "", ">")?;
-
-        // For values, also print their name and type parameters.
-        if is_value_path {
-            empty.set(true);
-
-            if has_self {
-                write!(f, ">")?;
-            }
-
-            if let Some(item_name) = item_name {
-                write!(f, "::{}", item_name)?;
-            }
-
-            print_regions(f, "::<", own_counts.lifetimes, usize::MAX)?;
-
-            // FIXME: consider being smart with defaults here too
-            for ty in substs.types().skip(own_counts.types) {
-                start_or_continue(f, "::<", ", ")?;
-                ty.print_display(f, self)?;
-            }
-
-            start_or_continue(f, "", ">")?;
-        }
-
-        Ok(())
-    }
-
-    fn in_binder<'a, 'gcx, 'tcx, T, U, F>(&mut self,
-                                          f: &mut F,
-                                          tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                                          original: &ty::Binder<T>,
-                                          lifted: Option<ty::Binder<U>>) -> fmt::Result
-        where T: Print, U: Print + TypeFoldable<'tcx>, F: fmt::Write
-    {
-        fn name_by_region_index(index: usize) -> InternedString {
-            match index {
-                0 => Symbol::intern("'r"),
-                1 => Symbol::intern("'s"),
-                i => Symbol::intern(&format!("'t{}", i-2)),
-            }.as_interned_str()
-        }
-
-        // Replace any anonymous late-bound regions with named
-        // variants, using gensym'd identifiers, so that we can
-        // clearly differentiate between named and unnamed regions in
-        // the output. We'll probably want to tweak this over time to
-        // decide just how much information to give.
-        let value = if let Some(v) = lifted {
-            v
-        } else {
-            return original.skip_binder().print_display(f, self);
-        };
-
-        if self.binder_depth == 0 {
-            self.prepare_late_bound_region_info(&value);
-        }
-
-        let mut empty = true;
-        let mut start_or_continue = |f: &mut F, start: &str, cont: &str| {
-            if empty {
-                empty = false;
-                write!(f, "{}", start)
-            } else {
-                write!(f, "{}", cont)
-            }
-        };
-
-        let old_region_index = self.region_index;
-        let mut region_index = old_region_index;
-        let new_value = tcx.replace_late_bound_regions(&value, |br| {
-            let _ = start_or_continue(f, "for<", ", ");
-            let br = match br {
-                ty::BrNamed(_, name) => {
-                    let _ = write!(f, "{}", name);
-                    br
-                }
-                ty::BrAnon(_) |
-                ty::BrFresh(_) |
-                ty::BrEnv => {
-                    let name = loop {
-                        let name = name_by_region_index(region_index);
-                        region_index += 1;
-                        if !self.is_name_used(&name) {
-                            break name;
-                        }
-                    };
-                    let _ = write!(f, "{}", name);
-                    ty::BrNamed(tcx.hir().local_def_id(CRATE_NODE_ID), name)
-                }
-            };
-            tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br))
-        }).0;
-        start_or_continue(f, "", "> ")?;
-
-        // Push current state to gcx, and restore after writing new_value.
-        self.binder_depth += 1;
-        self.region_index = region_index;
-        let result = new_value.print_display(f, self);
-        self.region_index = old_region_index;
-        self.binder_depth -= 1;
-        result
-    }
-
-    fn is_name_used(&self, name: &InternedString) -> bool {
-        match self.used_region_names {
-            Some(ref names) => names.contains(name),
-            None => false,
-        }
-    }
-}
-
-pub fn verbose() -> bool {
-    ty::tls::with(|tcx| tcx.sess.verbose())
-}
-
-pub fn identify_regions() -> bool {
-    ty::tls::with(|tcx| tcx.sess.opts.debugging_opts.identify_regions)
-}
-
-pub fn parameterized<F: fmt::Write>(f: &mut F,
-                                    substs: SubstsRef<'_>,
-                                    did: DefId,
-                                    projections: &[ty::ProjectionPredicate<'_>])
-                                    -> fmt::Result {
-    PrintContext::new().parameterized(f, substs, did, projections)
-}
-
-impl<'a, T: Print> Print for &'a T {
-    fn print<F: fmt::Write>(&self, f: &mut F, cx: &mut PrintContext) -> fmt::Result {
-        (*self).print(f, cx)
-    }
-}
-
-define_print! {
-    ('tcx) &'tcx ty::List<ty::ExistentialPredicate<'tcx>>, (self, f, cx) {
-        display {
-            // Generate the main trait ref, including associated types.
-            ty::tls::with(|tcx| {
-                // Use a type that can't appear in defaults of type parameters.
-                let dummy_self = tcx.mk_infer(ty::FreshTy(0));
-                let mut first = true;
-
-                if let Some(principal) = self.principal() {
-                    let principal = tcx
-                        .lift(&principal)
-                        .expect("could not lift TraitRef for printing")
-                        .with_self_ty(tcx, dummy_self);
-                    let projections = self.projection_bounds().map(|p| {
-                        tcx.lift(&p)
-                            .expect("could not lift projection for printing")
-                            .with_self_ty(tcx, dummy_self)
-                    }).collect::<Vec<_>>();
-                    cx.parameterized(f, principal.substs, principal.def_id, &projections)?;
-                    first = false;
-                }
-
-                // Builtin bounds.
-                let mut auto_traits: Vec<_> = self.auto_traits().map(|did| {
-                    tcx.item_path_str(did)
-                }).collect();
-
-                // The auto traits come ordered by `DefPathHash`. While
-                // `DefPathHash` is *stable* in the sense that it depends on
-                // neither the host nor the phase of the moon, it depends
-                // "pseudorandomly" on the compiler version and the target.
-                //
-                // To avoid that causing instabilities in compiletest
-                // output, sort the auto-traits alphabetically.
-                auto_traits.sort();
-
-                for auto_trait in auto_traits {
-                    if !first {
-                        write!(f, " + ")?;
-                    }
-                    first = false;
-
-                    write!(f, "{}", auto_trait)?;
-                }
-
-                Ok(())
-            })?;
-
-            Ok(())
-        }
-    }
-}
-
-impl fmt::Debug for ty::GenericParamDef {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let type_name = match self.kind {
-            ty::GenericParamDefKind::Lifetime => "Lifetime",
-            ty::GenericParamDefKind::Type { .. } => "Type",
-            ty::GenericParamDefKind::Const => "Const",
-        };
-        write!(f, "{}({}, {:?}, {})",
-               type_name,
-               self.name,
-               self.def_id,
-               self.index)
-    }
-}
-
-impl fmt::Debug for ty::TraitDef {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        ty::tls::with(|tcx| {
-            write!(f, "{}", tcx.item_path_str(self.def_id))
-        })
-    }
-}
-
-impl fmt::Debug for ty::AdtDef {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        ty::tls::with(|tcx| {
-            write!(f, "{}", tcx.item_path_str(self.did))
-        })
-    }
-}
-
-impl<'tcx> fmt::Debug for ty::ClosureUpvar<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "ClosureUpvar({:?},{:?})",
-               self.def,
-               self.ty)
-    }
-}
-
-impl fmt::Debug for ty::UpvarId {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "UpvarId({:?};`{}`;{:?})",
-               self.var_path.hir_id,
-               ty::tls::with(|tcx| tcx.hir().name_by_hir_id(self.var_path.hir_id)),
-               self.closure_expr_id)
-    }
-}
-
-impl<'tcx> fmt::Debug for ty::UpvarBorrow<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "UpvarBorrow({:?}, {:?})",
-               self.kind, self.region)
-    }
-}
-
-define_print! {
-    ('tcx) &'tcx ty::List<Ty<'tcx>>, (self, f, cx) {
-        display {
-            write!(f, "{{")?;
-            let mut tys = self.iter();
-            if let Some(&ty) = tys.next() {
-                print!(f, cx, print(ty))?;
-                for &ty in tys {
-                    print!(f, cx, write(", "), print(ty))?;
-                }
-            }
-            write!(f, "}}")
-        }
-    }
-}
-
-define_print! {
-    ('tcx) ty::TypeAndMut<'tcx>, (self, f, cx) {
-        display {
-            print!(f, cx,
-                   write("{}", if self.mutbl == hir::MutMutable { "mut " } else { "" }),
-                   print(self.ty))
-        }
-    }
-}
-
-define_print! {
-    ('tcx) ty::ExistentialTraitRef<'tcx>, (self, f, cx) {
-        display {
-            cx.parameterized(f, self.substs, self.def_id, &[])
-        }
-        debug {
-            ty::tls::with(|tcx| {
-                let dummy_self = tcx.mk_infer(ty::FreshTy(0));
-
-                let trait_ref = *tcx.lift(&ty::Binder::bind(*self))
-                                   .expect("could not lift TraitRef for printing")
-                                   .with_self_ty(tcx, dummy_self).skip_binder();
-                cx.parameterized(f, trait_ref.substs, trait_ref.def_id, &[])
-            })
-        }
-    }
-}
-
-define_print! {
-    ('tcx) ty::adjustment::Adjustment<'tcx>, (self, f, cx) {
-        debug {
-            print!(f, cx, write("{:?} -> ", self.kind), print(self.target))
-        }
-    }
-}
-
-define_print! {
-    () ty::BoundRegion, (self, f, cx) {
-        display {
-            if cx.is_verbose {
-                return self.print_debug(f, cx);
-            }
-
-            if let Some((region, counter)) = RegionHighlightMode::get().highlight_bound_region {
-                if *self == region {
-                    return match *self {
-                        BrNamed(_, name) => write!(f, "{}", name),
-                        BrAnon(_) | BrFresh(_) | BrEnv => write!(f, "'{}", counter)
-                    };
-                }
-            }
-
-            match *self {
-                BrNamed(_, name) => write!(f, "{}", name),
-                BrAnon(_) | BrFresh(_) | BrEnv => Ok(())
-            }
-        }
-        debug {
-            return match *self {
-                BrAnon(n) => write!(f, "BrAnon({:?})", n),
-                BrFresh(n) => write!(f, "BrFresh({:?})", n),
-                BrNamed(did, name) => {
-                    write!(f, "BrNamed({:?}:{:?}, {})",
-                           did.krate, did.index, name)
-                }
-                BrEnv => write!(f, "BrEnv"),
-            };
-        }
-    }
-}
-
-define_print! {
-    () ty::PlaceholderRegion, (self, f, cx) {
-        display {
-            if cx.is_verbose {
-                return self.print_debug(f, cx);
-            }
-
-            let highlight = RegionHighlightMode::get();
-            if let Some(counter) = highlight.placeholder_highlight(*self) {
-                write!(f, "'{}", counter)
-            } else if highlight.any_placeholders_highlighted() {
-                write!(f, "'_")
-            } else {
-                write!(f, "{}", self.name)
-            }
-        }
-    }
-}
-
-define_print! {
-    () ty::RegionKind, (self, f, cx) {
-        display {
-            if cx.is_verbose {
-                return self.print_debug(f, cx);
-            }
-
-            // Watch out for region highlights.
-            if let Some(n) = RegionHighlightMode::get().region_highlighted(self) {
-                return write!(f, "'{:?}", n);
-            }
-
-            // These printouts are concise.  They do not contain all the information
-            // the user might want to diagnose an error, but there is basically no way
-            // to fit that into a short string.  Hence the recommendation to use
-            // `explain_region()` or `note_and_explain_region()`.
-            match *self {
-                ty::ReEarlyBound(ref data) => {
-                    write!(f, "{}", data.name)
-                }
-                ty::ReLateBound(_, br) |
-                ty::ReFree(ty::FreeRegion { bound_region: br, .. }) => {
-                    write!(f, "{}", br)
-                }
-                ty::RePlaceholder(p) => {
-                    write!(f, "{}", p)
-                }
-                ty::ReScope(scope) if cx.identify_regions => {
-                    match scope.data {
-                        region::ScopeData::Node =>
-                            write!(f, "'{}s", scope.item_local_id().as_usize()),
-                        region::ScopeData::CallSite =>
-                            write!(f, "'{}cs", scope.item_local_id().as_usize()),
-                        region::ScopeData::Arguments =>
-                            write!(f, "'{}as", scope.item_local_id().as_usize()),
-                        region::ScopeData::Destruction =>
-                            write!(f, "'{}ds", scope.item_local_id().as_usize()),
-                        region::ScopeData::Remainder(first_statement_index) => write!(
-                            f,
-                            "'{}_{}rs",
-                            scope.item_local_id().as_usize(),
-                            first_statement_index.index()
-                        ),
-                    }
-                }
-                ty::ReVar(region_vid) => {
-                    if RegionHighlightMode::get().any_region_vids_highlighted() {
-                        write!(f, "{:?}", region_vid)
-                    } else if cx.identify_regions {
-                        write!(f, "'{}rv", region_vid.index())
-                    } else {
-                        Ok(())
-                    }
-                }
-                ty::ReScope(_) |
-                ty::ReErased => Ok(()),
-                ty::ReStatic => write!(f, "'static"),
-                ty::ReEmpty => write!(f, "'<empty>"),
-
-                // The user should never encounter these in unsubstituted form.
-                ty::ReClosureBound(vid) => write!(f, "{:?}", vid),
-            }
-        }
-        debug {
-            match *self {
-                ty::ReEarlyBound(ref data) => {
-                    write!(f, "ReEarlyBound({}, {})",
-                           data.index,
-                           data.name)
-                }
-
-                ty::ReClosureBound(ref vid) => {
-                    write!(f, "ReClosureBound({:?})",
-                           vid)
-                }
-
-                ty::ReLateBound(binder_id, ref bound_region) => {
-                    write!(f, "ReLateBound({:?}, {:?})",
-                           binder_id,
-                           bound_region)
-                }
-
-                ty::ReFree(ref fr) => write!(f, "{:?}", fr),
-
-                ty::ReScope(id) => {
-                    write!(f, "ReScope({:?})", id)
-                }
-
-                ty::ReStatic => write!(f, "ReStatic"),
-
-                ty::ReVar(ref vid) => {
-                    write!(f, "{:?}", vid)
-                }
-
-                ty::RePlaceholder(placeholder) => {
-                    write!(f, "RePlaceholder({:?})", placeholder)
-                }
-
-                ty::ReEmpty => write!(f, "ReEmpty"),
-
-                ty::ReErased => write!(f, "ReErased")
-            }
-        }
-    }
-}
-
-define_print! {
-    () ty::FreeRegion, (self, f, cx) {
-        debug {
-            write!(f, "ReFree({:?}, {:?})", self.scope, self.bound_region)
-        }
-    }
-}
-
-define_print! {
-    () ty::Variance, (self, f, cx) {
-        debug {
-            f.write_str(match *self {
-                ty::Covariant => "+",
-                ty::Contravariant => "-",
-                ty::Invariant => "o",
-                ty::Bivariant => "*",
-            })
-        }
-    }
-}
-
-define_print! {
-    ('tcx) ty::GenericPredicates<'tcx>, (self, f, cx) {
-        debug {
-            write!(f, "GenericPredicates({:?})", self.predicates)
-        }
-    }
-}
-
-define_print! {
-    ('tcx) ty::InstantiatedPredicates<'tcx>, (self, f, cx) {
-        debug {
-            write!(f, "InstantiatedPredicates({:?})", self.predicates)
-        }
-    }
-}
-
-define_print! {
-    ('tcx) ty::FnSig<'tcx>, (self, f, cx) {
-        display {
-            if self.unsafety == hir::Unsafety::Unsafe {
-                write!(f, "unsafe ")?;
-            }
-
-            if self.abi != Abi::Rust {
-                write!(f, "extern {} ", self.abi)?;
-            }
-
-            write!(f, "fn")?;
-            cx.fn_sig(f, self.inputs(), self.c_variadic, self.output())
-        }
-        debug {
-            write!(f, "({:?}; c_variadic: {})->{:?}", self.inputs(), self.c_variadic, self.output())
-        }
-    }
-}
-
-impl fmt::Debug for ty::TyVid {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "_#{}t", self.index)
-    }
-}
-
-impl<'tcx> fmt::Debug for ty::ConstVid<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "_#{}f", self.index)
-    }
-}
-
-impl fmt::Debug for ty::IntVid {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "_#{}i", self.index)
-    }
-}
-
-impl fmt::Debug for ty::FloatVid {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "_#{}f", self.index)
-    }
-}
-
-impl fmt::Debug for ty::RegionVid {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        if let Some(counter) = RegionHighlightMode::get().region_highlighted(&ty::ReVar(*self)) {
-            return write!(f, "'{:?}", counter);
-        } else if RegionHighlightMode::get().any_region_vids_highlighted() {
-            return write!(f, "'_");
-        }
-
-        write!(f, "'_#{}r", self.index())
-    }
-}
-
-define_print! {
-    () ty::InferTy, (self, f, cx) {
-        display {
-            if cx.is_verbose {
-                print!(f, cx, print_debug(self))
-            } else {
-                match *self {
-                    ty::TyVar(_) => write!(f, "_"),
-                    ty::IntVar(_) => write!(f, "{}", "{integer}"),
-                    ty::FloatVar(_) => write!(f, "{}", "{float}"),
-                    ty::FreshTy(v) => write!(f, "FreshTy({})", v),
-                    ty::FreshIntTy(v) => write!(f, "FreshIntTy({})", v),
-                    ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({})", v)
-                }
-            }
-        }
-        debug {
-            match *self {
-                ty::TyVar(ref v) => write!(f, "{:?}", v),
-                ty::IntVar(ref v) => write!(f, "{:?}", v),
-                ty::FloatVar(ref v) => write!(f, "{:?}", v),
-                ty::FreshTy(v) => write!(f, "FreshTy({:?})", v),
-                ty::FreshIntTy(v) => write!(f, "FreshIntTy({:?})", v),
-                ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({:?})", v)
-            }
-        }
-    }
-}
-
-impl fmt::Debug for ty::IntVarValue {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match *self {
-            ty::IntType(ref v) => v.fmt(f),
-            ty::UintType(ref v) => v.fmt(f),
-        }
-    }
-}
-
-impl fmt::Debug for ty::FloatVarValue {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.0.fmt(f)
-    }
-}
-
-// The generic impl doesn't work yet because projections are not
-// normalized under HRTB.
-/*impl<T> fmt::Display for ty::Binder<T>
-    where T: fmt::Display + for<'a> ty::Lift<'a>,
-          for<'a> <T as ty::Lift<'a>>::Lifted: fmt::Display + TypeFoldable<'a>
-{
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
-    }
-}*/
-
-define_print_multi! {
-    [
-    ('tcx) ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
-    ('tcx) ty::Binder<ty::TraitRef<'tcx>>,
-    ('tcx) ty::Binder<ty::FnSig<'tcx>>,
-    ('tcx) ty::Binder<ty::TraitPredicate<'tcx>>,
-    ('tcx) ty::Binder<ty::SubtypePredicate<'tcx>>,
-    ('tcx) ty::Binder<ty::ProjectionPredicate<'tcx>>,
-    ('tcx) ty::Binder<ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>,
-    ('tcx) ty::Binder<ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>>
-    ]
-    (self, f, cx) {
-        display {
-            ty::tls::with(|tcx| cx.in_binder(f, tcx, self, tcx.lift(self)))
-        }
-    }
-}
-
-define_print! {
-    ('tcx) ty::TraitRef<'tcx>, (self, f, cx) {
-        display {
-            cx.parameterized(f, self.substs, self.def_id, &[])
-        }
-        debug {
-            // when printing out the debug representation, we don't need
-            // to enumerate the `for<...>` etc because the debruijn index
-            // tells you everything you need to know.
-            print!(f, cx,
-                   write("<"),
-                   print(self.self_ty()),
-                   write(" as "))?;
-            cx.parameterized(f, self.substs, self.def_id, &[])?;
-            write!(f, ">")
-        }
-    }
-}
-
-define_print! {
-    ('tcx) ty::TyKind<'tcx>, (self, f, cx) {
-        display {
-            match *self {
-                Bool => write!(f, "bool"),
-                Char => write!(f, "char"),
-                Int(t) => write!(f, "{}", t.ty_to_string()),
-                Uint(t) => write!(f, "{}", t.ty_to_string()),
-                Float(t) => write!(f, "{}", t.ty_to_string()),
-                RawPtr(ref tm) => {
-                    write!(f, "*{} ", match tm.mutbl {
-                        hir::MutMutable => "mut",
-                        hir::MutImmutable => "const",
-                    })?;
-                    tm.ty.print(f, cx)
-                }
-                Ref(r, ty, mutbl) => {
-                    write!(f, "&")?;
-                    let s = r.print_to_string(cx);
-                    if s != "'_" {
-                        write!(f, "{}", s)?;
-                        if !s.is_empty() {
-                            write!(f, " ")?;
-                        }
-                    }
-                    ty::TypeAndMut { ty, mutbl }.print(f, cx)
-                }
-                Never => write!(f, "!"),
-                Tuple(ref tys) => {
-                    write!(f, "(")?;
-                    let mut tys = tys.iter();
-                    if let Some(&ty) = tys.next() {
-                        print!(f, cx, print(ty), write(","))?;
-                        if let Some(&ty) = tys.next() {
-                            print!(f, cx, write(" "), print(ty))?;
-                            for &ty in tys {
-                                print!(f, cx, write(", "), print(ty))?;
-                            }
-                        }
-                    }
-                    write!(f, ")")
-                }
-                FnDef(def_id, substs) => {
-                    ty::tls::with(|tcx| {
-                        let mut sig = tcx.fn_sig(def_id);
-                        if let Some(substs) = tcx.lift(&substs) {
-                            sig = sig.subst(tcx, substs);
-                        }
-                        print!(f, cx, print(sig), write(" {{"))
-                    })?;
-                    cx.parameterized(f, substs, def_id, &[])?;
-                    write!(f, "}}")
-                }
-                FnPtr(ref bare_fn) => {
-                    bare_fn.print(f, cx)
-                }
-                Infer(infer_ty) => write!(f, "{}", infer_ty),
-                Error => write!(f, "[type error]"),
-                Param(ref param_ty) => write!(f, "{}", param_ty),
-                Bound(debruijn, bound_ty) => {
-                    match bound_ty.kind {
-                        ty::BoundTyKind::Anon => {
-                            if debruijn == ty::INNERMOST {
-                                write!(f, "^{}", bound_ty.var.index())
-                            } else {
-                                write!(f, "^{}_{}", debruijn.index(), bound_ty.var.index())
-                            }
-                        }
-
-                        ty::BoundTyKind::Param(p) => write!(f, "{}", p),
-                    }
-                }
-                Adt(def, substs) => cx.parameterized(f, substs, def.did, &[]),
-                Dynamic(data, r) => {
-                    let r = r.print_to_string(cx);
-                    if !r.is_empty() {
-                        write!(f, "(")?;
-                    }
-                    write!(f, "dyn ")?;
-                    data.print(f, cx)?;
-                    if !r.is_empty() {
-                        write!(f, " + {})", r)
-                    } else {
-                        Ok(())
-                    }
-                }
-                Foreign(def_id) => parameterized(f, subst::InternalSubsts::empty(), def_id, &[]),
-                Projection(ref data) => data.print(f, cx),
-                UnnormalizedProjection(ref data) => {
-                    write!(f, "Unnormalized(")?;
-                    data.print(f, cx)?;
-                    write!(f, ")")
-                }
-                Placeholder(placeholder) => {
-                    write!(f, "Placeholder({:?})", placeholder)
-                }
-                Opaque(def_id, substs) => {
-                    if cx.is_verbose {
-                        return write!(f, "Opaque({:?}, {:?})", def_id, substs);
-                    }
-
-                    ty::tls::with(|tcx| {
-                        let def_key = tcx.def_key(def_id);
-                        if let Some(name) = def_key.disambiguated_data.data.get_opt_name() {
-                            write!(f, "{}", name)?;
-                            let mut substs = substs.iter();
-                            if let Some(first) = substs.next() {
-                                write!(f, "::<")?;
-                                write!(f, "{}", first)?;
-                                for subst in substs {
-                                    write!(f, ", {}", subst)?;
-                                }
-                                write!(f, ">")?;
-                            }
-                            return Ok(());
-                        }
-                        // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
-                        // by looking up the projections associated with the def_id.
-                        let predicates_of = tcx.predicates_of(def_id);
-                        let substs = tcx.lift(&substs).unwrap_or_else(|| {
-                            tcx.intern_substs(&[])
-                        });
-                        let bounds = predicates_of.instantiate(tcx, substs);
-
-                        let mut first = true;
-                        let mut is_sized = false;
-                        write!(f, "impl")?;
-                        for predicate in bounds.predicates {
-                            if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() {
-                                // Don't print +Sized, but rather +?Sized if absent.
-                                if Some(trait_ref.def_id()) == tcx.lang_items().sized_trait() {
-                                    is_sized = true;
-                                    continue;
-                                }
-
-                                print!(f, cx,
-                                       write("{}", if first { " " } else { "+" }),
-                                       print(trait_ref))?;
-                                first = false;
-                            }
-                        }
-                        if !is_sized {
-                            write!(f, "{}?Sized", if first { " " } else { "+" })?;
-                        } else if first {
-                            write!(f, " Sized")?;
-                        }
-                        Ok(())
-                    })
-                }
-                Str => write!(f, "str"),
-                Generator(did, substs, movability) => ty::tls::with(|tcx| {
-                    let upvar_tys = substs.upvar_tys(did, tcx);
-                    let witness = substs.witness(did, tcx);
-                    if movability == hir::GeneratorMovability::Movable {
-                        write!(f, "[generator")?;
-                    } else {
-                        write!(f, "[static generator")?;
-                    }
-
-                    if let Some(hir_id) = tcx.hir().as_local_hir_id(did) {
-                        write!(f, "@{:?}", tcx.hir().span_by_hir_id(hir_id))?;
-                        let mut sep = " ";
-                        tcx.with_freevars(hir_id, |freevars| {
-                            for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) {
-                                print!(f, cx,
-                                       write("{}{}:",
-                                             sep,
-                                             tcx.hir().name(freevar.var_id())),
-                                       print(upvar_ty))?;
-                                sep = ", ";
-                            }
-                            Ok(())
-                        })?
-                    } else {
-                        // cross-crate closure types should only be
-                        // visible in codegen bug reports, I imagine.
-                        write!(f, "@{:?}", did)?;
-                        let mut sep = " ";
-                        for (index, upvar_ty) in upvar_tys.enumerate() {
-                            print!(f, cx,
-                                   write("{}{}:", sep, index),
-                                   print(upvar_ty))?;
-                            sep = ", ";
-                        }
-                    }
-
-                    print!(f, cx, write(" "), print(witness), write("]"))
-                }),
-                GeneratorWitness(types) => {
-                    ty::tls::with(|tcx| cx.in_binder(f, tcx, &types, tcx.lift(&types)))
-                }
-                Closure(did, substs) => ty::tls::with(|tcx| {
-                    let upvar_tys = substs.upvar_tys(did, tcx);
-                    write!(f, "[closure")?;
-
-                    if let Some(hir_id) = tcx.hir().as_local_hir_id(did) {
-                        if tcx.sess.opts.debugging_opts.span_free_formats {
-                            write!(f, "@{:?}", hir_id)?;
-                        } else {
-                            write!(f, "@{:?}", tcx.hir().span_by_hir_id(hir_id))?;
-                        }
-                        let mut sep = " ";
-                        tcx.with_freevars(hir_id, |freevars| {
-                            for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) {
-                                print!(f, cx,
-                                       write("{}{}:",
-                                             sep,
-                                             tcx.hir().name(freevar.var_id())),
-                                       print(upvar_ty))?;
-                                sep = ", ";
-                            }
-                            Ok(())
-                        })?
-                    } else {
-                        // cross-crate closure types should only be
-                        // visible in codegen bug reports, I imagine.
-                        write!(f, "@{:?}", did)?;
-                        let mut sep = " ";
-                        for (index, upvar_ty) in upvar_tys.enumerate() {
-                            print!(f, cx,
-                                   write("{}{}:", sep, index),
-                                   print(upvar_ty))?;
-                            sep = ", ";
-                        }
-                    }
-
-                    if cx.is_verbose {
-                        write!(
-                            f,
-                            " closure_kind_ty={:?} closure_sig_ty={:?}",
-                            substs.closure_kind_ty(did, tcx),
-                            substs.closure_sig_ty(did, tcx),
-                        )?;
-                    }
-
-                    write!(f, "]")
-                }),
-                Array(ty, sz) => {
-                    print!(f, cx, write("["), print(ty), write("; "))?;
-                    match sz {
-                        ty::LazyConst::Unevaluated(_def_id, _substs) => {
-                            write!(f, "_")?;
-                        }
-                        ty::LazyConst::Evaluated(c) => ty::tls::with(|tcx| {
-                            match c.val {
-                                ConstValue::Infer(..) => write!(f, "_"),
-                                ConstValue::Param(ParamConst { name, .. }) =>
-                                    write!(f, "{}", name),
-                                _ => write!(f, "{}", c.unwrap_usize(tcx)),
-                            }
-                        })?,
-                    }
-                    write!(f, "]")
-                }
-                Slice(ty) => {
-                    print!(f, cx, write("["), print(ty), write("]"))
-                }
-            }
-        }
-    }
-}
-
-define_print! {
-    ('tcx) ty::TyS<'tcx>, (self, f, cx) {
-        display {
-            self.sty.print(f, cx)
-        }
-        debug {
-            self.sty.print_display(f, cx)
-        }
-    }
-}
-
-define_print! {
-    ('tcx) ConstValue<'tcx>, (self, f, cx) {
-        display {
-            match self {
-                ConstValue::Infer(..) => write!(f, "_"),
-                ConstValue::Param(ParamConst { name, .. }) => write!(f, "{}", name),
-                _ => write!(f, "{:?}", self),
-            }
-        }
-    }
-}
-
-define_print! {
-    ('tcx) ty::Const<'tcx>, (self, f, cx) {
-        display {
-            write!(f, "{} : {}", self.val, self.ty)
-        }
-    }
-}
-
-define_print! {
-    ('tcx) ty::LazyConst<'tcx>, (self, f, cx) {
-        display {
-            match self {
-                ty::LazyConst::Unevaluated(..) => write!(f, "_ : _"),
-                ty::LazyConst::Evaluated(c) => write!(f, "{}", c),
-            }
-        }
-    }
-}
-
-define_print! {
-    () ty::ParamTy, (self, f, cx) {
-        display {
-            write!(f, "{}", self.name)
-        }
-        debug {
-            write!(f, "{}/#{}", self.name, self.idx)
-        }
-    }
-}
-
-define_print! {
-    () ty::ParamConst, (self, f, cx) {
-        display {
-            write!(f, "{}", self.name)
-        }
-        debug {
-            write!(f, "{}/#{}", self.name, self.index)
-        }
-    }
-}
-
-define_print! {
-    ('tcx, T: Print + fmt::Debug, U: Print + fmt::Debug) ty::OutlivesPredicate<T, U>,
-    (self, f, cx) {
-        display {
-            print!(f, cx, print(self.0), write(" : "), print(self.1))
-        }
-    }
-}
-
-define_print! {
-    ('tcx) ty::SubtypePredicate<'tcx>, (self, f, cx) {
-        display {
-            print!(f, cx, print(self.a), write(" <: "), print(self.b))
-        }
-    }
-}
-
-define_print! {
-    ('tcx) ty::TraitPredicate<'tcx>, (self, f, cx) {
-        debug {
-            write!(f, "TraitPredicate({:?})",
-                   self.trait_ref)
-        }
-        display {
-            print!(f, cx, print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref))
-        }
-    }
-}
-
-define_print! {
-    ('tcx) ty::ProjectionPredicate<'tcx>, (self, f, cx) {
-        debug {
-            print!(f, cx,
-                   write("ProjectionPredicate("),
-                   print(self.projection_ty),
-                   write(", "),
-                   print(self.ty),
-                   write(")"))
-        }
-        display {
-            print!(f, cx, print(self.projection_ty), write(" == "), print(self.ty))
-        }
-    }
-}
-
-define_print! {
-    ('tcx) ty::ProjectionTy<'tcx>, (self, f, cx) {
-        display {
-            // FIXME(tschottdorf): use something like
-            //   parameterized(f, self.substs, self.item_def_id, &[])
-            // (which currently ICEs).
-            let (trait_ref, item_name) = ty::tls::with(|tcx|
-                (self.trait_ref(tcx), tcx.associated_item(self.item_def_id).ident)
-            );
-            print!(f, cx, print_debug(trait_ref), write("::{}", item_name))
-        }
-    }
-}
-
-define_print! {
-    () ty::ClosureKind, (self, f, cx) {
-        display {
-            match *self {
-                ty::ClosureKind::Fn => write!(f, "Fn"),
-                ty::ClosureKind::FnMut => write!(f, "FnMut"),
-                ty::ClosureKind::FnOnce => write!(f, "FnOnce"),
-            }
-        }
-    }
-}
-
-define_print! {
-    ('tcx) ty::Predicate<'tcx>, (self, f, cx) {
-        display {
-            match *self {
-                ty::Predicate::Trait(ref data) => data.print(f, cx),
-                ty::Predicate::Subtype(ref predicate) => predicate.print(f, cx),
-                ty::Predicate::RegionOutlives(ref predicate) => predicate.print(f, cx),
-                ty::Predicate::TypeOutlives(ref predicate) => predicate.print(f, cx),
-                ty::Predicate::Projection(ref predicate) => predicate.print(f, cx),
-                ty::Predicate::WellFormed(ty) => print!(f, cx, print(ty), write(" well-formed")),
-                ty::Predicate::ObjectSafe(trait_def_id) =>
-                    ty::tls::with(|tcx| {
-                        write!(f, "the trait `{}` is object-safe", tcx.item_path_str(trait_def_id))
-                    }),
-                ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) =>
-                    ty::tls::with(|tcx| {
-                        write!(f, "the closure `{}` implements the trait `{}`",
-                               tcx.item_path_str(closure_def_id), kind)
-                    }),
-                ty::Predicate::ConstEvaluatable(def_id, substs) => {
-                    write!(f, "the constant `")?;
-                    cx.parameterized(f, substs, def_id, &[])?;
-                    write!(f, "` can be evaluated")
-                }
-            }
-        }
-        debug {
-            match *self {
-                ty::Predicate::Trait(ref a) => a.print(f, cx),
-                ty::Predicate::Subtype(ref pair) => pair.print(f, cx),
-                ty::Predicate::RegionOutlives(ref pair) => pair.print(f, cx),
-                ty::Predicate::TypeOutlives(ref pair) => pair.print(f, cx),
-                ty::Predicate::Projection(ref pair) => pair.print(f, cx),
-                ty::Predicate::WellFormed(ty) => ty.print(f, cx),
-                ty::Predicate::ObjectSafe(trait_def_id) => {
-                    write!(f, "ObjectSafe({:?})", trait_def_id)
-                }
-                ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
-                    write!(f, "ClosureKind({:?}, {:?}, {:?})", closure_def_id, closure_substs, kind)
-                }
-                ty::Predicate::ConstEvaluatable(def_id, substs) => {
-                    write!(f, "ConstEvaluatable({:?}, {:?})", def_id, substs)
-                }
-            }
-        }
-    }
-}
diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs
index da065f9..01bfe5d 100644
--- a/src/librustc_borrowck/borrowck/mod.rs
+++ b/src/librustc_borrowck/borrowck/mod.rs
@@ -1406,7 +1406,7 @@
                 out.push('(');
                 self.append_loan_path_to_string(&lp_base, out);
                 out.push_str(DOWNCAST_PRINTED_OPERATOR);
-                out.push_str(&self.tcx.item_path_str(variant_def_id));
+                out.push_str(&self.tcx.def_path_str(variant_def_id));
                 out.push(')');
             }
 
@@ -1443,7 +1443,7 @@
                 out.push('(');
                 self.append_autoderefd_loan_path_to_string(&lp_base, out);
                 out.push_str(DOWNCAST_PRINTED_OPERATOR);
-                out.push_str(&self.tcx.item_path_str(variant_def_id));
+                out.push_str(&self.tcx.def_path_str(variant_def_id));
                 out.push(')');
             }
 
@@ -1523,7 +1523,7 @@
 
             LpDowncast(ref lp, variant_def_id) => {
                 let variant_str = if variant_def_id.is_local() {
-                    ty::tls::with(|tcx| tcx.item_path_str(variant_def_id))
+                    ty::tls::with(|tcx| tcx.def_path_str(variant_def_id))
                 } else {
                     format!("{:?}", variant_def_id)
                 };
@@ -1558,7 +1558,7 @@
 
             LpDowncast(ref lp, variant_def_id) => {
                 let variant_str = if variant_def_id.is_local() {
-                    ty::tls::with(|tcx| tcx.item_path_str(variant_def_id))
+                    ty::tls::with(|tcx| tcx.def_path_str(variant_def_id))
                 } else {
                     format!("{:?}", variant_def_id)
                 };
diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs
index 3268af3..ceb08f9 100644
--- a/src/librustc_codegen_llvm/intrinsic.rs
+++ b/src/librustc_codegen_llvm/intrinsic.rs
@@ -513,8 +513,7 @@
 
             },
             "fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" => {
-                let sty = &arg_tys[0].sty;
-                match float_type_width(sty) {
+                match float_type_width(arg_tys[0]) {
                     Some(_width) =>
                         match name {
                             "fadd_fast" => self.fadd_fast(args[0].immediate(), args[1].immediate()),
@@ -528,7 +527,7 @@
                         span_invalid_monomorphization_error(
                             tcx.sess, span,
                             &format!("invalid monomorphization of `{}` intrinsic: \
-                                      expected basic float type, found `{}`", name, sty));
+                                      expected basic float type, found `{}`", name, arg_tys[0]));
                         return;
                     }
                 }
@@ -1473,8 +1472,8 @@
                 require!(false, "expected element type `{}` of second argument `{}` \
                                  to be a pointer to the element type `{}` of the first \
                                  argument `{}`, found `{}` != `*_ {}`",
-                         arg_tys[1].simd_type(tcx).sty, arg_tys[1], in_elem, in_ty,
-                         arg_tys[1].simd_type(tcx).sty, in_elem);
+                         arg_tys[1].simd_type(tcx), arg_tys[1], in_elem, in_ty,
+                         arg_tys[1].simd_type(tcx), in_elem);
                 unreachable!();
             }
         };
@@ -1488,7 +1487,7 @@
             _ => {
                 require!(false, "expected element type `{}` of third argument `{}` \
                                  to be a signed integer type",
-                         arg_tys[2].simd_type(tcx).sty, arg_tys[2]);
+                         arg_tys[2].simd_type(tcx), arg_tys[2]);
             }
         }
 
@@ -1573,8 +1572,8 @@
                 require!(false, "expected element type `{}` of second argument `{}` \
                                  to be a pointer to the element type `{}` of the first \
                                  argument `{}`, found `{}` != `*mut {}`",
-                         arg_tys[1].simd_type(tcx).sty, arg_tys[1], in_elem, in_ty,
-                         arg_tys[1].simd_type(tcx).sty, in_elem);
+                         arg_tys[1].simd_type(tcx), arg_tys[1], in_elem, in_ty,
+                         arg_tys[1].simd_type(tcx), in_elem);
                 unreachable!();
             }
         };
@@ -1588,7 +1587,7 @@
             _ => {
                 require!(false, "expected element type `{}` of third argument `{}` \
                                  to be a signed integer type",
-                         arg_tys[2].simd_type(tcx).sty, arg_tys[2]);
+                         arg_tys[2].simd_type(tcx), arg_tys[2]);
             }
         }
 
@@ -1904,7 +1903,7 @@
                 return_error!(
                     "expected element type `{}` of vector type `{}` \
                      to be a signed or unsigned integer type",
-                    arg_tys[0].simd_type(tcx).sty, arg_tys[0]
+                    arg_tys[0].simd_type(tcx), arg_tys[0]
                 );
             }
         };
@@ -1954,10 +1953,10 @@
     }
 }
 
-// Returns the width of a float TypeVariant
+// Returns the width of a float Ty
 // Returns None if the type is not a float
-fn float_type_width<'tcx>(sty: &ty::TyKind<'tcx>) -> Option<u64> {
-    match *sty {
+fn float_type_width(ty: Ty<'_>) -> Option<u64> {
+    match ty.sty {
         ty::Float(t) => Some(t.bit_width() as u64),
         _ => None,
     }
diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs
index 0a295c2..c75788e 100644
--- a/src/librustc_codegen_llvm/lib.rs
+++ b/src/librustc_codegen_llvm/lib.rs
@@ -15,7 +15,6 @@
 #![allow(unused_attributes)]
 #![feature(libc)]
 #![feature(nll)]
-#![feature(range_contains)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(optin_builtin_traits)]
 #![feature(concat_idents)]
diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs
index 1f4c554..e6470db 100644
--- a/src/librustc_codegen_ssa/back/linker.rs
+++ b/src/librustc_codegen_ssa/back/linker.rs
@@ -382,20 +382,19 @@
 
         if self.sess.target.target.options.is_like_osx {
             // Write a plain, newline-separated list of symbols
-            let res = (|| -> io::Result<()> {
+            let res: io::Result<()> = try {
                 let mut f = BufWriter::new(File::create(&path)?);
                 for sym in self.info.exports[&crate_type].iter() {
                     debug!("  _{}", sym);
                     writeln!(f, "_{}", sym)?;
                 }
-                Ok(())
-            })();
+            };
             if let Err(e) = res {
                 self.sess.fatal(&format!("failed to write lib.def file: {}", e));
             }
         } else {
             // Write an LD version script
-            let res = (|| -> io::Result<()> {
+            let res: io::Result<()> = try {
                 let mut f = BufWriter::new(File::create(&path)?);
                 writeln!(f, "{{\n  global:")?;
                 for sym in self.info.exports[&crate_type].iter() {
@@ -403,8 +402,7 @@
                     writeln!(f, "    {};", sym)?;
                 }
                 writeln!(f, "\n  local:\n    *;\n}};")?;
-                Ok(())
-            })();
+            };
             if let Err(e) = res {
                 self.sess.fatal(&format!("failed to write version script: {}", e));
             }
@@ -644,7 +642,7 @@
                       tmpdir: &Path,
                       crate_type: CrateType) {
         let path = tmpdir.join("lib.def");
-        let res = (|| -> io::Result<()> {
+        let res: io::Result<()> = try {
             let mut f = BufWriter::new(File::create(&path)?);
 
             // Start off with the standard module name header and then go
@@ -655,8 +653,7 @@
                 debug!("  _{}", symbol);
                 writeln!(f, "  {}", symbol)?;
             }
-            Ok(())
-        })();
+        };
         if let Err(e) = res {
             self.sess.fatal(&format!("failed to write lib.def file: {}", e));
         }
diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs
index fec4193..fe9b88c 100644
--- a/src/librustc_codegen_ssa/lib.rs
+++ b/src/librustc_codegen_ssa/lib.rs
@@ -7,6 +7,7 @@
 #![feature(libc)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(stmt_expr_attributes)]
+#![feature(try_blocks)]
 #![feature(in_band_lifetimes)]
 #![feature(nll)]
 #![allow(unused_attributes)]
diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs
index 349c913..a1d44b2 100644
--- a/src/librustc_codegen_ssa/mir/constant.rs
+++ b/src/librustc_codegen_ssa/mir/constant.rs
@@ -2,7 +2,6 @@
 use rustc_mir::const_eval::const_field;
 use rustc::mir;
 use rustc_data_structures::indexed_vec::Idx;
-use rustc::mir::interpret::GlobalId;
 use rustc::ty::{self, Ty};
 use rustc::ty::layout;
 use syntax::source_map::Span;
@@ -11,33 +10,25 @@
 use super::FunctionCx;
 
 impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
-    fn fully_evaluate(
-        &mut self,
-        bx: &Bx,
-        constant: &'tcx ty::LazyConst<'tcx>,
-    ) -> Result<ty::Const<'tcx>, ErrorHandled> {
-        match *constant {
-            ty::LazyConst::Unevaluated(def_id, ref substs) => {
-                let tcx = bx.tcx();
-                let param_env = ty::ParamEnv::reveal_all();
-                let instance = ty::Instance::resolve(tcx, param_env, def_id, substs).unwrap();
-                let cid = GlobalId {
-                    instance,
-                    promoted: None,
-                };
-                tcx.const_eval(param_env.and(cid))
-            },
-            ty::LazyConst::Evaluated(constant) => Ok(constant),
-        }
-    }
-
     pub fn eval_mir_constant(
         &mut self,
         bx: &Bx,
         constant: &mir::Constant<'tcx>,
     ) -> Result<ty::Const<'tcx>, ErrorHandled> {
-        let c = self.monomorphize(&constant.literal);
-        self.fully_evaluate(bx, c)
+        match constant.literal.val {
+            mir::interpret::ConstValue::Unevaluated(def_id, ref substs) => {
+                let substs = self.monomorphize(substs);
+                let instance = ty::Instance::resolve(
+                    bx.tcx(), ty::ParamEnv::reveal_all(), def_id, substs,
+                ).unwrap();
+                let cid = mir::interpret::GlobalId {
+                    instance,
+                    promoted: None,
+                };
+                bx.tcx().const_eval(ty::ParamEnv::reveal_all().and(cid))
+            },
+            _ => Ok(*self.monomorphize(&constant.literal)),
+        }
     }
 
     /// process constant containing SIMD shuffle indices
@@ -53,7 +44,7 @@
                 let field_ty = c.ty.builtin_index().unwrap();
                 let fields = match c.ty.sty {
                     ty::Array(_, n) => n.unwrap_usize(bx.tcx()),
-                    ref other => bug!("invalid simd shuffle type: {}", other),
+                    _ => bug!("invalid simd shuffle type: {}", c.ty),
                 };
                 let values: Vec<_> = (0..fields).map(|field| {
                     let field = const_field(
diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs
index 55a1eb0..e17a6e7 100644
--- a/src/librustc_codegen_ssa/mir/operand.rs
+++ b/src/librustc_codegen_ssa/mir/operand.rs
@@ -76,6 +76,7 @@
         }
 
         let val = match val.val {
+            ConstValue::Unevaluated(..) => bug!("unevaluated constant in `OperandRef::from_const`"),
             ConstValue::Param(_) => bug!("encountered a ConstValue::Param in codegen"),
             ConstValue::Infer(_) => bug!("encountered a ConstValue::Infer in codegen"),
             ConstValue::Scalar(x) => {
diff --git a/src/librustc_codegen_ssa/traits/type_.rs b/src/librustc_codegen_ssa/traits/type_.rs
index 7c5e615..fe00276 100644
--- a/src/librustc_codegen_ssa/traits/type_.rs
+++ b/src/librustc_codegen_ssa/traits/type_.rs
@@ -148,7 +148,7 @@
         match tail.sty {
             ty::Foreign(..) => false,
             ty::Str | ty::Slice(..) | ty::Dynamic(..) => true,
-            _ => bug!("unexpected unsized tail: {:?}", tail.sty),
+            _ => bug!("unexpected unsized tail: {:?}", tail),
         }
     }
 }
diff --git a/src/librustc_codegen_utils/Cargo.toml b/src/librustc_codegen_utils/Cargo.toml
index 5f241eb..c75208b 100644
--- a/src/librustc_codegen_utils/Cargo.toml
+++ b/src/librustc_codegen_utils/Cargo.toml
@@ -21,4 +21,3 @@
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_metadata = { path = "../librustc_metadata" }
 rustc_mir = { path = "../librustc_mir" }
-rustc_incremental = { path = "../librustc_incremental" }
diff --git a/src/librustc_codegen_utils/codegen_backend.rs b/src/librustc_codegen_utils/codegen_backend.rs
index 29bcb4f..56eaffb 100644
--- a/src/librustc_codegen_utils/codegen_backend.rs
+++ b/src/librustc_codegen_utils/codegen_backend.rs
@@ -10,27 +10,16 @@
 #![feature(box_syntax)]
 
 use std::any::Any;
-use std::io::Write;
-use std::fs;
-use std::path::Path;
-use std::sync::{mpsc, Arc};
-
-use rustc_data_structures::owning_ref::OwningRef;
-use flate2::Compression;
-use flate2::write::DeflateEncoder;
+use std::sync::mpsc;
 
 use syntax::symbol::Symbol;
-use rustc::hir::def_id::LOCAL_CRATE;
 use rustc::session::Session;
 use rustc::util::common::ErrorReported;
-use rustc::session::config::{CrateType, OutputFilenames, PrintRequest};
+use rustc::session::config::{OutputFilenames, PrintRequest};
 use rustc::ty::TyCtxt;
 use rustc::ty::query::Providers;
-use rustc::middle::cstore::EncodedMetadata;
 use rustc::middle::cstore::MetadataLoader;
 use rustc::dep_graph::DepGraph;
-use rustc_target::spec::Target;
-use crate::link::out_filename;
 
 pub use rustc_data_structures::sync::MetadataRef;
 
@@ -64,134 +53,3 @@
         outputs: &OutputFilenames,
     ) -> Result<(), ErrorReported>;
 }
-
-pub struct NoLlvmMetadataLoader;
-
-impl MetadataLoader for NoLlvmMetadataLoader {
-    fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result<MetadataRef, String> {
-        let buf = fs::read(filename).map_err(|e| format!("metadata file open err: {:?}", e))?;
-        let buf: OwningRef<Vec<u8>, [u8]> = OwningRef::new(buf);
-        Ok(rustc_erase_owner!(buf.map_owner_box()))
-    }
-
-    fn get_dylib_metadata(&self, target: &Target, filename: &Path) -> Result<MetadataRef, String> {
-        self.get_rlib_metadata(target, filename)
-    }
-}
-
-pub struct MetadataOnlyCodegenBackend(());
-pub struct OngoingCodegen {
-    metadata: EncodedMetadata,
-    metadata_version: Vec<u8>,
-    crate_name: Symbol,
-}
-
-impl MetadataOnlyCodegenBackend {
-    pub fn boxed() -> Box<dyn CodegenBackend> {
-        box MetadataOnlyCodegenBackend(())
-    }
-}
-
-impl CodegenBackend for MetadataOnlyCodegenBackend {
-    fn init(&self, sess: &Session) {
-        for cty in sess.opts.crate_types.iter() {
-            match *cty {
-                CrateType::Rlib | CrateType::Dylib | CrateType::Executable => {},
-                _ => {
-                    sess.diagnostic().warn(
-                        &format!("LLVM unsupported, so output type {} is not supported", cty)
-                    );
-                },
-            }
-        }
-    }
-
-    fn metadata_loader(&self) -> Box<dyn MetadataLoader + Sync> {
-        box NoLlvmMetadataLoader
-    }
-
-    fn provide(&self, providers: &mut Providers<'_>) {
-        crate::symbol_names::provide(providers);
-
-        providers.target_features_whitelist = |_tcx, _cnum| {
-            Default::default() // Just a dummy
-        };
-        providers.is_reachable_non_generic = |_tcx, _defid| true;
-        providers.exported_symbols = |_tcx, _crate| Arc::new(Vec::new());
-    }
-    fn provide_extern(&self, providers: &mut Providers<'_>) {
-        providers.is_reachable_non_generic = |_tcx, _defid| true;
-    }
-
-    fn codegen_crate<'a, 'tcx>(
-        &self,
-        tcx: TyCtxt<'a, 'tcx, 'tcx>,
-        _rx: mpsc::Receiver<Box<dyn Any + Send>>
-    ) -> Box<dyn Any> {
-        use rustc_mir::monomorphize::item::MonoItem;
-
-        crate::check_for_rustc_errors_attr(tcx);
-        crate::symbol_names_test::report_symbol_names(tcx);
-        rustc_incremental::assert_dep_graph(tcx);
-        rustc_incremental::assert_module_sources::assert_module_sources(tcx);
-        // FIXME: Fix this
-        // rustc::middle::dependency_format::calculate(tcx);
-        let _ = tcx.link_args(LOCAL_CRATE);
-        let _ = tcx.native_libraries(LOCAL_CRATE);
-        let (_, cgus) = tcx.collect_and_partition_mono_items(LOCAL_CRATE);
-        for (mono_item, _) in cgus.iter().flat_map(|cgu| cgu.items().iter()) {
-            if let MonoItem::Fn(inst) = mono_item {
-                let def_id = inst.def_id();
-                if def_id.is_local() {
-                    let _ = tcx.codegen_fn_attrs(def_id);
-                }
-            }
-        }
-        tcx.sess.abort_if_errors();
-
-        let metadata = tcx.encode_metadata();
-
-        box OngoingCodegen {
-            metadata,
-            metadata_version: tcx.metadata_encoding_version().to_vec(),
-            crate_name: tcx.crate_name(LOCAL_CRATE),
-        }
-    }
-
-    fn join_codegen_and_link(
-        &self,
-        ongoing_codegen: Box<dyn Any>,
-        sess: &Session,
-        _dep_graph: &DepGraph,
-        outputs: &OutputFilenames,
-    ) -> Result<(), ErrorReported> {
-        let ongoing_codegen = ongoing_codegen.downcast::<OngoingCodegen>()
-            .expect("Expected MetadataOnlyCodegenBackend's OngoingCodegen, found Box<dyn Any>");
-        for &crate_type in sess.opts.crate_types.iter() {
-            if crate_type != CrateType::Rlib &&
-               crate_type != CrateType::Dylib {
-                continue;
-            }
-            let output_name =
-                out_filename(sess, crate_type, &outputs, &ongoing_codegen.crate_name.as_str());
-            let mut compressed = ongoing_codegen.metadata_version.clone();
-            let metadata = if crate_type == CrateType::Dylib {
-                DeflateEncoder::new(&mut compressed, Compression::fast())
-                    .write_all(&ongoing_codegen.metadata.raw_data)
-                    .unwrap();
-                &compressed
-            } else {
-                &ongoing_codegen.metadata.raw_data
-            };
-            fs::write(&output_name, metadata).unwrap();
-        }
-
-        sess.abort_if_errors();
-        if !sess.opts.crate_types.contains(&CrateType::Rlib)
-            && !sess.opts.crate_types.contains(&CrateType::Dylib)
-        {
-            sess.fatal("Executables are not supported by the metadata-only backend.");
-        }
-        Ok(())
-    }
-}
diff --git a/src/librustc_codegen_utils/lib.rs b/src/librustc_codegen_utils/lib.rs
index 2b70141..1a3914e 100644
--- a/src/librustc_codegen_utils/lib.rs
+++ b/src/librustc_codegen_utils/lib.rs
@@ -4,6 +4,7 @@
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 
+#![feature(arbitrary_self_types)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(custom_attribute)]
@@ -18,7 +19,6 @@
 
 #[macro_use]
 extern crate rustc;
-#[macro_use] extern crate rustc_data_structures;
 
 use rustc::ty::TyCtxt;
 use rustc::hir::def_id::LOCAL_CRATE;
diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs
index 5de5c29..0fa9351 100644
--- a/src/librustc_codegen_utils/symbol_names.rs
+++ b/src/librustc_codegen_utils/symbol_names.rs
@@ -87,14 +87,14 @@
 //! virtually impossible. Thus, symbol hash generation exclusively relies on
 //! DefPaths which are much more robust in the face of changes to the code base.
 
-use rustc::hir::def_id::{DefId, LOCAL_CRATE};
+use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc::hir::Node;
 use rustc::hir::CodegenFnAttrFlags;
-use rustc::hir::map::definitions::DefPathData;
+use rustc::hir::map::{DefPathData, DisambiguatedDefPathData};
 use rustc::ich::NodeIdHashingMode;
-use rustc::ty::item_path::{self, ItemPathBuffer, RootMode};
+use rustc::ty::print::{PrettyPrinter, Printer, Print};
 use rustc::ty::query::Providers;
-use rustc::ty::subst::SubstsRef;
+use rustc::ty::subst::{Kind, SubstsRef, UnpackedKind};
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc::util::common::record_time;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
@@ -105,8 +105,8 @@
 
 use log::debug;
 
-use std::fmt::Write;
-use std::mem::discriminant;
+use std::fmt::{self, Write};
+use std::mem::{self, discriminant};
 
 pub fn provide(providers: &mut Providers<'_>) {
     *providers = Providers {
@@ -223,11 +223,11 @@
 }
 
 fn def_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::SymbolName {
-    let mut buffer = SymbolPathBuffer::new(tcx);
-    item_path::with_forced_absolute_paths(|| {
-        tcx.push_item_path(&mut buffer, def_id, false);
-    });
-    buffer.into_interned()
+    SymbolPrinter {
+        tcx,
+        path: SymbolPath::new(),
+        keep_within_component: false,
+    }.print_def_path(def_id, &[]).unwrap().path.into_interned()
 }
 
 fn symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance<'tcx>) -> ty::SymbolName {
@@ -319,13 +319,17 @@
 
     let hash = get_symbol_hash(tcx, def_id, instance, instance_ty, substs);
 
-    let mut buf = SymbolPathBuffer::from_interned(tcx.def_symbol_name(def_id), tcx);
+    let mut printer = SymbolPrinter {
+        tcx,
+        path: SymbolPath::from_interned(tcx.def_symbol_name(def_id)),
+        keep_within_component: false,
+    };
 
     if instance.is_vtable_shim() {
-        buf.push("{{vtable-shim}}");
+        let _ = printer.write_str("{{vtable-shim}}");
     }
 
-    buf.finish(hash)
+    printer.path.finish(hash)
 }
 
 // Follow C++ namespace-mangling style, see
@@ -342,126 +346,312 @@
 // To be able to work on all platforms and get *some* reasonable output, we
 // use C++ name-mangling.
 #[derive(Debug)]
-struct SymbolPathBuffer {
+struct SymbolPath {
     result: String,
     temp_buf: String,
-    strict_naming: bool,
 }
 
-impl SymbolPathBuffer {
-    fn new(tcx: TyCtxt<'_, '_, '_>) -> Self {
-        let mut result = SymbolPathBuffer {
+impl SymbolPath {
+    fn new() -> Self {
+        let mut result = SymbolPath {
             result: String::with_capacity(64),
             temp_buf: String::with_capacity(16),
-            strict_naming: tcx.has_strict_asm_symbol_naming(),
         };
         result.result.push_str("_ZN"); // _Z == Begin name-sequence, N == nested
         result
     }
 
-    fn from_interned(symbol: ty::SymbolName, tcx: TyCtxt<'_, '_, '_>) -> Self {
-        let mut result = SymbolPathBuffer {
+    fn from_interned(symbol: ty::SymbolName) -> Self {
+        let mut result = SymbolPath {
             result: String::with_capacity(64),
             temp_buf: String::with_capacity(16),
-            strict_naming: tcx.has_strict_asm_symbol_naming(),
         };
         result.result.push_str(&symbol.as_str());
         result
     }
 
-    fn into_interned(self) -> ty::SymbolName {
+    fn into_interned(mut self) -> ty::SymbolName {
+        self.finalize_pending_component();
         ty::SymbolName {
             name: Symbol::intern(&self.result).as_interned_str(),
         }
     }
 
+    fn finalize_pending_component(&mut self) {
+        if !self.temp_buf.is_empty() {
+            let _ = write!(self.result, "{}{}", self.temp_buf.len(), self.temp_buf);
+            self.temp_buf.clear();
+        }
+    }
+
     fn finish(mut self, hash: u64) -> String {
+        self.finalize_pending_component();
         // E = end name-sequence
         let _ = write!(self.result, "17h{:016x}E", hash);
         self.result
     }
+}
 
-    // Name sanitation. LLVM will happily accept identifiers with weird names, but
-    // gas doesn't!
-    // gas accepts the following characters in symbols: a-z, A-Z, 0-9, ., _, $
-    // NVPTX assembly has more strict naming rules than gas, so additionally, dots
-    // are replaced with '$' there.
-    fn sanitize_and_append(&mut self, s: &str) {
-        self.temp_buf.clear();
+struct SymbolPrinter<'a, 'tcx> {
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    path: SymbolPath,
+
+    // When `true`, `finalize_pending_component` isn't used.
+    // This is needed when recursing into `path_qualified`,
+    // or `path_generic_args`, as any nested paths are
+    // logically within one component.
+    keep_within_component: bool,
+}
+
+// HACK(eddyb) this relies on using the `fmt` interface to get
+// `PrettyPrinter` aka pretty printing of e.g. types in paths,
+// symbol names should have their own printing machinery.
+
+impl Printer<'tcx, 'tcx> for SymbolPrinter<'_, 'tcx> {
+    type Error = fmt::Error;
+
+    type Path = Self;
+    type Region = Self;
+    type Type = Self;
+    type DynExistential = Self;
+
+    fn tcx(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
+        self.tcx
+    }
+
+    fn print_region(
+        self,
+        _region: ty::Region<'_>,
+    ) -> Result<Self::Region, Self::Error> {
+        Ok(self)
+    }
+
+    fn print_type(
+        self,
+        ty: Ty<'tcx>,
+    ) -> Result<Self::Type, Self::Error> {
+        match ty.sty {
+            // Print all nominal types as paths (unlike `pretty_print_type`).
+            ty::FnDef(def_id, substs) |
+            ty::Opaque(def_id, substs) |
+            ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs }) |
+            ty::UnnormalizedProjection(ty::ProjectionTy { item_def_id: def_id, substs }) |
+            ty::Closure(def_id, ty::ClosureSubsts { substs }) |
+            ty::Generator(def_id, ty::GeneratorSubsts { substs }, _) => {
+                self.print_def_path(def_id, substs)
+            }
+            _ => self.pretty_print_type(ty),
+        }
+    }
+
+    fn print_dyn_existential(
+        mut self,
+        predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
+    ) -> Result<Self::DynExistential, Self::Error> {
+        let mut first = false;
+        for p in predicates {
+            if !first {
+                write!(self, "+")?;
+            }
+            first = false;
+            self = p.print(self)?;
+        }
+        Ok(self)
+    }
+
+    fn path_crate(
+        mut self,
+        cnum: CrateNum,
+    ) -> Result<Self::Path, Self::Error> {
+        self.write_str(&self.tcx.original_crate_name(cnum).as_str())?;
+        Ok(self)
+    }
+    fn path_qualified(
+        self,
+        self_ty: Ty<'tcx>,
+        trait_ref: Option<ty::TraitRef<'tcx>>,
+    ) -> Result<Self::Path, Self::Error> {
+        // Similar to `pretty_path_qualified`, but for the other
+        // types that are printed as paths (see `print_type` above).
+        match self_ty.sty {
+            ty::FnDef(..) |
+            ty::Opaque(..) |
+            ty::Projection(_) |
+            ty::UnnormalizedProjection(_) |
+            ty::Closure(..) |
+            ty::Generator(..)
+                if trait_ref.is_none() =>
+            {
+                self.print_type(self_ty)
+            }
+
+            _ => self.pretty_path_qualified(self_ty, trait_ref)
+        }
+    }
+
+    fn path_append_impl(
+        self,
+        print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+        _disambiguated_data: &DisambiguatedDefPathData,
+        self_ty: Ty<'tcx>,
+        trait_ref: Option<ty::TraitRef<'tcx>>,
+    ) -> Result<Self::Path, Self::Error> {
+        self.pretty_path_append_impl(
+            |mut cx| {
+                cx = print_prefix(cx)?;
+
+                if cx.keep_within_component {
+                    // HACK(eddyb) print the path similarly to how `FmtPrinter` prints it.
+                    cx.write_str("::")?;
+                } else {
+                    cx.path.finalize_pending_component();
+                }
+
+                Ok(cx)
+            },
+            self_ty,
+            trait_ref,
+        )
+    }
+    fn path_append(
+        mut self,
+        print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+        disambiguated_data: &DisambiguatedDefPathData,
+    ) -> Result<Self::Path, Self::Error> {
+        self = print_prefix(self)?;
+
+        // Skip `::{{constructor}}` on tuple/unit structs.
+        match disambiguated_data.data {
+            DefPathData::StructCtor => return Ok(self),
+            _ => {}
+        }
+
+        if self.keep_within_component {
+            // HACK(eddyb) print the path similarly to how `FmtPrinter` prints it.
+            self.write_str("::")?;
+        } else {
+            self.path.finalize_pending_component();
+        }
+
+        self.write_str(&disambiguated_data.data.as_interned_str().as_str())?;
+        Ok(self)
+    }
+    fn path_generic_args(
+        mut self,
+        print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+        args: &[Kind<'tcx>],
+    )  -> Result<Self::Path, Self::Error> {
+        self = print_prefix(self)?;
+
+        let args = args.iter().cloned().filter(|arg| {
+            match arg.unpack() {
+                UnpackedKind::Lifetime(_) => false,
+                _ => true,
+            }
+        });
+
+        if args.clone().next().is_some() {
+            self.generic_delimiters(|cx| cx.comma_sep(args))
+        } else {
+            Ok(self)
+        }
+    }
+}
+
+impl PrettyPrinter<'tcx, 'tcx> for SymbolPrinter<'_, 'tcx> {
+    fn region_should_not_be_omitted(
+        &self,
+        _region: ty::Region<'_>,
+    ) -> bool {
+        false
+    }
+    fn comma_sep<T>(
+        mut self,
+        mut elems: impl Iterator<Item = T>,
+    ) -> Result<Self, Self::Error>
+        where T: Print<'tcx, 'tcx, Self, Output = Self, Error = Self::Error>
+    {
+        if let Some(first) = elems.next() {
+            self = first.print(self)?;
+            for elem in elems {
+                self.write_str(",")?;
+                self = elem.print(self)?;
+            }
+        }
+        Ok(self)
+    }
+
+    fn generic_delimiters(
+        mut self,
+        f: impl FnOnce(Self) -> Result<Self, Self::Error>,
+    ) -> Result<Self, Self::Error> {
+        write!(self, "<")?;
+
+        let kept_within_component =
+            mem::replace(&mut self.keep_within_component, true);
+        self = f(self)?;
+        self.keep_within_component = kept_within_component;
+
+        write!(self, ">")?;
+
+        Ok(self)
+    }
+}
+
+impl fmt::Write for SymbolPrinter<'_, '_> {
+    fn write_str(&mut self, s: &str) -> fmt::Result {
+        // Name sanitation. LLVM will happily accept identifiers with weird names, but
+        // gas doesn't!
+        // gas accepts the following characters in symbols: a-z, A-Z, 0-9, ., _, $
+        // NVPTX assembly has more strict naming rules than gas, so additionally, dots
+        // are replaced with '$' there.
 
         for c in s.chars() {
+            if self.path.temp_buf.is_empty() {
+                match c {
+                    'a'..='z' | 'A'..='Z' | '_' => {}
+                    _ => {
+                        // Underscore-qualify anything that didn't start as an ident.
+                        self.path.temp_buf.push('_');
+                    }
+                }
+            }
             match c {
                 // Escape these with $ sequences
-                '@' => self.temp_buf.push_str("$SP$"),
-                '*' => self.temp_buf.push_str("$BP$"),
-                '&' => self.temp_buf.push_str("$RF$"),
-                '<' => self.temp_buf.push_str("$LT$"),
-                '>' => self.temp_buf.push_str("$GT$"),
-                '(' => self.temp_buf.push_str("$LP$"),
-                ')' => self.temp_buf.push_str("$RP$"),
-                ',' => self.temp_buf.push_str("$C$"),
+                '@' => self.path.temp_buf.push_str("$SP$"),
+                '*' => self.path.temp_buf.push_str("$BP$"),
+                '&' => self.path.temp_buf.push_str("$RF$"),
+                '<' => self.path.temp_buf.push_str("$LT$"),
+                '>' => self.path.temp_buf.push_str("$GT$"),
+                '(' => self.path.temp_buf.push_str("$LP$"),
+                ')' => self.path.temp_buf.push_str("$RP$"),
+                ',' => self.path.temp_buf.push_str("$C$"),
 
-                '-' | ':' => if self.strict_naming {
+                '-' | ':' | '.' if self.tcx.has_strict_asm_symbol_naming() => {
                     // NVPTX doesn't support these characters in symbol names.
-                    self.temp_buf.push('$')
+                    self.path.temp_buf.push('$')
                 }
-                else {
-                    // '.' doesn't occur in types and functions, so reuse it
-                    // for ':' and '-'
-                    self.temp_buf.push('.')
-                },
 
-                '.' => if self.strict_naming {
-                    self.temp_buf.push('$')
-                }
-                else {
-                    self.temp_buf.push('.')
-                },
+                // '.' doesn't occur in types and functions, so reuse it
+                // for ':' and '-'
+                '-' | ':' => self.path.temp_buf.push('.'),
 
                 // These are legal symbols
-                'a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '$' => self.temp_buf.push(c),
+                'a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '.' | '$' => self.path.temp_buf.push(c),
 
                 _ => {
-                    self.temp_buf.push('$');
+                    self.path.temp_buf.push('$');
                     for c in c.escape_unicode().skip(1) {
                         match c {
                             '{' => {}
-                            '}' => self.temp_buf.push('$'),
-                            c => self.temp_buf.push(c),
+                            '}' => self.path.temp_buf.push('$'),
+                            c => self.path.temp_buf.push(c),
                         }
                     }
                 }
             }
         }
 
-        let need_underscore = {
-            // Underscore-qualify anything that didn't start as an ident.
-            !self.temp_buf.is_empty()
-                && self.temp_buf.as_bytes()[0] != '_' as u8
-                && !(self.temp_buf.as_bytes()[0] as char).is_xid_start()
-        };
-
-        let _ = write!(
-            self.result,
-            "{}",
-            self.temp_buf.len() + (need_underscore as usize)
-        );
-
-        if need_underscore {
-            self.result.push('_');
-        }
-
-        self.result.push_str(&self.temp_buf);
-    }
-}
-
-impl ItemPathBuffer for SymbolPathBuffer {
-    fn root_mode(&self) -> &RootMode {
-        const ABSOLUTE: &RootMode = &RootMode::Absolute;
-        ABSOLUTE
-    }
-
-    fn push(&mut self, text: &str) {
-        self.sanitize_and_append(text);
+        Ok(())
     }
 }
diff --git a/src/librustc_codegen_utils/symbol_names_test.rs b/src/librustc_codegen_utils/symbol_names_test.rs
index c495268..6a2b6f1 100644
--- a/src/librustc_codegen_utils/symbol_names_test.rs
+++ b/src/librustc_codegen_utils/symbol_names_test.rs
@@ -1,7 +1,7 @@
 //! Walks the crate looking for items/impl-items/trait-items that have
-//! either a `rustc_symbol_name` or `rustc_item_path` attribute and
+//! either a `rustc_symbol_name` or `rustc_def_path` attribute and
 //! generates an error giving, respectively, the symbol name or
-//! item-path. This is used for unit testing the code that generates
+//! def-path. This is used for unit testing the code that generates
 //! paths etc in all kinds of annoying scenarios.
 
 use rustc::hir;
@@ -10,7 +10,7 @@
 use rustc_mir::monomorphize::Instance;
 
 const SYMBOL_NAME: &'static str = "rustc_symbol_name";
-const ITEM_PATH: &'static str = "rustc_item_path";
+const DEF_PATH: &'static str = "rustc_def_path";
 
 pub fn report_symbol_names<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     // if the `rustc_attrs` feature is not enabled, then the
@@ -41,9 +41,9 @@
                 let instance = Instance::mono(tcx, def_id);
                 let name = self.tcx.symbol_name(instance);
                 tcx.sess.span_err(attr.span, &format!("symbol-name({})", name));
-            } else if attr.check_name(ITEM_PATH) {
-                let path = tcx.item_path_str(def_id);
-                tcx.sess.span_err(attr.span, &format!("item-path({})", path));
+            } else if attr.check_name(DEF_PATH) {
+                let path = tcx.def_path_str(def_id);
+                tcx.sess.span_err(attr.span, &format!("def-path({})", path));
             }
 
             // (*) The formatting of `tag({})` is chosen so that tests can elect
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index c7b6f37..2598461 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -91,9 +91,6 @@
 use syntax::parse::{self, PResult};
 use syntax_pos::{DUMMY_SP, MultiSpan, FileName};
 
-#[cfg(test)]
-mod test;
-
 pub mod pretty;
 
 /// Exit status code used for successful compilation and help output.
@@ -683,7 +680,7 @@
 
                     let mut cfgs = sess.parse_sess.config.iter().filter_map(|&(name, ref value)| {
                         let gated_cfg = GatedCfg::gate(&ast::MetaItem {
-                            ident: ast::Path::from_ident(ast::Ident::with_empty_ctxt(name)),
+                            path: ast::Path::from_ident(ast::Ident::with_empty_ctxt(name)),
                             node: ast::MetaItemKind::Word,
                             span: DUMMY_SP,
                         });
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index 3182b2c..dde88a2 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -471,7 +471,7 @@
     }
 
     fn node_path(&self, id: ast::NodeId) -> Option<String> {
-        Some(self.tcx.node_path_str(id))
+        Some(self.tcx.def_path_str(self.tcx.hir().local_def_id(id)))
     }
 }
 
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
deleted file mode 100644
index f98939e..0000000
--- a/src/librustc_driver/test.rs
+++ /dev/null
@@ -1,614 +0,0 @@
-//! Standalone tests for the inference module.
-
-use errors::emitter::Emitter;
-use errors::{DiagnosticBuilder, Level};
-use rustc::hir;
-use rustc::infer::outlives::env::OutlivesEnvironment;
-use rustc::infer::{self, InferOk, InferResult, SuppressRegionErrors};
-use rustc::middle::region;
-use rustc::session::{DiagnosticOutput, config};
-use rustc::traits::ObligationCause;
-use rustc::ty::subst::Subst;
-use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
-use rustc_data_structures::sync;
-use rustc_target::spec::abi::Abi;
-use rustc_interface::interface;
-use syntax::ast;
-use syntax::feature_gate::UnstableFeatures;
-use syntax::source_map::FileName;
-use syntax::symbol::Symbol;
-
-struct Env<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
-    infcx: &'a infer::InferCtxt<'a, 'gcx, 'tcx>,
-    region_scope_tree: &'a mut region::ScopeTree,
-    param_env: ty::ParamEnv<'tcx>,
-}
-
-struct RH<'a> {
-    id: hir::ItemLocalId,
-    sub: &'a [RH<'a>],
-}
-
-const EMPTY_SOURCE_STR: &'static str = "#![feature(no_core)] #![no_core]";
-
-struct ExpectErrorEmitter {
-    messages: Vec<String>,
-}
-
-fn remove_message(e: &mut ExpectErrorEmitter, msg: &str, lvl: Level) {
-    match lvl {
-        Level::Bug | Level::Fatal | Level::Error => {}
-        _ => {
-            return;
-        }
-    }
-
-    debug!("Error: {}", msg);
-    match e.messages.iter().position(|m| msg.contains(m)) {
-        Some(i) => {
-            e.messages.remove(i);
-        }
-        None => {
-            debug!("Unexpected error: {} Expected: {:?}", msg, e.messages);
-            panic!("Unexpected error: {} Expected: {:?}", msg, e.messages);
-        }
-    }
-}
-
-impl Emitter for ExpectErrorEmitter {
-    fn emit(&mut self, db: &DiagnosticBuilder) {
-        remove_message(self, &db.message(), db.level);
-        for child in &db.children {
-            remove_message(self, &child.message(), child.level);
-        }
-    }
-}
-
-fn errors(msgs: &[&str]) -> (Box<dyn Emitter + Send + sync::Send>, usize) {
-    let mut v: Vec<_> = msgs.iter().map(|m| m.to_string()).collect();
-    if !v.is_empty() {
-        v.push("aborting due to previous error".to_owned());
-    }
-    (
-        box ExpectErrorEmitter { messages: v } as Box<dyn Emitter + Send + sync::Send>,
-        msgs.len(),
-    )
-}
-
-fn test_env<F>(
-    source_string: &str,
-    (emitter, expected_err_count): (Box<dyn Emitter + Send + sync::Send>, usize),
-    body: F,
-)
-where
-    F: FnOnce(Env) + Send,
-{
-    let mut opts = config::Options::default();
-    opts.debugging_opts.verbose = true;
-    opts.unstable_features = UnstableFeatures::Allow;
-
-    // When we're compiling this library with `--test` it'll run as a binary but
-    // not actually exercise much functionality.
-    // As a result most of the logic loading the codegen backend is defunkt
-    // (it assumes we're a dynamic library in a sysroot)
-    // so let's just use the metadata only backend which doesn't need to load any libraries.
-    opts.debugging_opts.codegen_backend = Some("metadata_only".to_owned());
-
-    let input = config::Input::Str {
-        name: FileName::anon_source_code(&source_string),
-        input: source_string.to_string(),
-    };
-
-    let config = interface::Config {
-        opts,
-        crate_cfg: Default::default(),
-        input,
-        input_path: None,
-        output_file: None,
-        output_dir: None,
-        file_loader: None,
-        diagnostic_output: DiagnosticOutput::Emitter(emitter),
-        stderr: None,
-        crate_name: Some("test".to_owned()),
-        lint_caps: Default::default(),
-    };
-
-    interface::run_compiler(config, |compiler| {
-        compiler.global_ctxt().unwrap().peek_mut().enter(|tcx| {
-            tcx.infer_ctxt().enter(|infcx| {
-                let mut region_scope_tree = region::ScopeTree::default();
-                let param_env = ty::ParamEnv::empty();
-                body(Env {
-                    infcx: &infcx,
-                    region_scope_tree: &mut region_scope_tree,
-                    param_env: param_env,
-                });
-                let outlives_env = OutlivesEnvironment::new(param_env);
-                let def_id = tcx.hir().local_def_id(ast::CRATE_NODE_ID);
-                infcx.resolve_regions_and_report_errors(
-                    def_id,
-                    &region_scope_tree,
-                    &outlives_env,
-                    SuppressRegionErrors::default(),
-                );
-                assert_eq!(tcx.sess.err_count(), expected_err_count);
-            });
-        })
-    });
-}
-
-fn d1() -> ty::DebruijnIndex {
-    ty::INNERMOST
-}
-
-fn d2() -> ty::DebruijnIndex {
-    d1().shifted_in(1)
-}
-
-impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> {
-    pub fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
-        self.infcx.tcx
-    }
-
-    pub fn create_region_hierarchy(
-        &mut self,
-        rh: &RH,
-        parent: (region::Scope, region::ScopeDepth),
-    ) {
-        let me = region::Scope {
-            id: rh.id,
-            data: region::ScopeData::Node,
-        };
-        self.region_scope_tree.record_scope_parent(me, Some(parent));
-        for child_rh in rh.sub {
-            self.create_region_hierarchy(child_rh, (me, parent.1 + 1));
-        }
-    }
-
-    pub fn create_simple_region_hierarchy(&mut self) {
-        // Creates a region hierarchy where 1 is root, 10 and 11 are
-        // children of 1, etc.
-
-        let dscope = region::Scope {
-            id: hir::ItemLocalId::from_u32(1),
-            data: region::ScopeData::Destruction,
-        };
-        self.region_scope_tree.record_scope_parent(dscope, None);
-        self.create_region_hierarchy(
-            &RH {
-                id: hir::ItemLocalId::from_u32(1),
-                sub: &[
-                    RH {
-                        id: hir::ItemLocalId::from_u32(10),
-                        sub: &[],
-                    },
-                    RH {
-                        id: hir::ItemLocalId::from_u32(11),
-                        sub: &[],
-                    },
-                ],
-            },
-            (dscope, 1),
-        );
-    }
-
-    #[allow(dead_code)] // this seems like it could be useful, even if we don't use it now
-    pub fn lookup_item(&self, names: &[String]) -> hir::HirId {
-        return match search_mod(self, &self.infcx.tcx.hir().krate().module, 0, names) {
-            Some(id) => id,
-            None => {
-                panic!("no item found: `{}`", names.join("::"));
-            }
-        };
-
-        fn search_mod(
-            this: &Env,
-            m: &hir::Mod,
-            idx: usize,
-            names: &[String],
-        ) -> Option<hir::HirId> {
-            assert!(idx < names.len());
-            for item in &m.item_ids {
-                let item = this.infcx.tcx.hir().expect_item(item.id);
-                if item.ident.to_string() == names[idx] {
-                    return search(this, item, idx + 1, names);
-                }
-            }
-            return None;
-        }
-
-        fn search(this: &Env, it: &hir::Item, idx: usize, names: &[String]) -> Option<hir::HirId> {
-            if idx == names.len() {
-                return Some(it.hir_id);
-            }
-
-            return match it.node {
-                hir::ItemKind::Use(..)
-                | hir::ItemKind::ExternCrate(..)
-                | hir::ItemKind::Const(..)
-                | hir::ItemKind::Static(..)
-                | hir::ItemKind::Fn(..)
-                | hir::ItemKind::ForeignMod(..)
-                | hir::ItemKind::GlobalAsm(..)
-                | hir::ItemKind::Existential(..)
-                | hir::ItemKind::Ty(..) => None,
-
-                hir::ItemKind::Enum(..)
-                | hir::ItemKind::Struct(..)
-                | hir::ItemKind::Union(..)
-                | hir::ItemKind::Trait(..)
-                | hir::ItemKind::TraitAlias(..)
-                | hir::ItemKind::Impl(..) => None,
-
-                hir::ItemKind::Mod(ref m) => search_mod(this, m, idx, names),
-            };
-        }
-    }
-
-    pub fn make_subtype(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
-        match self.infcx
-            .at(&ObligationCause::dummy(), self.param_env)
-            .sub(a, b)
-        {
-            Ok(_) => true,
-            Err(ref e) => panic!("Encountered error: {}", e),
-        }
-    }
-
-    pub fn is_subtype(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
-        self.infcx.can_sub(self.param_env, a, b).is_ok()
-    }
-
-    pub fn assert_subtype(&self, a: Ty<'tcx>, b: Ty<'tcx>) {
-        if !self.is_subtype(a, b) {
-            panic!("{} is not a subtype of {}, but it should be", a, b);
-        }
-    }
-
-    pub fn assert_eq(&self, a: Ty<'tcx>, b: Ty<'tcx>) {
-        self.assert_subtype(a, b);
-        self.assert_subtype(b, a);
-    }
-
-    pub fn t_fn(&self, input_tys: &[Ty<'tcx>], output_ty: Ty<'tcx>) -> Ty<'tcx> {
-        self.infcx
-            .tcx
-            .mk_fn_ptr(ty::Binder::bind(self.infcx.tcx.mk_fn_sig(
-                input_tys.iter().cloned(),
-                output_ty,
-                false,
-                hir::Unsafety::Normal,
-                Abi::Rust,
-            )))
-    }
-
-    pub fn t_nil(&self) -> Ty<'tcx> {
-        self.infcx.tcx.mk_unit()
-    }
-
-    pub fn t_pair(&self, ty1: Ty<'tcx>, ty2: Ty<'tcx>) -> Ty<'tcx> {
-        self.infcx.tcx.intern_tup(&[ty1, ty2])
-    }
-
-    pub fn t_param(&self, index: u32) -> Ty<'tcx> {
-        let name = format!("T{}", index);
-        self.infcx
-            .tcx
-            .mk_ty_param(index, Symbol::intern(&name).as_interned_str())
-    }
-
-    pub fn re_early_bound(&self, index: u32, name: &'static str) -> ty::Region<'tcx> {
-        let name = Symbol::intern(name).as_interned_str();
-        self.infcx
-            .tcx
-            .mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
-                def_id: self.infcx.tcx.hir().local_def_id(ast::CRATE_NODE_ID),
-                index,
-                name,
-            }))
-    }
-
-    pub fn re_late_bound_with_debruijn(
-        &self,
-        id: u32,
-        debruijn: ty::DebruijnIndex,
-    ) -> ty::Region<'tcx> {
-        self.infcx
-            .tcx
-            .mk_region(ty::ReLateBound(debruijn, ty::BrAnon(id)))
-    }
-
-    pub fn t_rptr(&self, r: ty::Region<'tcx>) -> Ty<'tcx> {
-        self.infcx.tcx.mk_imm_ref(r, self.tcx().types.isize)
-    }
-
-    pub fn t_rptr_late_bound(&self, id: u32) -> Ty<'tcx> {
-        let r = self.re_late_bound_with_debruijn(id, d1());
-        self.infcx.tcx.mk_imm_ref(r, self.tcx().types.isize)
-    }
-
-    pub fn t_rptr_late_bound_with_debruijn(
-        &self,
-        id: u32,
-        debruijn: ty::DebruijnIndex,
-    ) -> Ty<'tcx> {
-        let r = self.re_late_bound_with_debruijn(id, debruijn);
-        self.infcx.tcx.mk_imm_ref(r, self.tcx().types.isize)
-    }
-
-    pub fn t_rptr_scope(&self, id: u32) -> Ty<'tcx> {
-        let r = ty::ReScope(region::Scope {
-            id: hir::ItemLocalId::from_u32(id),
-            data: region::ScopeData::Node,
-        });
-        self.infcx
-            .tcx
-            .mk_imm_ref(self.infcx.tcx.mk_region(r), self.tcx().types.isize)
-    }
-
-    pub fn re_free(&self, id: u32) -> ty::Region<'tcx> {
-        self.infcx.tcx.mk_region(ty::ReFree(ty::FreeRegion {
-            scope: self.infcx.tcx.hir().local_def_id(ast::CRATE_NODE_ID),
-            bound_region: ty::BrAnon(id),
-        }))
-    }
-
-    pub fn t_rptr_free(&self, id: u32) -> Ty<'tcx> {
-        let r = self.re_free(id);
-        self.infcx.tcx.mk_imm_ref(r, self.tcx().types.isize)
-    }
-
-    pub fn sub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) -> InferResult<'tcx, ()> {
-        self.infcx
-            .at(&ObligationCause::dummy(), self.param_env)
-            .sub(t1, t2)
-    }
-
-    /// Checks that `t1 <: t2` is true (this may register additional
-    /// region checks).
-    pub fn check_sub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) {
-        match self.sub(t1, t2) {
-            Ok(InferOk {
-                obligations,
-                value: (),
-            }) => {
-                // None of these tests should require nested obligations.
-                assert!(obligations.is_empty());
-            }
-            Err(ref e) => {
-                panic!("unexpected error computing sub({:?},{:?}): {}", t1, t2, e);
-            }
-        }
-    }
-}
-
-#[test]
-fn contravariant_region_ptr_ok() {
-    test_env(EMPTY_SOURCE_STR, errors(&[]), |mut env| {
-        env.create_simple_region_hierarchy();
-        let t_rptr1 = env.t_rptr_scope(1);
-        let t_rptr10 = env.t_rptr_scope(10);
-        env.assert_eq(t_rptr1, t_rptr1);
-        env.assert_eq(t_rptr10, t_rptr10);
-        env.make_subtype(t_rptr1, t_rptr10);
-    })
-}
-
-#[test]
-fn contravariant_region_ptr_err() {
-    test_env(EMPTY_SOURCE_STR, errors(&["mismatched types"]), |mut env| {
-        env.create_simple_region_hierarchy();
-        let t_rptr1 = env.t_rptr_scope(1);
-        let t_rptr10 = env.t_rptr_scope(10);
-        env.assert_eq(t_rptr1, t_rptr1);
-        env.assert_eq(t_rptr10, t_rptr10);
-
-        // This will cause an error when regions are resolved.
-        env.make_subtype(t_rptr10, t_rptr1);
-    })
-}
-
-#[test]
-fn sub_bound_free_true() {
-    //! Test that:
-    //!
-    //!     for<'a> fn(&'a isize) <: fn(&'b isize)
-    //!
-    //! *does* hold.
-
-    test_env(EMPTY_SOURCE_STR, errors(&[]), |mut env| {
-        env.create_simple_region_hierarchy();
-        let t_rptr_bound1 = env.t_rptr_late_bound(1);
-        let t_rptr_free1 = env.t_rptr_free(1);
-        env.check_sub(
-            env.t_fn(&[t_rptr_bound1], env.tcx().types.isize),
-            env.t_fn(&[t_rptr_free1], env.tcx().types.isize),
-        );
-    })
-}
-
-/// Test substituting a bound region into a function, which introduces another level of binding.
-/// This requires adjusting the Debruijn index.
-#[test]
-fn subst_ty_renumber_bound() {
-    test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
-        // Situation:
-        // Theta = [A -> &'a foo]
-
-        let t_rptr_bound1 = env.t_rptr_late_bound(1);
-
-        // t_source = fn(A)
-        let t_source = {
-            let t_param = env.t_param(0);
-            env.t_fn(&[t_param], env.t_nil())
-        };
-
-        let substs = env.infcx.tcx.intern_substs(&[t_rptr_bound1.into()]);
-        let t_substituted = t_source.subst(env.infcx.tcx, substs);
-
-        // t_expected = fn(&'a isize)
-        let t_expected = {
-            let t_ptr_bound2 = env.t_rptr_late_bound_with_debruijn(1, d2());
-            env.t_fn(&[t_ptr_bound2], env.t_nil())
-        };
-
-        debug!(
-            "subst_bound: t_source={:?} substs={:?} t_substituted={:?} t_expected={:?}",
-            t_source, substs, t_substituted, t_expected
-        );
-
-        assert_eq!(t_substituted, t_expected);
-    })
-}
-
-/// Tests substituting a bound region into a function, which introduces another level of binding.
-/// This requires adjusting the De Bruijn index.
-#[test]
-fn subst_ty_renumber_some_bounds() {
-    test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
-        // Situation:
-        // `Theta = [A -> &'a foo]`
-
-        let t_rptr_bound1 = env.t_rptr_late_bound(1);
-
-        // `t_source = (A, fn(A))`
-        let t_source = {
-            let t_param = env.t_param(0);
-            env.t_pair(t_param, env.t_fn(&[t_param], env.t_nil()))
-        };
-
-        let substs = env.infcx.tcx.intern_substs(&[t_rptr_bound1.into()]);
-        let t_substituted = t_source.subst(env.infcx.tcx, substs);
-
-        // `t_expected = (&'a isize, fn(&'a isize))`
-        //
-        // However, note that the Debruijn index is different in the different cases.
-        let t_expected = {
-            let t_rptr_bound2 = env.t_rptr_late_bound_with_debruijn(1, d2());
-            env.t_pair(t_rptr_bound1, env.t_fn(&[t_rptr_bound2], env.t_nil()))
-        };
-
-        debug!(
-            "subst_bound: t_source={:?} substs={:?} t_substituted={:?} t_expected={:?}",
-            t_source, substs, t_substituted, t_expected
-        );
-
-        assert_eq!(t_substituted, t_expected);
-    })
-}
-
-/// Tests that we correctly compute whether a type has escaping regions or not.
-#[test]
-fn escaping() {
-    test_env(EMPTY_SOURCE_STR, errors(&[]), |mut env| {
-        // Situation:
-        // `Theta = [A -> &'a foo]`
-        env.create_simple_region_hierarchy();
-
-        assert!(!env.t_nil().has_escaping_bound_vars());
-
-        let t_rptr_free1 = env.t_rptr_free(1);
-        assert!(!t_rptr_free1.has_escaping_bound_vars());
-
-        let t_rptr_bound1 = env.t_rptr_late_bound_with_debruijn(1, d1());
-        assert!(t_rptr_bound1.has_escaping_bound_vars());
-
-        let t_rptr_bound2 = env.t_rptr_late_bound_with_debruijn(1, d2());
-        assert!(t_rptr_bound2.has_escaping_bound_vars());
-
-        // `t_fn = fn(A)`
-        let t_param = env.t_param(0);
-        assert!(!t_param.has_escaping_bound_vars());
-        let t_fn = env.t_fn(&[t_param], env.t_nil());
-        assert!(!t_fn.has_escaping_bound_vars());
-    })
-}
-
-/// Tests applying a substitution where the value being substituted for an early-bound region is a
-/// late-bound region.
-#[test]
-fn subst_region_renumber_region() {
-    test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
-        let re_bound1 = env.re_late_bound_with_debruijn(1, d1());
-
-        // `type t_source<'a> = fn(&'a isize)`
-        let t_source = {
-            let re_early = env.re_early_bound(0, "'a");
-            env.t_fn(&[env.t_rptr(re_early)], env.t_nil())
-        };
-
-        let substs = env.infcx.tcx.intern_substs(&[re_bound1.into()]);
-        let t_substituted = t_source.subst(env.infcx.tcx, substs);
-
-        // `t_expected = fn(&'a isize)`
-        //
-        // but not that the Debruijn index is different in the different cases.
-        let t_expected = {
-            let t_rptr_bound2 = env.t_rptr_late_bound_with_debruijn(1, d2());
-            env.t_fn(&[t_rptr_bound2], env.t_nil())
-        };
-
-        debug!(
-            "subst_bound: t_source={:?} substs={:?} t_substituted={:?} t_expected={:?}",
-            t_source, substs, t_substituted, t_expected
-        );
-
-        assert_eq!(t_substituted, t_expected);
-    })
-}
-
-#[test]
-fn walk_ty() {
-    test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
-        let tcx = env.infcx.tcx;
-        let int_ty = tcx.types.isize;
-        let usize_ty = tcx.types.usize;
-        let tup1_ty = tcx.intern_tup(&[int_ty, usize_ty, int_ty, usize_ty]);
-        let tup2_ty = tcx.intern_tup(&[tup1_ty, tup1_ty, usize_ty]);
-        let walked: Vec<_> = tup2_ty.walk().collect();
-        assert_eq!(
-            walked,
-            [
-                tup2_ty, tup1_ty, int_ty, usize_ty, int_ty, usize_ty, tup1_ty, int_ty, usize_ty,
-                int_ty, usize_ty, usize_ty
-            ]
-        );
-    })
-}
-
-#[test]
-fn walk_ty_skip_subtree() {
-    test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
-        let tcx = env.infcx.tcx;
-        let int_ty = tcx.types.isize;
-        let usize_ty = tcx.types.usize;
-        let tup1_ty = tcx.intern_tup(&[int_ty, usize_ty, int_ty, usize_ty]);
-        let tup2_ty = tcx.intern_tup(&[tup1_ty, tup1_ty, usize_ty]);
-
-        // types we expect to see (in order), plus a boolean saying
-        // whether to skip the subtree.
-        let mut expected = vec![
-            (tup2_ty, false),
-            (tup1_ty, false),
-            (int_ty, false),
-            (usize_ty, false),
-            (int_ty, false),
-            (usize_ty, false),
-            (tup1_ty, true), // skip the isize/usize/isize/usize
-            (usize_ty, false),
-        ];
-        expected.reverse();
-
-        let mut walker = tup2_ty.walk();
-        while let Some(t) = walker.next() {
-            debug!("walked to {:?}", t);
-            let (expected_ty, skip) = expected.pop().unwrap();
-            assert_eq!(t, expected_ty);
-            if skip {
-                walker.skip_current_subtree();
-            }
-        }
-
-        assert!(expected.is_empty());
-    })
-}
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index 7c7698d..6b4b437 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -2,7 +2,6 @@
 
 #![feature(custom_attribute)]
 #![allow(unused_attributes)]
-#![feature(range_contains)]
 #![cfg_attr(unix, feature(libc))]
 #![feature(nll)]
 #![feature(optin_builtin_traits)]
diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs
index 1f69d61..c964f4c 100644
--- a/src/librustc_incremental/assert_dep_graph.rs
+++ b/src/librustc_incremental/assert_dep_graph.rs
@@ -99,12 +99,12 @@
     fn argument(&self, attr: &ast::Attribute) -> Option<ast::Name> {
         let mut value = None;
         for list_item in attr.meta_item_list().unwrap_or_default() {
-            match list_item.word() {
-                Some(word) if value.is_none() =>
-                    value = Some(word.name()),
+            match list_item.ident() {
+                Some(ident) if list_item.is_word() && value.is_none() =>
+                    value = Some(ident.name),
                 _ =>
                     // FIXME better-encapsulate meta_item (don't directly access `node`)
-                    span_bug!(list_item.span(), "unexpected meta-item {:?}", list_item.node),
+                    span_bug!(list_item.span(), "unexpected meta-item {:?}", list_item),
             }
         }
         value
@@ -206,7 +206,7 @@
                 tcx.sess.span_err(
                     target_span,
                     &format!("no path from `{}` to `{}`",
-                             tcx.item_path_str(source_def_id),
+                             tcx.def_path_str(source_def_id),
                              target_pass));
             } else {
                 tcx.sess.span_err(
diff --git a/src/librustc_incremental/assert_module_sources.rs b/src/librustc_incremental/assert_module_sources.rs
index 5cbb412..2c83501 100644
--- a/src/librustc_incremental/assert_module_sources.rs
+++ b/src/librustc_incremental/assert_module_sources.rs
@@ -153,7 +153,7 @@
                     return value;
                 } else {
                     self.tcx.sess.span_fatal(
-                        item.span,
+                        item.span(),
                         &format!("associated value expected for `{}`", name));
                 }
             }
diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs
index 2794b6c..6b5e19c 100644
--- a/src/librustc_incremental/persist/dirty_clean.rs
+++ b/src/librustc_incremental/persist/dirty_clean.rs
@@ -36,16 +36,16 @@
 
 /// For typedef, constants, and statics
 const BASE_CONST: &[&str] = &[
-    label_strs::TypeOfItem,
+    label_strs::type_of,
 ];
 
 /// DepNodes for functions + methods
 const BASE_FN: &[&str] = &[
     // Callers will depend on the signature of these items, so we better test
     label_strs::FnSignature,
-    label_strs::GenericsOfItem,
-    label_strs::PredicatesOfItem,
-    label_strs::TypeOfItem,
+    label_strs::generics_of,
+    label_strs::predicates_of,
+    label_strs::type_of,
 
     // And a big part of compilation (that we eventually want to cache) is type inference
     // information:
@@ -62,7 +62,7 @@
 /// `impl` implementation of struct/trait
 const BASE_IMPL: &[&str] = &[
     label_strs::AssociatedItemDefIds,
-    label_strs::GenericsOfItem,
+    label_strs::generics_of,
     label_strs::ImplTraitRef,
 ];
 
@@ -78,17 +78,17 @@
 /// Note that changing the type of a field does not change the type of the struct or enum, but
 /// adding/removing fields or changing a fields name or visibility does.
 const BASE_STRUCT: &[&str] = &[
-    label_strs::GenericsOfItem,
-    label_strs::PredicatesOfItem,
-    label_strs::TypeOfItem,
+    label_strs::generics_of,
+    label_strs::predicates_of,
+    label_strs::type_of,
 ];
 
 /// Trait definition `DepNode`s.
 const BASE_TRAIT_DEF: &[&str] = &[
     label_strs::AssociatedItemDefIds,
-    label_strs::GenericsOfItem,
+    label_strs::generics_of,
     label_strs::ObjectSafety,
-    label_strs::PredicatesOfItem,
+    label_strs::predicates_of,
     label_strs::SpecializationGraph,
     label_strs::TraitDefOfItem,
     label_strs::TraitImpls,
@@ -179,7 +179,7 @@
 // Fields are kind of separate from their containers, as they can change independently from
 // them. We should at least check
 //
-//     TypeOfItem for these.
+//     type_of for these.
 
 type Labels = FxHashSet<String>;
 
@@ -430,13 +430,13 @@
             if DepNode::has_label_string(label) {
                 if out.contains(label) {
                     self.tcx.sess.span_fatal(
-                        item.span,
+                        item.span(),
                         &format!("dep-node label `{}` is repeated", label));
                 }
                 out.insert(label.to_string());
             } else {
                 self.tcx.sess.span_fatal(
-                    item.span,
+                    item.span(),
                     &format!("dep-node label `{}` not recognized", label));
             }
         }
@@ -463,7 +463,7 @@
         if let Some(def_id) = dep_node.extract_def_id(self.tcx) {
             format!("{:?}({})",
                     dep_node.kind,
-                    self.tcx.item_path_str(def_id))
+                    self.tcx.def_path_str(def_id))
         } else {
             format!("{:?}({:?})", dep_node.kind, dep_node.hash)
         }
@@ -576,13 +576,13 @@
     if let Some(value) = item.value_str() {
         value
     } else {
-        let msg = if let Some(name) = item.name() {
+        let msg = if let Some(name) = item.ident_str() {
             format!("associated value expected for `{}`", name)
         } else {
             "expected an associated value".to_string()
         };
 
-        tcx.sess.span_fatal(item.span, &msg);
+        tcx.sess.span_fatal(item.span(), &msg);
     }
 }
 
diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs
index 5bb47bd..0c710fd 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -243,6 +243,7 @@
         krate,
         &sess.parse_sess,
         sess.edition(),
+        &sess.opts.debugging_opts.allow_features,
     );
     // these need to be set "early" so that expansion sees `quote` if enabled.
     sess.init_features(features);
diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs
index 0f858d6..b1ef4e3 100644
--- a/src/librustc_interface/util.rs
+++ b/src/librustc_interface/util.rs
@@ -266,9 +266,6 @@
         let codegen_name = sess.opts.debugging_opts.codegen_backend.as_ref()
             .unwrap_or(&sess.target.target.options.codegen_backend);
         let backend = match &codegen_name[..] {
-            "metadata_only" => {
-                rustc_codegen_utils::codegen_backend::MetadataOnlyCodegenBackend::boxed
-            }
             filename if filename.contains(".") => {
                 load_backend_from_dylib(filename.as_ref())
             }
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 7a7c49e..80c5eee 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -760,7 +760,7 @@
 impl EarlyLintPass for DeprecatedAttr {
     fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) {
         for &&(n, _, _, ref g) in &self.depr_attrs {
-            if attr.name() == n {
+            if attr.ident_str() == Some(n) {
                 if let &AttributeGate::Gated(Stability::Deprecated(link, suggestion),
                                              ref name,
                                              ref reason,
@@ -831,7 +831,7 @@
 
             let span = sugared_span.take().unwrap_or_else(|| attr.span);
 
-            if attr.name() == "doc" {
+            if attr.check_name("doc") {
                 let mut err = cx.struct_span_lint(UNUSED_DOC_COMMENTS, span, "unused doc comment");
 
                 err.span_label(
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index 86b8b27..648cae3 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -182,7 +182,7 @@
             for attr in cx.tcx.get_attrs(def_id).iter() {
                 if attr.check_name("must_use") {
                     let msg = format!("unused {}`{}`{} that must be used",
-                        descr_pre_path, cx.tcx.item_path_str(def_id), descr_post_path);
+                        descr_pre_path, cx.tcx.def_path_str(def_id), descr_post_path);
                     let mut err = cx.struct_span_lint(UNUSED_MUST_USE, sp, &msg);
                     // check for #[must_use = "..."]
                     if let Some(note) = attr.value_str() {
@@ -267,19 +267,21 @@
             }
         }
 
-        let name = attr.name();
+        let name = attr.ident_str();
         if !attr::is_used(attr) {
             debug!("Emitting warning for: {:?}", attr);
             cx.span_lint(UNUSED_ATTRIBUTES, attr.span, "unused attribute");
             // Is it a builtin attribute that must be used at the crate level?
             let known_crate = BUILTIN_ATTRIBUTES.iter()
-                .find(|&&(builtin, ty, ..)| name == builtin && ty == AttributeType::CrateLevel)
+                .find(|&&(builtin, ty, ..)| {
+                    name == Some(builtin) && ty == AttributeType::CrateLevel
+                })
                 .is_some();
 
             // Has a plugin registered this attribute as one that must be used at
             // the crate level?
             let plugin_crate = plugin_attributes.iter()
-                .find(|&&(ref x, t)| name == &**x && AttributeType::CrateLevel == t)
+                .find(|&&(ref x, t)| name == Some(x) && AttributeType::CrateLevel == t)
                 .is_some();
             if known_crate || plugin_crate {
                 let msg = match attr.style {
diff --git a/src/librustc_macros/src/lib.rs b/src/librustc_macros/src/lib.rs
index cad3126..e99ceb1 100644
--- a/src/librustc_macros/src/lib.rs
+++ b/src/librustc_macros/src/lib.rs
@@ -1,8 +1,18 @@
 #![feature(proc_macro_hygiene)]
 #![deny(rust_2018_idioms)]
 
+extern crate proc_macro;
+
 use synstructure::decl_derive;
 
+use proc_macro::TokenStream;
+
 mod hash_stable;
+mod query;
+
+#[proc_macro]
+pub fn rustc_queries(input: TokenStream) -> TokenStream {
+    query::rustc_queries(input)
+}
 
 decl_derive!([HashStable, attributes(stable_hasher)] => hash_stable::hash_stable_derive);
diff --git a/src/librustc_macros/src/query.rs b/src/librustc_macros/src/query.rs
new file mode 100644
index 0000000..3849e47
--- /dev/null
+++ b/src/librustc_macros/src/query.rs
@@ -0,0 +1,394 @@
+use proc_macro::TokenStream;
+use syn::{
+    Token, Ident, Type, Attribute, ReturnType, Expr, Block, Error,
+    braced, parenthesized, parse_macro_input,
+};
+use syn::spanned::Spanned;
+use syn::parse::{Result, Parse, ParseStream};
+use syn::punctuated::Punctuated;
+use syn;
+use quote::quote;
+
+#[allow(non_camel_case_types)]
+mod kw {
+    syn::custom_keyword!(query);
+}
+
+/// Ident or a wildcard `_`.
+struct IdentOrWild(Ident);
+
+impl Parse for IdentOrWild {
+    fn parse(input: ParseStream<'_>) -> Result<Self> {
+        Ok(if input.peek(Token![_]) {
+            let underscore = input.parse::<Token![_]>()?;
+            IdentOrWild(Ident::new("_", underscore.span()))
+        } else {
+            IdentOrWild(input.parse()?)
+        })
+    }
+}
+
+/// A modifier for a query
+enum QueryModifier {
+    /// The description of the query.
+    Desc(Option<Ident>, Punctuated<Expr, Token![,]>),
+
+    /// Cache the query to disk if the `Expr` returns true.
+    Cache(Option<Ident>, Expr),
+
+    /// Custom code to load the query from disk.
+    LoadCached(Ident, Ident, Block),
+
+    /// A cycle error for this query aborting the compilation with a fatal error.
+    FatalCycle,
+}
+
+impl Parse for QueryModifier {
+    fn parse(input: ParseStream<'_>) -> Result<Self> {
+        let modifier: Ident = input.parse()?;
+        if modifier == "desc" {
+            // Parse a description modifier like:
+            // `desc { |tcx| "foo {}", tcx.item_path(key) }`
+            let attr_content;
+            braced!(attr_content in input);
+            let tcx = if attr_content.peek(Token![|]) {
+                attr_content.parse::<Token![|]>()?;
+                let tcx = attr_content.parse()?;
+                attr_content.parse::<Token![|]>()?;
+                Some(tcx)
+            } else {
+                None
+            };
+            let desc = attr_content.parse_terminated(Expr::parse)?;
+            Ok(QueryModifier::Desc(tcx, desc))
+        } else if modifier == "cache" {
+            // Parse a cache modifier like:
+            // `cache { |tcx| key.is_local() }`
+            let attr_content;
+            braced!(attr_content in input);
+            let tcx = if attr_content.peek(Token![|]) {
+                attr_content.parse::<Token![|]>()?;
+                let tcx = attr_content.parse()?;
+                attr_content.parse::<Token![|]>()?;
+                Some(tcx)
+            } else {
+                None
+            };
+            let expr = attr_content.parse()?;
+            Ok(QueryModifier::Cache(tcx, expr))
+        } else if modifier == "load_cached" {
+            // Parse a load_cached modifier like:
+            // `load_cached(tcx, id) { tcx.queries.on_disk_cache.try_load_query_result(tcx, id) }`
+            let args;
+            parenthesized!(args in input);
+            let tcx = args.parse()?;
+            args.parse::<Token![,]>()?;
+            let id = args.parse()?;
+            let block = input.parse()?;
+            Ok(QueryModifier::LoadCached(tcx, id, block))
+        } else if modifier == "fatal_cycle" {
+            Ok(QueryModifier::FatalCycle)
+        } else {
+            Err(Error::new(modifier.span(), "unknown query modifier"))
+        }
+    }
+}
+
+/// Ensures only doc comment attributes are used
+fn check_attributes(attrs: Vec<Attribute>) -> Result<()> {
+    for attr in attrs {
+        if !attr.path.is_ident("doc") {
+            return Err(Error::new(attr.span(), "attributes not supported on queries"));
+        }
+    }
+    Ok(())
+}
+
+/// A compiler query. `query ... { ... }`
+struct Query {
+    modifiers: List<QueryModifier>,
+    name: Ident,
+    key: IdentOrWild,
+    arg: Type,
+    result: ReturnType,
+}
+
+impl Parse for Query {
+    fn parse(input: ParseStream<'_>) -> Result<Self> {
+        check_attributes(input.call(Attribute::parse_outer)?)?;
+
+        // Parse the query declaration. Like `query type_of(key: DefId) -> Ty<'tcx>`
+        input.parse::<kw::query>()?;
+        let name: Ident = input.parse()?;
+        let arg_content;
+        parenthesized!(arg_content in input);
+        let key = arg_content.parse()?;
+        arg_content.parse::<Token![:]>()?;
+        let arg = arg_content.parse()?;
+        let result = input.parse()?;
+
+        // Parse the query modifiers
+        let content;
+        braced!(content in input);
+        let modifiers = content.parse()?;
+
+        Ok(Query {
+            modifiers,
+            name,
+            key,
+            arg,
+            result,
+        })
+    }
+}
+
+/// A type used to greedily parse another type until the input is empty.
+struct List<T>(Vec<T>);
+
+impl<T: Parse> Parse for List<T> {
+    fn parse(input: ParseStream<'_>) -> Result<Self> {
+        let mut list = Vec::new();
+        while !input.is_empty() {
+            list.push(input.parse()?);
+        }
+        Ok(List(list))
+    }
+}
+
+/// A named group containing queries.
+struct Group {
+    name: Ident,
+    queries: List<Query>,
+}
+
+impl Parse for Group {
+    fn parse(input: ParseStream<'_>) -> Result<Self> {
+        let name: Ident = input.parse()?;
+        let content;
+        braced!(content in input);
+        Ok(Group {
+            name,
+            queries: content.parse()?,
+        })
+    }
+}
+
+struct QueryModifiers {
+    /// The description of the query.
+    desc: Option<(Option<Ident>, Punctuated<Expr, Token![,]>)>,
+
+    /// Cache the query to disk if the `Expr` returns true.
+    cache: Option<(Option<Ident>, Expr)>,
+
+    /// Custom code to load the query from disk.
+    load_cached: Option<(Ident, Ident, Block)>,
+
+    /// A cycle error for this query aborting the compilation with a fatal error.
+    fatal_cycle: bool,
+}
+
+/// Process query modifiers into a struct, erroring on duplicates
+fn process_modifiers(query: &mut Query) -> QueryModifiers {
+    let mut load_cached = None;
+    let mut cache = None;
+    let mut desc = None;
+    let mut fatal_cycle = false;
+    for modifier in query.modifiers.0.drain(..) {
+        match modifier {
+            QueryModifier::LoadCached(tcx, id, block) => {
+                if load_cached.is_some() {
+                    panic!("duplicate modifier `load_cached` for query `{}`", query.name);
+                }
+                load_cached = Some((tcx, id, block));
+            }
+            QueryModifier::Cache(tcx, expr) => {
+                if cache.is_some() {
+                    panic!("duplicate modifier `cache` for query `{}`", query.name);
+                }
+                cache = Some((tcx, expr));
+            }
+            QueryModifier::Desc(tcx, list) => {
+                if desc.is_some() {
+                    panic!("duplicate modifier `desc` for query `{}`", query.name);
+                }
+                desc = Some((tcx, list));
+            }
+            QueryModifier::FatalCycle => {
+                if fatal_cycle {
+                    panic!("duplicate modifier `fatal_cycle` for query `{}`", query.name);
+                }
+                fatal_cycle = true;
+            }
+        }
+    }
+    QueryModifiers {
+        load_cached,
+        cache,
+        desc,
+        fatal_cycle,
+    }
+}
+
+/// Add the impl of QueryDescription for the query to `impls` if one is requested
+fn add_query_description_impl(
+    query: &Query,
+    modifiers: QueryModifiers,
+    impls: &mut proc_macro2::TokenStream
+) {
+    let name = &query.name;
+    let arg = &query.arg;
+    let key = &query.key.0;
+
+    // Find out if we should cache the query on disk
+    let cache = modifiers.cache.as_ref().map(|(tcx, expr)| {
+        let try_load_from_disk = if let Some((tcx, id, block)) = modifiers.load_cached.as_ref() {
+            // Use custom code to load the query from disk
+            quote! {
+                #[inline]
+                fn try_load_from_disk(
+                    #tcx: TyCtxt<'_, 'tcx, 'tcx>,
+                    #id: SerializedDepNodeIndex
+                ) -> Option<Self::Value> {
+                    #block
+                }
+            }
+        } else {
+            // Use the default code to load the query from disk
+            quote! {
+                #[inline]
+                fn try_load_from_disk(
+                    tcx: TyCtxt<'_, 'tcx, 'tcx>,
+                    id: SerializedDepNodeIndex
+                ) -> Option<Self::Value> {
+                    tcx.queries.on_disk_cache.try_load_query_result(tcx, id)
+                }
+            }
+        };
+
+        let tcx = tcx.as_ref().map(|t| quote! { #t }).unwrap_or(quote! { _ });
+        quote! {
+            #[inline]
+            fn cache_on_disk(#tcx: TyCtxt<'_, 'tcx, 'tcx>, #key: Self::Key) -> bool {
+                #expr
+            }
+
+            #try_load_from_disk
+        }
+    });
+
+    if cache.is_none() && modifiers.load_cached.is_some() {
+        panic!("load_cached modifier on query `{}` without a cache modifier", name);
+    }
+
+    let desc = modifiers.desc.as_ref().map(|(tcx, desc)| {
+        let tcx = tcx.as_ref().map(|t| quote! { #t }).unwrap_or(quote! { _ });
+        quote! {
+            fn describe(
+                #tcx: TyCtxt<'_, '_, '_>,
+                #key: #arg,
+            ) -> Cow<'static, str> {
+                format!(#desc).into()
+            }
+        }
+    });
+
+    if desc.is_some() || cache.is_some() {
+        let cache = cache.unwrap_or(quote! {});
+        let desc = desc.unwrap_or(quote! {});
+
+        impls.extend(quote! {
+            impl<'tcx> QueryDescription<'tcx> for queries::#name<'tcx> {
+                #desc
+                #cache
+            }
+        });
+    }
+}
+
+pub fn rustc_queries(input: TokenStream) -> TokenStream {
+    let groups = parse_macro_input!(input as List<Group>);
+
+    let mut query_stream = quote! {};
+    let mut query_description_stream = quote! {};
+    let mut dep_node_def_stream = quote! {};
+    let mut dep_node_force_stream = quote! {};
+
+    for group in groups.0 {
+        let mut group_stream = quote! {};
+        for mut query in group.queries.0 {
+            let modifiers = process_modifiers(&mut query);
+            let name = &query.name;
+            let arg = &query.arg;
+            let result_full = &query.result;
+            let result = match query.result {
+                ReturnType::Default => quote! { -> () },
+                _ => quote! { #result_full },
+            };
+
+            // Pass on the fatal_cycle modifier
+            let fatal_cycle = if modifiers.fatal_cycle {
+                quote! { fatal_cycle }
+            } else {
+                quote! {}
+            };
+
+            // Add the query to the group
+            group_stream.extend(quote! {
+                [#fatal_cycle] fn #name: #name(#arg) #result,
+            });
+
+            add_query_description_impl(&query, modifiers, &mut query_description_stream);
+
+            // Create a dep node for the query
+            dep_node_def_stream.extend(quote! {
+                [] #name(#arg),
+            });
+
+            // Add a match arm to force the query given the dep node
+            dep_node_force_stream.extend(quote! {
+                DepKind::#name => {
+                    if let Some(key) = RecoverKey::recover($tcx, $dep_node) {
+                        force_ex!($tcx, #name, key);
+                    } else {
+                        return false;
+                    }
+                }
+            });
+        }
+        let name = &group.name;
+        query_stream.extend(quote! {
+            #name { #group_stream },
+        });
+    }
+    TokenStream::from(quote! {
+        macro_rules! rustc_query_append {
+            ([$($macro:tt)*][$($other:tt)*]) => {
+                $($macro)* {
+                    $($other)*
+
+                    #query_stream
+
+                }
+            }
+        }
+        macro_rules! rustc_dep_node_append {
+            ([$($macro:tt)*][$($other:tt)*]) => {
+                $($macro)*(
+                    $($other)*
+
+                    #dep_node_def_stream
+                );
+            }
+        }
+        macro_rules! rustc_dep_node_force {
+            ([$dep_node:expr, $tcx:expr] $($other:tt)*) => {
+                match $dep_node.kind {
+                    $($other)*
+
+                    #dep_node_force_stream
+                }
+            }
+        }
+        #query_description_stream
+    })
+}
diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs
index b4f6839..14416b5 100644
--- a/src/librustc_metadata/lib.rs
+++ b/src/librustc_metadata/lib.rs
@@ -1,6 +1,7 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 
 #![feature(box_patterns)]
+#![feature(drain_filter)]
 #![feature(libc)]
 #![feature(nll)]
 #![feature(proc_macro_internals)]
diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs
index 2389838..314c95a 100644
--- a/src/librustc_metadata/native_libs.rs
+++ b/src/librustc_metadata/native_libs.rs
@@ -76,7 +76,7 @@
                         k => {
                             struct_span_err!(self.tcx.sess, m.span, E0458,
                                       "unknown kind: `{}`", k)
-                                .span_label(item.span, "unknown kind").emit();
+                                .span_label(item.span(), "unknown kind").emit();
                             cstore::NativeUnknown
                         }
                     };
@@ -199,34 +199,31 @@
         }
 
         // Update kind and, optionally, the name of all native libraries
-        // (there may be more than one) with the specified name.
+        // (there may be more than one) with the specified name.  If any
+        // library is mentioned more than once, keep the latest mention
+        // of it, so that any possible dependent libraries appear before
+        // it.  (This ensures that the linker is able to see symbols from
+        // all possible dependent libraries before linking in the library
+        // in question.)
         for &(ref name, ref new_name, kind) in &self.tcx.sess.opts.libs {
-            let mut found = false;
-            for lib in self.libs.iter_mut() {
-                let lib_name = match lib.name {
-                    Some(n) => n,
-                    None => continue,
-                };
-                if lib_name == name as &str {
-                    let mut changed = false;
-                    if let Some(k) = kind {
-                        lib.kind = k;
-                        changed = true;
+            // If we've already added any native libraries with the same
+            // name, they will be pulled out into `existing`, so that we
+            // can move them to the end of the list below.
+            let mut existing = self.libs.drain_filter(|lib| {
+                if let Some(lib_name) = lib.name {
+                    if lib_name == name as &str {
+                        if let Some(k) = kind {
+                            lib.kind = k;
+                        }
+                        if let &Some(ref new_name) = new_name {
+                            lib.name = Some(Symbol::intern(new_name));
+                        }
+                        return true;
                     }
-                    if let &Some(ref new_name) = new_name {
-                        lib.name = Some(Symbol::intern(new_name));
-                        changed = true;
-                    }
-                    if !changed {
-                        let msg = format!("redundant linker flag specified for \
-                                           library `{}`", name);
-                        self.tcx.sess.warn(&msg);
-                    }
-
-                    found = true;
                 }
-            }
-            if !found {
+                false
+            }).collect::<Vec<_>>();
+            if existing.is_empty() {
                 // Add if not found
                 let new_name = new_name.as_ref().map(|s| &**s); // &Option<String> -> Option<&str>
                 let lib = NativeLibrary {
@@ -237,6 +234,10 @@
                     wasm_import_module: None,
                 };
                 self.register_native_lib(None, lib);
+            } else {
+                // Move all existing libraries with the same name to the
+                // end of the command line.
+                self.libs.append(&mut existing);
             }
         }
     }
diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs
index fe07cc0..1428938 100644
--- a/src/librustc_mir/borrow_check/error_reporting.rs
+++ b/src/librustc_mir/borrow_check/error_reporting.rs
@@ -3,6 +3,7 @@
 use crate::borrow_check::prefixes::IsPrefixOf;
 use crate::borrow_check::WriteKind;
 use rustc::hir;
+use rustc::hir::def::Namespace;
 use rustc::hir::def_id::DefId;
 use rustc::middle::region::ScopeTree;
 use rustc::mir::{
@@ -12,7 +13,7 @@
     TerminatorKind, VarBindingForm,
 };
 use rustc::ty::{self, DefIdTree};
-use rustc::util::ppaux::RegionHighlightMode;
+use rustc::ty::print::Print;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::sync::Lrc;
@@ -831,7 +832,7 @@
         );
 
         if let Some(annotation) = self.annotate_argument_and_return_for_borrow(borrow) {
-            let region_name = annotation.emit(&mut err);
+            let region_name = annotation.emit(self, &mut err);
 
             err.span_label(
                 borrow_span,
@@ -1504,10 +1505,10 @@
         debug!("add_moved_or_invoked_closure_note: terminator={:?}", terminator);
         if let TerminatorKind::Call {
             func: Operand::Constant(box Constant {
-                literal: ty::LazyConst::Evaluated(ty::Const {
+                literal: ty::Const {
                     ty: &ty::TyS { sty: ty::TyKind::FnDef(id, _), ..  },
                     ..
-                }),
+                },
                 ..
             }),
             args,
@@ -1799,7 +1800,7 @@
                     // (https://github.com/rust-lang/rfcs/pull/1546)
                     bug!(
                         "End-user description not implemented for field access on `{:?}`",
-                        ty.sty
+                        ty
                     );
                 }
             }
@@ -1875,7 +1876,7 @@
     fn annotate_argument_and_return_for_borrow(
         &self,
         borrow: &BorrowData<'tcx>,
-    ) -> Option<AnnotatedBorrowFnSignature<'_>> {
+    ) -> Option<AnnotatedBorrowFnSignature<'tcx>> {
         // Define a fallback for when we can't match a closure.
         let fallback = || {
             let is_closure = self.infcx.tcx.is_closure(self.mir_def_id);
@@ -2099,7 +2100,7 @@
         &self,
         did: DefId,
         sig: ty::PolyFnSig<'tcx>,
-    ) -> Option<AnnotatedBorrowFnSignature<'_>> {
+    ) -> Option<AnnotatedBorrowFnSignature<'tcx>> {
         debug!("annotate_fn_sig: did={:?} sig={:?}", did, sig);
         let is_closure = self.infcx.tcx.is_closure(did);
         let fn_hir_id = self.infcx.tcx.hir().as_local_hir_id(did)?;
@@ -2245,7 +2246,11 @@
 impl<'tcx> AnnotatedBorrowFnSignature<'tcx> {
     /// Annotate the provided diagnostic with information about borrow from the fn signature that
     /// helps explain.
-    fn emit(&self, diag: &mut DiagnosticBuilder<'_>) -> String {
+    fn emit(
+        &self,
+        cx: &mut MirBorrowckCtxt<'_, '_, 'tcx>,
+        diag: &mut DiagnosticBuilder<'_>,
+    ) -> String {
         match self {
             AnnotatedBorrowFnSignature::Closure {
                 argument_ty,
@@ -2253,10 +2258,10 @@
             } => {
                 diag.span_label(
                     *argument_span,
-                    format!("has type `{}`", self.get_name_for_ty(argument_ty, 0)),
+                    format!("has type `{}`", cx.get_name_for_ty(argument_ty, 0)),
                 );
 
-                self.get_region_name_for_ty(argument_ty, 0)
+                cx.get_region_name_for_ty(argument_ty, 0)
             }
             AnnotatedBorrowFnSignature::AnonymousFunction {
                 argument_ty,
@@ -2264,10 +2269,10 @@
                 return_ty,
                 return_span,
             } => {
-                let argument_ty_name = self.get_name_for_ty(argument_ty, 0);
+                let argument_ty_name = cx.get_name_for_ty(argument_ty, 0);
                 diag.span_label(*argument_span, format!("has type `{}`", argument_ty_name));
 
-                let return_ty_name = self.get_name_for_ty(return_ty, 0);
+                let return_ty_name = cx.get_name_for_ty(return_ty, 0);
                 let types_equal = return_ty_name == argument_ty_name;
                 diag.span_label(
                     *return_span,
@@ -2286,7 +2291,7 @@
                      lifetime-syntax.html#lifetime-elision>",
                 );
 
-                self.get_region_name_for_ty(return_ty, 0)
+                cx.get_region_name_for_ty(return_ty, 0)
             }
             AnnotatedBorrowFnSignature::NamedFunction {
                 arguments,
@@ -2294,7 +2299,7 @@
                 return_span,
             } => {
                 // Region of return type and arguments checked to be the same earlier.
-                let region_name = self.get_region_name_for_ty(return_ty, 0);
+                let region_name = cx.get_region_name_for_ty(return_ty, 0);
                 for (_, argument_span) in arguments {
                     diag.span_label(*argument_span, format!("has lifetime `{}`", region_name));
                 }
@@ -2314,10 +2319,15 @@
             }
         }
     }
+}
 
+impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
     /// Return the name of the provided `Ty` (that must be a reference) with a synthesized lifetime
     /// name where required.
     fn get_name_for_ty(&self, ty: ty::Ty<'tcx>, counter: usize) -> String {
+        let mut s = String::new();
+        let mut printer = ty::print::FmtPrinter::new(self.infcx.tcx, &mut s, Namespace::TypeNS);
+
         // We need to add synthesized lifetimes where appropriate. We do
         // this by hooking into the pretty printer and telling it to label the
         // lifetimes without names with the value `'0`.
@@ -2327,28 +2337,37 @@
                 ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }),
                 _,
                 _,
-            ) => RegionHighlightMode::highlighting_bound_region(*br, counter, || ty.to_string()),
-            _ => ty.to_string(),
+            ) => printer.region_highlight_mode.highlighting_bound_region(*br, counter),
+            _ => {}
         }
+
+        let _ = ty.print(printer);
+        s
     }
 
     /// Returns the name of the provided `Ty` (that must be a reference)'s region with a
     /// synthesized lifetime name where required.
     fn get_region_name_for_ty(&self, ty: ty::Ty<'tcx>, counter: usize) -> String {
-        match ty.sty {
-            ty::TyKind::Ref(region, _, _) => match region {
-                ty::RegionKind::ReLateBound(_, br)
-                | ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => {
-                    RegionHighlightMode::highlighting_bound_region(
-                        *br,
-                        counter,
-                        || region.to_string(),
-                    )
+        let mut s = String::new();
+        let mut printer = ty::print::FmtPrinter::new(self.infcx.tcx, &mut s, Namespace::TypeNS);
+
+        let region = match ty.sty {
+            ty::TyKind::Ref(region, _, _) => {
+                match region {
+                    ty::RegionKind::ReLateBound(_, br)
+                    | ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => {
+                        printer.region_highlight_mode.highlighting_bound_region(*br, counter)
+                    }
+                    _ => {}
                 }
-                _ => region.to_string(),
-            },
+
+                region
+            }
             _ => bug!("ty for annotation of borrow region is not a reference"),
-        }
+        };
+
+        let _ = region.print(printer);
+        s
     }
 }
 
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 0bdf44c..c4e371d 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -68,7 +68,7 @@
 
 fn mir_borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> BorrowCheckResult<'tcx> {
     let input_mir = tcx.mir_validated(def_id);
-    debug!("run query mir_borrowck: {}", tcx.item_path_str(def_id));
+    debug!("run query mir_borrowck: {}", tcx.def_path_str(def_id));
 
     let mut return_early;
 
diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs
index 65703ad..b8dae98 100644
--- a/src/librustc_mir/borrow_check/mutability_errors.rs
+++ b/src/librustc_mir/borrow_check/mutability_errors.rs
@@ -471,13 +471,13 @@
                             Terminator {
                                 kind: TerminatorKind::Call {
                                     func: Operand::Constant(box Constant {
-                                        literal: ty::LazyConst::Evaluated(Const {
+                                        literal: Const {
                                             ty: &TyS {
                                                 sty: TyKind::FnDef(id, substs),
                                                 ..
                                             },
                                             ..
-                                        }),
+                                        },
                                         ..
                                     }),
                                     ..
diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
index 17f8c23..dfa5af4 100644
--- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
@@ -93,7 +93,7 @@
                     // simplify output by reporting just the ADT name.
                     ty::Adt(adt, _substs) if adt.has_dtor(tcx) && !adt.is_box() => (
                         "`Drop` code",
-                        format!("type `{}`", tcx.item_path_str(adt.did)),
+                        format!("type `{}`", tcx.def_path_str(adt.did)),
                     ),
 
                     // Otherwise, just report the whole type (and use
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 fdede05..362214d 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
@@ -8,7 +8,7 @@
 use rustc::mir::Mir;
 use rustc::ty::subst::{SubstsRef, UnpackedKind};
 use rustc::ty::{self, RegionKind, RegionVid, Ty, TyCtxt};
-use rustc::util::ppaux::RegionHighlightMode;
+use rustc::ty::print::RegionHighlightMode;
 use rustc_errors::DiagnosticBuilder;
 use syntax::ast::Name;
 use syntax::symbol::keywords;
@@ -396,9 +396,9 @@
         argument_ty: Ty<'tcx>,
         counter: &mut usize,
     ) -> Option<RegionName> {
-        let type_name = RegionHighlightMode::highlighting_region_vid(needle_fr, *counter, || {
-            infcx.extract_type_name(&argument_ty)
-        });
+        let mut highlight = RegionHighlightMode::default();
+        highlight.highlighting_region_vid(needle_fr, *counter);
+        let type_name = infcx.extract_type_name(&argument_ty, Some(highlight));
 
         debug!(
             "give_name_if_we_cannot_match_hir_ty: type_name={:?} needle_fr={:?}",
@@ -680,9 +680,9 @@
             return None;
         }
 
-        let type_name = RegionHighlightMode::highlighting_region_vid(
-            fr, *counter, || infcx.extract_type_name(&return_ty),
-        );
+        let mut highlight = RegionHighlightMode::default();
+        highlight.highlighting_region_vid(fr, *counter);
+        let type_name = infcx.extract_type_name(&return_ty, Some(highlight));
 
         let mir_node_id = tcx.hir().as_local_node_id(mir_def_id).expect("non-local mir");
 
diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs
index 0a0a88e..58e567c 100644
--- a/src/librustc_mir/borrow_check/nll/renumber.rs
+++ b/src/librustc_mir/borrow_check/nll/renumber.rs
@@ -80,7 +80,7 @@
         debug!("visit_region: region={:?}", region);
     }
 
-    fn visit_const(&mut self, constant: &mut &'tcx ty::LazyConst<'tcx>, _location: Location) {
+    fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, _location: Location) {
         *constant = self.renumber_regions(&*constant);
     }
 
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 5b444ab..25a3160 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -28,7 +28,7 @@
 use rustc::infer::outlives::env::RegionBoundPairs;
 use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin};
 use rustc::infer::type_variable::TypeVariableOrigin;
-use rustc::mir::interpret::EvalErrorKind::BoundsCheck;
+use rustc::mir::interpret::{EvalErrorKind::BoundsCheck, ConstValue};
 use rustc::mir::tcx::PlaceTy;
 use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext, NonMutatingUseContext};
 use rustc::mir::*;
@@ -296,37 +296,33 @@
                 );
             }
         } else {
-            match *constant.literal {
-                ty::LazyConst::Unevaluated(def_id, substs) => {
-                    if let Err(terr) = self.cx.fully_perform_op(
-                        location.to_locations(),
-                        ConstraintCategory::Boring,
-                        self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
-                            constant.ty, def_id, UserSubsts { substs, user_self_ty: None },
-                        )),
-                    ) {
-                        span_mirbug!(
-                            self,
-                            constant,
-                            "bad constant type {:?} ({:?})",
-                            constant,
-                            terr
-                        );
-                    }
+            if let ConstValue::Unevaluated(def_id, substs) = constant.literal.val {
+                if let Err(terr) = self.cx.fully_perform_op(
+                    location.to_locations(),
+                    ConstraintCategory::Boring,
+                    self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
+                        constant.ty, def_id, UserSubsts { substs, user_self_ty: None },
+                    )),
+                ) {
+                    span_mirbug!(
+                        self,
+                        constant,
+                        "bad constant type {:?} ({:?})",
+                        constant,
+                        terr
+                    );
                 }
-                ty::LazyConst::Evaluated(lit) => {
-                    if let ty::FnDef(def_id, substs) = lit.ty.sty {
-                        let tcx = self.tcx();
+            }
+            if let ty::FnDef(def_id, substs) = constant.literal.ty.sty {
+                let tcx = self.tcx();
 
-                        let instantiated_predicates = tcx
-                            .predicates_of(def_id)
-                            .instantiate(tcx, substs);
-                        self.cx.normalize_and_prove_instantiated_predicates(
-                            instantiated_predicates,
-                            location.to_locations(),
-                        );
-                    }
-                }
+                let instantiated_predicates = tcx
+                    .predicates_of(def_id)
+                    .instantiate(tcx, substs);
+                self.cx.normalize_and_prove_instantiated_predicates(
+                    instantiated_predicates,
+                    location.to_locations(),
+                );
             }
         }
     }
@@ -418,10 +414,11 @@
             constant, location
         );
 
-        let literal = match constant.literal {
-            ty::LazyConst::Evaluated(lit) => lit,
-            ty::LazyConst::Unevaluated(..) => return,
-        };
+        let literal = constant.literal;
+
+        if let ConstValue::Unevaluated(..) = literal.val {
+            return;
+        }
 
         debug!("sanitize_constant: expected_ty={:?}", literal.ty);
 
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index f1a82ec..9e12a7e 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -275,13 +275,13 @@
                             span: expr_span,
                             ty: this.hir.tcx().types.u32,
                             user_ty: None,
-                            literal: this.hir.tcx().mk_lazy_const(ty::LazyConst::Evaluated(
+                            literal: this.hir.tcx().mk_const(
                                 ty::Const::from_bits(
                                     this.hir.tcx(),
                                     0,
                                     ty::ParamEnv::empty().and(this.hir.tcx().types.u32),
                                 ),
-                            )),
+                            ),
                         }));
                         box AggregateKind::Generator(closure_id, substs, movability)
                     }
diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs
index d60a094..77978d7 100644
--- a/src/librustc_mir/build/matches/simplify.rs
+++ b/src/librustc_mir/build/matches/simplify.rs
@@ -114,14 +114,12 @@
                         (Some(('\u{0000}' as u128, '\u{10FFFF}' as u128, Size::from_bits(32))), 0)
                     }
                     ty::Int(ity) => {
-                        // FIXME(49937): refactor these bit manipulations into interpret.
                         let size = Integer::from_attr(&tcx, SignedInt(ity)).size();
                         let max = truncate(u128::max_value(), size);
                         let bias = 1u128 << (size.bits() - 1);
                         (Some((0, max, size)), bias)
                     }
                     ty::Uint(uty) => {
-                        // FIXME(49937): refactor these bit manipulations into interpret.
                         let size = Integer::from_attr(&tcx, UnsignedInt(uty)).size();
                         let max = truncate(u128::max_value(), size);
                         (Some((0, max, size)), 0)
diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs
index 72b9244..0c93984 100644
--- a/src/librustc_mir/build/matches/test.rs
+++ b/src/librustc_mir/build/matches/test.rs
@@ -299,7 +299,7 @@
                     }
                     let eq_def_id = self.hir.tcx().lang_items().eq_trait().unwrap();
                     let (mty, method) = self.hir.trait_method(eq_def_id, "eq", ty, &[ty.into()]);
-                    let method = self.hir.tcx().mk_lazy_const(ty::LazyConst::Evaluated(method));
+                    let method = self.hir.tcx().mk_const(method);
 
                     let re_erased = self.hir.tcx().types.re_erased;
                     // take the argument by reference
diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir/build/misc.rs
index 2692c24..d76d376 100644
--- a/src/librustc_mir/build/misc.rs
+++ b/src/librustc_mir/build/misc.rs
@@ -33,7 +33,7 @@
             span,
             ty,
             user_ty: None,
-            literal: self.hir.tcx().mk_lazy_const(ty::LazyConst::Evaluated(literal)),
+            literal: self.hir.tcx().mk_const(literal),
         };
         Operand::Constant(constant)
     }
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index c8e48de..ec8c62b 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -201,7 +201,7 @@
         }
     }
 
-    fn visit_const(&mut self, constant: &mut &'tcx ty::LazyConst<'tcx>, _: Location) {
+    fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, _: Location) {
         if let Some(lifted) = self.tcx.lift(constant) {
             *constant = lifted;
         } else {
diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs
index 365cb50..79a3e0c 100644
--- a/src/librustc_mir/const_eval.rs
+++ b/src/librustc_mir/const_eval.rs
@@ -65,12 +65,12 @@
 fn mplace_to_const<'tcx>(
     ecx: &CompileTimeEvalContext<'_, '_, 'tcx>,
     mplace: MPlaceTy<'tcx>,
-) -> EvalResult<'tcx, ty::Const<'tcx>> {
+) -> ty::Const<'tcx> {
     let MemPlace { ptr, align, meta } = *mplace;
     // extract alloc-offset pair
     assert!(meta.is_none());
-    let ptr = ptr.to_ptr()?;
-    let alloc = ecx.memory.get(ptr.alloc_id)?;
+    let ptr = ptr.to_ptr().unwrap();
+    let alloc = ecx.memory.get(ptr.alloc_id).unwrap();
     assert!(alloc.align >= align);
     assert!(alloc.bytes.len() as u64 - ptr.offset.bytes() >= mplace.layout.size.bytes());
     let mut alloc = alloc.clone();
@@ -79,16 +79,16 @@
     // interned this?  I thought that is the entire point of that `FinishStatic` stuff?
     let alloc = ecx.tcx.intern_const_alloc(alloc);
     let val = ConstValue::ByRef(ptr, alloc);
-    Ok(ty::Const { val, ty: mplace.layout.ty })
+    ty::Const { val, ty: mplace.layout.ty }
 }
 
 fn op_to_const<'tcx>(
     ecx: &CompileTimeEvalContext<'_, '_, 'tcx>,
     op: OpTy<'tcx>,
-) -> EvalResult<'tcx, ty::Const<'tcx>> {
-    // We do not normalize just any data.  Only scalar layout and slices.
+) -> ty::Const<'tcx> {
+    // We do not normalize just any data.  Only non-union scalars and slices.
     let normalize = match op.layout.abi {
-        layout::Abi::Scalar(..) => true,
+        layout::Abi::Scalar(..) => op.layout.ty.ty_adt_def().map_or(true, |adt| !adt.is_union()),
         layout::Abi::ScalarPair(..) => op.layout.ty.is_slice(),
         _ => false,
     };
@@ -100,11 +100,11 @@
     let val = match normalized_op {
         Ok(mplace) => return mplace_to_const(ecx, mplace),
         Err(Immediate::Scalar(x)) =>
-            ConstValue::Scalar(x.not_undef()?),
+            ConstValue::Scalar(x.not_undef().unwrap()),
         Err(Immediate::ScalarPair(a, b)) =>
-            ConstValue::Slice(a.not_undef()?, b.to_usize(ecx)?),
+            ConstValue::Slice(a.not_undef().unwrap(), b.to_usize(ecx).unwrap()),
     };
-    Ok(ty::Const { val, ty: op.layout.ty })
+    ty::Const { val, ty: op.layout.ty }
 }
 
 fn eval_body_and_ecx<'a, 'mir, 'tcx>(
@@ -142,7 +142,7 @@
     assert!(!layout.is_unsized());
     let ret = ecx.allocate(layout, MemoryKind::Stack);
 
-    let name = ty::tls::with(|tcx| tcx.item_path_str(cid.instance.def_id()));
+    let name = ty::tls::with(|tcx| tcx.def_path_str(cid.instance.def_id()));
     let prom = cid.promoted.map_or(String::new(), |p| format!("::promoted[{:?}]", p));
     trace!("eval_body_using_ecx: pushing stack frame for global: {}{}", name, prom);
     assert!(mir.arg_count == 0);
@@ -478,7 +478,7 @@
     trace!("const_field: {:?}, {:?}", field, value);
     let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
     // get the operand again
-    let op = ecx.const_to_op(value, None).unwrap();
+    let op = ecx.eval_const_to_op(value, None).unwrap();
     // downcast
     let down = match variant {
         None => op,
@@ -488,7 +488,7 @@
     let field = ecx.operand_field(down, field.index() as u64).unwrap();
     // and finally move back to the const world, always normalizing because
     // this is not called for statics.
-    op_to_const(&ecx, field).unwrap()
+    op_to_const(&ecx, field)
 }
 
 // this function uses `unwrap` copiously, because an already validated constant must have valid
@@ -500,7 +500,7 @@
 ) -> VariantIdx {
     trace!("const_variant_index: {:?}", val);
     let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
-    let op = ecx.const_to_op(val, None).unwrap();
+    let op = ecx.eval_const_to_op(val, None).unwrap();
     ecx.read_discriminant(op).unwrap().1
 }
 
@@ -534,9 +534,9 @@
         // Now that we validated, turn this into a proper constant.
         let def_id = cid.instance.def.def_id();
         if tcx.is_static(def_id).is_some() || cid.promoted.is_some() {
-            mplace_to_const(&ecx, mplace)
+            Ok(mplace_to_const(&ecx, mplace))
         } else {
-            op_to_const(&ecx, mplace.into())
+            Ok(op_to_const(&ecx, mplace.into()))
         }
     })();
 
@@ -602,14 +602,15 @@
             other => return other,
         }
     }
-    // the first trace is for replicating an ice
-    // There's no tracking issue, but the next two lines concatenated link to the discussion on
-    // zulip. It's not really possible to test this, because it doesn't show up in diagnostics
-    // or MIR.
-    // https://rust-lang.zulipchat.com/#narrow/stream/146212-t-compiler.2Fconst-eval/
-    // subject/anon_const_instance_printing/near/135980032
-    trace!("const eval: {}", key.value.instance);
-    trace!("const eval: {:?}", key);
+    if cfg!(debug_assertions) {
+        // Make sure we format the instance even if we do not print it.
+        // This serves as a regression test against an ICE on printing.
+        // The next two lines concatenated contain some discussion:
+        // https://rust-lang.zulipchat.com/#narrow/stream/146212-t-compiler.2Fconst-eval/
+        // subject/anon_const_instance_printing/near/135980032
+        let instance = key.value.instance.to_string();
+        trace!("const eval: {:?} ({})", key, instance);
+    }
 
     let cid = key.value;
     let def_id = cid.instance.def.def_id();
diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs
index 03f8ac6..af2cd8f 100644
--- a/src/librustc_mir/dataflow/mod.rs
+++ b/src/librustc_mir/dataflow/mod.rs
@@ -146,7 +146,7 @@
                 } else {
                     sess.span_err(
                         item.span,
-                        &format!("{} attribute requires a path", item.ident));
+                        &format!("{} attribute requires a path", item.path));
                     return None;
                 }
             }
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index 7749b3a..b83f048 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -342,9 +342,9 @@
         }
 
         hir::ExprKind::Lit(ref lit) => ExprKind::Literal {
-            literal: cx.tcx.mk_lazy_const(ty::LazyConst::Evaluated(
+            literal: cx.tcx.mk_const(
                 cx.const_eval_literal(&lit.node, expr_ty, lit.span, false)
-            )),
+            ),
             user_ty: None,
         },
 
@@ -442,9 +442,9 @@
             } else {
                 if let hir::ExprKind::Lit(ref lit) = arg.node {
                     ExprKind::Literal {
-                        literal: cx.tcx.mk_lazy_const(ty::LazyConst::Evaluated(
+                        literal: cx.tcx.mk_const(
                             cx.const_eval_literal(&lit.node, expr_ty, lit.span, true)
-                        )),
+                        ),
                         user_ty: None,
                     }
                 } else {
@@ -693,26 +693,29 @@
                 };
 
                 let source = if let Some((did, offset, var_ty)) = var {
-                    let mk_lazy_const = |literal| Expr {
+                    let mk_const = |literal| Expr {
                         temp_lifetime,
                         ty: var_ty,
                         span: expr.span,
                         kind: ExprKind::Literal {
-                            literal: cx.tcx.mk_lazy_const(literal),
+                            literal: cx.tcx.mk_const(literal),
                             user_ty: None
                         },
                     }.to_ref();
-                    let offset = mk_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_bits(
+                    let offset = mk_const(ty::Const::from_bits(
                         cx.tcx,
                         offset as u128,
                         cx.param_env.and(var_ty),
-                    )));
+                    ));
                     match did {
                         Some(did) => {
                             // in case we are offsetting from a computed discriminant
                             // and not the beginning of discriminants (which is always `0`)
                             let substs = InternalSubsts::identity_for_item(cx.tcx(), did);
-                            let lhs = mk_lazy_const(ty::LazyConst::Unevaluated(did, substs));
+                            let lhs = mk_const(ty::Const {
+                                val: ConstValue::Unevaluated(did, substs),
+                                ty: var_ty,
+                            });
                             let bin = ExprKind::Binary {
                                 op: BinOp::Add,
                                 lhs,
@@ -852,9 +855,9 @@
         ty,
         span,
         kind: ExprKind::Literal {
-            literal: cx.tcx().mk_lazy_const(ty::LazyConst::Evaluated(
+            literal: cx.tcx().mk_const(
                 ty::Const::zero_sized(ty)
-            )),
+            ),
             user_ty,
         },
     }
@@ -914,9 +917,9 @@
             let user_ty = user_substs_applied_to_def(cx, expr.hir_id, &def);
             debug!("convert_path_expr: user_ty={:?}", user_ty);
             ExprKind::Literal {
-                literal: cx.tcx.mk_lazy_const(ty::LazyConst::Evaluated(ty::Const::zero_sized(
+                literal: cx.tcx.mk_const(ty::Const::zero_sized(
                     cx.tables().node_type(expr.hir_id),
-                ))),
+                )),
                 user_ty,
             }
         }
@@ -930,11 +933,11 @@
             let name = cx.tcx.hir().name(node_id).as_interned_str();
             let val = ConstValue::Param(ty::ParamConst::new(index, name));
             ExprKind::Literal {
-                literal: cx.tcx.mk_lazy_const(
-                    ty::LazyConst::Evaluated(ty::Const {
+                literal: cx.tcx.mk_const(
+                    ty::Const {
                         val,
                         ty: cx.tables().node_type(expr.hir_id),
-                    })
+                    }
                 ),
                 user_ty: None,
             }
@@ -945,7 +948,10 @@
             let user_ty = user_substs_applied_to_def(cx, expr.hir_id, &def);
             debug!("convert_path_expr: (const) user_ty={:?}", user_ty);
             ExprKind::Literal {
-                literal: cx.tcx.mk_lazy_const(ty::LazyConst::Unevaluated(def_id, substs)),
+                literal: cx.tcx.mk_const(ty::Const {
+                    val: ConstValue::Unevaluated(def_id, substs),
+                    ty: cx.tcx.type_of(def_id),
+                }),
                 user_ty,
             }
         },
@@ -955,7 +961,8 @@
             let user_provided_types = cx.tables.user_provided_types();
             let user_provided_type = user_provided_types.get(expr.hir_id).map(|u_ty| *u_ty);
             debug!("convert_path_expr: user_provided_type={:?}", user_provided_type);
-            match cx.tables().node_type(expr.hir_id).sty {
+            let ty = cx.tables().node_type(expr.hir_id);
+            match ty.sty {
                 // A unit struct/variant which is used as a value.
                 // We return a completely different ExprKind here to account for this special case.
                 ty::Adt(adt_def, substs) => {
@@ -968,7 +975,7 @@
                         base: None,
                     }
                 }
-                ref sty => bug!("unexpected sty: {:?}", sty),
+                _ => bug!("unexpected ty: {:?}", ty),
             }
         }
 
diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs
index c0f3989..71c6489 100644
--- a/src/librustc_mir/hair/cx/mod.rs
+++ b/src/librustc_mir/hair/cx/mod.rs
@@ -106,8 +106,8 @@
         self.tcx.types.usize
     }
 
-    pub fn usize_literal(&mut self, value: u64) -> &'tcx ty::LazyConst<'tcx> {
-        self.tcx.mk_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_usize(self.tcx, value)))
+    pub fn usize_literal(&mut self, value: u64) -> &'tcx ty::Const<'tcx> {
+        self.tcx.mk_const(ty::Const::from_usize(self.tcx, value))
     }
 
     pub fn bool_ty(&mut self) -> Ty<'tcx> {
@@ -118,12 +118,12 @@
         self.tcx.mk_unit()
     }
 
-    pub fn true_literal(&mut self) -> &'tcx ty::LazyConst<'tcx> {
-        self.tcx.mk_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_bool(self.tcx, true)))
+    pub fn true_literal(&mut self) -> &'tcx ty::Const<'tcx> {
+        self.tcx.mk_const(ty::Const::from_bool(self.tcx, true))
     }
 
-    pub fn false_literal(&mut self) -> &'tcx ty::LazyConst<'tcx> {
-        self.tcx.mk_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_bool(self.tcx, false)))
+    pub fn false_literal(&mut self) -> &'tcx ty::Const<'tcx> {
+        self.tcx.mk_const(ty::Const::from_bool(self.tcx, false))
     }
 
     pub fn const_eval_literal(
diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs
index 385249e..3a38876 100644
--- a/src/librustc_mir/hair/mod.rs
+++ b/src/librustc_mir/hair/mod.rs
@@ -9,7 +9,7 @@
 use rustc::infer::canonical::Canonical;
 use rustc::middle::region;
 use rustc::ty::subst::SubstsRef;
-use rustc::ty::{AdtDef, UpvarSubsts, Ty, Const, LazyConst, UserType};
+use rustc::ty::{AdtDef, UpvarSubsts, Ty, Const, UserType};
 use rustc::ty::layout::VariantIdx;
 use rustc::hir;
 use syntax_pos::Span;
@@ -289,7 +289,7 @@
         movability: Option<hir::GeneratorMovability>,
     },
     Literal {
-        literal: &'tcx LazyConst<'tcx>,
+        literal: &'tcx Const<'tcx>,
         user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
     },
     InlineAsm {
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs
index 586a3fd..88d1eb2 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir/hair/pattern/_match.rs
@@ -172,7 +172,7 @@
 use rustc::ty::layout::{Integer, IntegerExt, VariantIdx, Size};
 
 use rustc::mir::Field;
-use rustc::mir::interpret::{ConstValue, Scalar};
+use rustc::mir::interpret::{ConstValue, Scalar, truncate};
 use rustc::util::common::ErrorReported;
 
 use syntax::attr::{SignedInt, UnsignedInt};
@@ -222,7 +222,7 @@
                 assert_eq!(t, u);
                 ConstValue::Slice(
                     Scalar::Ptr(p),
-                    n.map_evaluated(|val| val.val.try_to_scalar())
+                    n.val.try_to_scalar()
                         .unwrap()
                         .to_usize(&self.tcx)
                         .unwrap(),
@@ -678,16 +678,14 @@
             ]
         }
         ty::Int(ity) => {
-            // FIXME(49937): refactor these bit manipulations into interpret.
             let bits = Integer::from_attr(&cx.tcx, SignedInt(ity)).size().bits() as u128;
             let min = 1u128 << (bits - 1);
-            let max = (1u128 << (bits - 1)) - 1;
+            let max = min - 1;
             vec![ConstantRange(min, max, pcx.ty, RangeEnd::Included)]
         }
         ty::Uint(uty) => {
-            // FIXME(49937): refactor these bit manipulations into interpret.
-            let bits = Integer::from_attr(&cx.tcx, UnsignedInt(uty)).size().bits() as u128;
-            let max = !0u128 >> (128 - bits);
+            let size = Integer::from_attr(&cx.tcx, UnsignedInt(uty)).size();
+            let max = truncate(u128::max_value(), size);
             vec![ConstantRange(0, max, pcx.ty, RangeEnd::Included)]
         }
         _ => {
diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs
index 41babc1..49967df 100644
--- a/src/librustc_mir/hair/pattern/check_match.rs
+++ b/src/librustc_mir/hair/pattern/check_match.rs
@@ -319,7 +319,7 @@
                     if edef.is_enum() && edef.variants.iter().any(|variant| {
                         variant.ident == ident && variant.ctor_kind == CtorKind::Const
                     }) {
-                        let ty_path = cx.tcx.item_path_str(edef.did);
+                        let ty_path = cx.tcx.def_path_str(edef.did);
                         let mut err = struct_span_warn!(cx.tcx.sess, p.span, E0170,
                             "pattern binding `{}` is named the same as one \
                             of the variants of the type `{}`",
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs
index 67d4019..8614be8 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir/hair/pattern/mod.rs
@@ -13,7 +13,7 @@
 use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
 use rustc::mir::{UserTypeProjection};
 use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
-use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, Lift, UserType};
+use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, UserType, DefIdTree};
 use rustc::ty::{CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations};
 use rustc::ty::subst::{SubstsRef, Kind};
 use rustc::ty::layout::VariantIdx;
@@ -529,11 +529,11 @@
                     ty::Error => { // Avoid ICE
                         return Pattern { span: pat.span, ty, kind: Box::new(PatternKind::Wild) };
                     }
-                    ref sty =>
+                    _ =>
                         span_bug!(
                             pat.span,
                             "unexpanded type for vector pattern: {:?}",
-                            sty),
+                            ty),
                 }
             }
 
@@ -554,7 +554,7 @@
                     ty::Error => { // Avoid ICE (#50577)
                         return Pattern { span: pat.span, ty, kind: Box::new(PatternKind::Wild) };
                     }
-                    ref sty => span_bug!(pat.span, "unexpected type for tuple pattern: {:?}", sty),
+                    _ => span_bug!(pat.span, "unexpected type for tuple pattern: {:?}", ty),
                 }
             }
 
@@ -608,7 +608,7 @@
                     }
                     _ => span_bug!(pat.span,
                                    "tuple struct pattern not applied to an ADT {:?}",
-                                   ty.sty),
+                                   ty),
                 };
                 let variant_def = adt_def.variant_of_def(def);
 
@@ -735,7 +735,7 @@
     ) -> PatternKind<'tcx> {
         let mut kind = match def {
             Def::Variant(variant_id) | Def::VariantCtor(variant_id, ..) => {
-                let enum_id = self.tcx.parent_def_id(variant_id).unwrap();
+                let enum_id = self.tcx.parent(variant_id).unwrap();
                 let adt_def = self.tcx.adt_def(enum_id);
                 if adt_def.is_enum() {
                     let substs = match ty.sty {
@@ -744,7 +744,7 @@
                         ty::Error => {  // Avoid ICE (#50585)
                             return PatternKind::Wild;
                         }
-                        _ => bug!("inappropriate type for def: {:?}", ty.sty),
+                        _ => bug!("inappropriate type for def: {:?}", ty),
                     };
                     PatternKind::Variant {
                         adt_def,
@@ -969,8 +969,8 @@
             ty::Adt(adt_def, _) if !self.tcx.has_attr(adt_def.did, "structural_match") => {
                 let msg = format!("to use a constant of type `{}` in a pattern, \
                                     `{}` must be annotated with `#[derive(PartialEq, Eq)]`",
-                                    self.tcx.item_path_str(adt_def.did),
-                                    self.tcx.item_path_str(adt_def.did));
+                                    self.tcx.def_path_str(adt_def.did),
+                                    self.tcx.def_path_str(adt_def.did));
                 self.tcx.sess.span_err(span, &msg);
                 PatternKind::Wild
             }
@@ -1233,9 +1233,6 @@
         return fallback();
     }
 
-    let tcx = tcx.global_tcx();
-    let (a, b, ty) = (a, b, ty).lift_to_tcx(tcx).unwrap();
-
     // FIXME: This should use assert_bits(ty) instead of use_bits
     // but triggers possibly bugs due to mismatching of arrays and slices
     if let (Some(a), Some(b)) = (a.to_bits(tcx, ty), b.to_bits(tcx, ty)) {
@@ -1251,11 +1248,12 @@
                 let r = ::rustc_apfloat::ieee::Double::from_bits(b);
                 l.partial_cmp(&r)
             }
-            ty::Int(_) => {
-                let layout = tcx.layout_of(ty).ok()?;
-                assert!(layout.abi.is_signed());
-                let a = sign_extend(a, layout.size);
-                let b = sign_extend(b, layout.size);
+            ty::Int(ity) => {
+                use rustc::ty::layout::{Integer, IntegerExt};
+                use syntax::attr::SignedInt;
+                let size = Integer::from_attr(&tcx, SignedInt(ity)).size();
+                let a = sign_extend(a, size);
+                let b = sign_extend(b, size);
                 Some((a as i128).cmp(&(b as i128)))
             }
             _ => Some(a.cmp(&b)),
diff --git a/src/librustc_mir/hair/util.rs b/src/librustc_mir/hair/util.rs
index 4618cd4..c9dae69 100644
--- a/src/librustc_mir/hair/util.rs
+++ b/src/librustc_mir/hair/util.rs
@@ -16,7 +16,8 @@
         let user_provided_types = self.tables().user_provided_types();
         let mut user_ty = *user_provided_types.get(hir_id)?;
         debug!("user_subts_applied_to_ty_of_hir_id: user_ty={:?}", user_ty);
-        match &self.tables().node_type(hir_id).sty {
+        let ty = self.tables().node_type(hir_id);
+        match ty.sty {
             ty::Adt(adt_def, ..) => {
                 if let UserType::TypeOf(ref mut did, _) = &mut user_ty.value {
                     *did = adt_def.did;
@@ -24,8 +25,11 @@
                 Some(user_ty)
             }
             ty::FnDef(..) => Some(user_ty),
-            sty =>
-                bug!("sty: {:?} should not have user provided type {:?} recorded ", sty, user_ty),
+            _ => bug!(
+                "ty: {:?} should not have user provided type {:?} recorded ",
+                ty,
+                user_ty
+            ),
         }
     }
 }
diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs
index 73c73cc..7543dd6 100644
--- a/src/librustc_mir/interpret/cast.rs
+++ b/src/librustc_mir/interpret/cast.rs
@@ -90,7 +90,7 @@
                         let fn_ptr = self.memory.create_fn_alloc(instance?).with_default_tag();
                         self.write_scalar(Scalar::Ptr(fn_ptr.into()), dest)?;
                     }
-                    ref other => bug!("reify fn pointer on {:?}", other),
+                    _ => bug!("reify fn pointer on {:?}", src.layout.ty),
                 }
             }
 
@@ -101,7 +101,7 @@
                         // No change to value
                         self.write_immediate(*src, dest)?;
                     }
-                    ref other => bug!("fn to unsafe fn cast on {:?}", other),
+                    _ => bug!("fn to unsafe fn cast on {:?}", dest.layout.ty),
                 }
             }
 
@@ -120,7 +120,7 @@
                         let val = Immediate::Scalar(Scalar::Ptr(fn_ptr.into()).into());
                         self.write_immediate(val, dest)?;
                     }
-                    ref other => bug!("closure fn pointer on {:?}", other),
+                    _ => bug!("closure fn pointer on {:?}", src.layout.ty),
                 }
             }
         }
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 8a32c3b..e81d0a5 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -283,7 +283,7 @@
             ty::InstanceDef::Item(def_id) => if self.tcx.is_mir_available(did) {
                 Ok(self.tcx.optimized_mir(did))
             } else {
-                err!(NoMirFor(self.tcx.item_path_str(def_id)))
+                err!(NoMirFor(self.tcx.def_path_str(def_id)))
             },
             _ => Ok(self.tcx.instance_mir(instance)),
         }
@@ -450,7 +450,7 @@
         return_place: Option<PlaceTy<'tcx, M::PointerTag>>,
         return_to_block: StackPopCleanup,
     ) -> EvalResult<'tcx> {
-        if self.stack.len() > 1 { // FIXME should be "> 0", printing topmost frame crashes rustc...
+        if self.stack.len() > 0 {
             info!("PAUSING({}) {}", self.cur_frame(), self.frame().instance);
         }
         ::log_settings::settings().indentation += 1;
@@ -525,9 +525,7 @@
             self.frame_mut().locals = locals;
         }
 
-        if self.stack.len() > 1 { // FIXME no check should be needed, but some instances ICE
-            info!("ENTERING({}) {}", self.cur_frame(), self.frame().instance);
-        }
+        info!("ENTERING({}) {}", self.cur_frame(), self.frame().instance);
 
         if self.stack.len() > self.tcx.sess.const_eval_stack_frame_limit {
             err!(StackFrameLimitReached)
@@ -537,9 +535,7 @@
     }
 
     pub(super) fn pop_stack_frame(&mut self) -> EvalResult<'tcx> {
-        if self.stack.len() > 1 { // FIXME no check should be needed, but some instances ICE
-            info!("LEAVING({}) {}", self.cur_frame(), self.frame().instance);
-        }
+        info!("LEAVING({}) {}", self.cur_frame(), self.frame().instance);
         ::log_settings::settings().indentation -= 1;
         let frame = self.stack.pop().expect(
             "tried to pop a stack frame, but there were none",
@@ -591,7 +587,7 @@
             StackPopCleanup::None { .. } => {}
         }
 
-        if self.stack.len() > 1 { // FIXME should be "> 0", printing topmost frame crashes rustc...
+        if self.stack.len() > 0 {
             info!("CONTINUING({}) {}", self.cur_frame(), self.frame().instance);
         }
 
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index 88b936a..6ea200d 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -700,24 +700,29 @@
         // relocations overlapping the edges; those would not be handled correctly).
         let relocations = {
             let relocations = self.get(src.alloc_id)?.relocations(self, src, size);
-            let mut new_relocations = Vec::with_capacity(relocations.len() * (length as usize));
-            for i in 0..length {
-                new_relocations.extend(
-                    relocations
-                    .iter()
-                    .map(|&(offset, reloc)| {
-                        // compute offset for current repetition
-                        let dest_offset = dest.offset + (i * size);
-                        (
-                            // shift offsets from source allocation to destination allocation
-                            offset + dest_offset - src.offset,
-                            reloc,
-                        )
-                    })
-                );
-            }
+            if relocations.is_empty() {
+                // nothing to copy, ignore even the `length` loop
+                Vec::new()
+            } else {
+                let mut new_relocations = Vec::with_capacity(relocations.len() * (length as usize));
+                for i in 0..length {
+                    new_relocations.extend(
+                        relocations
+                        .iter()
+                        .map(|&(offset, reloc)| {
+                            // compute offset for current repetition
+                            let dest_offset = dest.offset + (i * size);
+                            (
+                                // shift offsets from source allocation to destination allocation
+                                offset + dest_offset - src.offset,
+                                reloc,
+                            )
+                        })
+                    );
+                }
 
-            new_relocations
+                new_relocations
+            }
         };
 
         let tcx = self.tcx.tcx;
@@ -784,20 +789,65 @@
         // The bits have to be saved locally before writing to dest in case src and dest overlap.
         assert_eq!(size.bytes() as usize as u64, size.bytes());
 
-        let undef_mask = self.get(src.alloc_id)?.undef_mask.clone();
-        let dest_allocation = self.get_mut(dest.alloc_id)?;
+        let undef_mask = &self.get(src.alloc_id)?.undef_mask;
 
-        for i in 0..size.bytes() {
-            let defined = undef_mask.get(src.offset + Size::from_bytes(i));
+        // Since we are copying `size` bytes from `src` to `dest + i * size` (`for i in 0..repeat`),
+        // a naive undef mask copying algorithm would repeatedly have to read the undef mask from
+        // the source and write it to the destination. Even if we optimized the memory accesses,
+        // we'd be doing all of this `repeat` times.
+        // Therefor we precompute a compressed version of the undef mask of the source value and
+        // then write it back `repeat` times without computing any more information from the source.
 
-            for j in 0..repeat {
-                dest_allocation.undef_mask.set(
-                    dest.offset + Size::from_bytes(i + (size.bytes() * j)),
-                    defined
-                );
+        // a precomputed cache for ranges of defined/undefined bits
+        // 0000010010001110 will become
+        // [5, 1, 2, 1, 3, 3, 1]
+        // where each element toggles the state
+        let mut ranges = smallvec::SmallVec::<[u64; 1]>::new();
+        let first = undef_mask.get(src.offset);
+        let mut cur_len = 1;
+        let mut cur = first;
+        for i in 1..size.bytes() {
+            // FIXME: optimize to bitshift the current undef block's bits and read the top bit
+            if undef_mask.get(src.offset + Size::from_bytes(i)) == cur {
+                cur_len += 1;
+            } else {
+                ranges.push(cur_len);
+                cur_len = 1;
+                cur = !cur;
             }
         }
 
+        // now fill in all the data
+        let dest_allocation = self.get_mut(dest.alloc_id)?;
+        // an optimization where we can just overwrite an entire range of definedness bits if
+        // they are going to be uniformly `1` or `0`.
+        if ranges.is_empty() {
+            dest_allocation.undef_mask.set_range_inbounds(
+                dest.offset,
+                dest.offset + size * repeat,
+                first,
+            );
+            return Ok(())
+        }
+
+        // remember to fill in the trailing bits
+        ranges.push(cur_len);
+
+        for mut j in 0..repeat {
+            j *= size.bytes();
+            j += dest.offset.bytes();
+            let mut cur = first;
+            for range in &ranges {
+                let old_j = j;
+                j += range;
+                dest_allocation.undef_mask.set_range_inbounds(
+                    Size::from_bytes(old_j),
+                    Size::from_bytes(j),
+                    cur,
+                );
+                cur = !cur;
+            }
+        }
         Ok(())
     }
 }
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index 206eaaf..7051107 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -547,7 +547,7 @@
             Move(ref place) =>
                 self.eval_place_to_op(place, layout)?,
 
-            Constant(ref constant) => self.eval_lazy_const_to_op(*constant.literal, layout)?,
+            Constant(ref constant) => self.eval_const_to_op(*constant.literal, layout)?,
         };
         trace!("{:?}: {:?}", mir_op, *op);
         Ok(op)
@@ -563,36 +563,13 @@
             .collect()
     }
 
-    // Used when Miri runs into a constant, and by const propagation.
-    crate fn eval_lazy_const_to_op(
-        &self,
-        val: ty::LazyConst<'tcx>,
-        layout: Option<TyLayout<'tcx>>,
-    ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
-        trace!("const_to_op: {:?}", val);
-        match val {
-            ty::LazyConst::Unevaluated(def_id, substs) => {
-                let instance = self.resolve(def_id, substs)?;
-                return Ok(OpTy::from(self.const_eval_raw(GlobalId {
-                    instance,
-                    promoted: None,
-                })?));
-            },
-            ty::LazyConst::Evaluated(c) => self.const_to_op(c, layout),
-        }
-    }
-
     // Used when the miri-engine runs into a constant and for extracting information from constants
     // in patterns via the `const_eval` module
-    crate fn const_to_op(
+    crate fn eval_const_to_op(
         &self,
         val: ty::Const<'tcx>,
         layout: Option<TyLayout<'tcx>>,
     ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
-        let val = self.monomorphize(val)?;
-        let layout = from_known_layout(layout, || {
-            self.layout_of(val.ty)
-        })?;
         let op = match val.val {
             ConstValue::Param(_) | ConstValue::Infer(_) => bug!(),
             ConstValue::ByRef(ptr, alloc) => {
@@ -609,7 +586,17 @@
                 )).with_default_tag(),
             ConstValue::Scalar(x) =>
                 Operand::Immediate(Immediate::Scalar(x.into())).with_default_tag(),
+            ConstValue::Unevaluated(def_id, substs) => {
+                let instance = self.resolve(def_id, substs)?;
+                return Ok(OpTy::from(self.const_eval_raw(GlobalId {
+                    instance,
+                    promoted: None,
+                })?));
+            },
         };
+        let layout = from_known_layout(layout, || {
+            self.layout_of(self.monomorphize(val.ty)?)
+        })?;
         Ok(OpTy {
             op,
             layout,
diff --git a/src/librustc_mir/interpret/operator.rs b/src/librustc_mir/interpret/operator.rs
index b3b9c74..944e393 100644
--- a/src/librustc_mir/interpret/operator.rs
+++ b/src/librustc_mir/interpret/operator.rs
@@ -336,7 +336,7 @@
 
         let layout = val.layout;
         let val = val.to_scalar()?;
-        trace!("Running unary op {:?}: {:?} ({:?})", un_op, val, layout.ty.sty);
+        trace!("Running unary op {:?}: {:?} ({:?})", un_op, val, layout.ty);
 
         match layout.ty.sty {
             ty::Bool => {
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index 4df274b..755bbd9 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -354,7 +354,7 @@
             ty::Ref(_, _, mutbl) => Some(mutbl),
             ty::Adt(def, _) if def.is_box() => Some(hir::MutMutable),
             ty::RawPtr(_) => None,
-            _ => bug!("Unexpected pointer type {}", val.layout.ty.sty),
+            _ => bug!("Unexpected pointer type {}", val.layout.ty),
         };
         place.mplace.ptr = M::tag_dereference(self, place, mutbl)?;
         Ok(place)
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index 0b735b4..c45e694 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -14,7 +14,6 @@
 #![feature(const_fn)]
 #![feature(decl_macro)]
 #![feature(exhaustive_patterns)]
-#![feature(range_contains)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_attrs)]
 #![feature(never_type)]
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index 1e245fa..4fe47a9 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -198,6 +198,8 @@
 use rustc_data_structures::bit_set::GrowableBitSet;
 use rustc_data_structures::sync::{MTRef, MTLock, ParallelIterator, par_iter};
 
+use std::iter;
+
 #[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
 pub enum MonoItemCollectionMode {
     Eager,
@@ -379,7 +381,7 @@
             let param_env = ty::ParamEnv::reveal_all();
 
             if let Ok(val) = tcx.const_eval(param_env.and(cid)) {
-                collect_const(tcx, val, &mut neighbors);
+                collect_const(tcx, val, InternalSubsts::empty(), &mut neighbors);
             }
         }
         MonoItem::Fn(instance) => {
@@ -466,15 +468,7 @@
                                      instance: Instance<'tcx>)
 {
     let type_length = instance.substs.types().flat_map(|ty| ty.walk()).count();
-    let const_length = instance.substs.consts()
-        .flat_map(|ct| {
-            let ty = match ct {
-                ty::LazyConst::Evaluated(ct) => ct.ty,
-                ty::LazyConst::Unevaluated(def_id, _) => tcx.type_of(*def_id),
-            };
-            ty.walk()
-        })
-        .count();
+    let const_length = instance.substs.consts().flat_map(|ct| ct.ty.walk()).count();
     debug!(" => type length={}, const length={}", type_length, const_length);
 
     // Rust code can easily create exponentially-long types using only a
@@ -487,21 +481,33 @@
     // We include the const length in the type length, as it's better
     // to be overly conservative.
     if type_length + const_length > type_length_limit {
-        // The instance name is already known to be too long for rustc. Use
-        // `{:.64}` to avoid blasting the user's terminal with thousands of
-        // lines of type-name.
-        let instance_name = instance.to_string();
-        let msg = format!("reached the type-length limit while instantiating `{:.64}...`",
-                          instance_name);
-        let mut diag = if let Some(hir_id) = tcx.hir().as_local_hir_id(instance.def_id()) {
-            tcx.sess.struct_span_fatal(tcx.hir().span_by_hir_id(hir_id), &msg)
-        } else {
-            tcx.sess.struct_fatal(&msg)
-        };
+        // The instance name is already known to be too long for rustc.
+        // Show only the first and last 32 characters to avoid blasting
+        // the user's terminal with thousands of lines of type-name.
+        let shrink = |s: String, before: usize, after: usize| {
+            // An iterator of all byte positions including the end of the string.
+            let positions = || s.char_indices().map(|(i, _)| i).chain(iter::once(s.len()));
 
+            let shrunk = format!(
+                "{before}...{after}",
+                before = &s[..positions().nth(before).unwrap_or(s.len())],
+                after = &s[positions().rev().nth(after).unwrap_or(0)..],
+            );
+
+            // Only use the shrunk version if it's really shorter.
+            // This also avoids the case where before and after slices overlap.
+            if shrunk.len() < s.len() {
+                shrunk
+            } else {
+                s
+            }
+        };
+        let msg = format!("reached the type-length limit while instantiating `{}`",
+                          shrink(instance.to_string(), 32, 32));
+        let mut diag = tcx.sess.struct_span_fatal(tcx.def_span(instance.def_id()), &msg);
         diag.note(&format!(
             "consider adding a `#![type_length_limit=\"{}\"]` attribute to your crate",
-            type_length_limit * 2));
+            type_length));
         diag.emit();
         tcx.sess.abort_if_errors();
     }
@@ -592,10 +598,10 @@
         self.super_rvalue(rvalue, location);
     }
 
-    fn visit_const(&mut self, constant: &&'tcx ty::LazyConst<'tcx>, location: Location) {
+    fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, location: Location) {
         debug!("visiting const {:?} @ {:?}", *constant, location);
 
-        collect_lazy_const(self.tcx, constant, self.param_substs, self.output);
+        collect_const(self.tcx, **constant, self.param_substs, self.output);
 
         self.super_const(constant);
     }
@@ -836,7 +842,7 @@
             match tail.sty {
                 ty::Foreign(..) => false,
                 ty::Str | ty::Slice(..) | ty::Dynamic(..) => true,
-                _ => bug!("unexpected unsized tail: {:?}", tail.sty),
+                _ => bug!("unexpected unsized tail: {:?}", tail),
             }
         };
         if type_has_metadata(inner_source) {
@@ -999,7 +1005,7 @@
                 let param_env = ty::ParamEnv::reveal_all();
 
                 if let Ok(val) = self.tcx.const_eval(param_env.and(cid)) {
-                    collect_const(self.tcx, val, &mut self.output);
+                    collect_const(self.tcx, val, InternalSubsts::empty(), &mut self.output);
                 }
             }
             hir::ItemKind::Fn(..) => {
@@ -1210,7 +1216,7 @@
             promoted: Some(i),
         };
         match tcx.const_eval(param_env.and(cid)) {
-            Ok(val) => collect_const(tcx, val, output),
+            Ok(val) => collect_const(tcx, val, instance.substs, output),
             Err(ErrorHandled::Reported) => {},
             Err(ErrorHandled::TooGeneric) => span_bug!(
                 mir.promoted[i].span, "collection encountered polymorphic constant",
@@ -1228,43 +1234,10 @@
     output
 }
 
-fn collect_lazy_const<'a, 'tcx>(
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    constant: &ty::LazyConst<'tcx>,
-    param_substs: SubstsRef<'tcx>,
-    output: &mut Vec<MonoItem<'tcx>>,
-) {
-    let (def_id, substs) = match *constant {
-        ty::LazyConst::Evaluated(c) => return collect_const(tcx, c, output),
-        ty::LazyConst::Unevaluated(did, substs) => (did, substs),
-    };
-    let param_env = ty::ParamEnv::reveal_all();
-    let substs = tcx.subst_and_normalize_erasing_regions(
-        param_substs,
-        param_env,
-        &substs,
-    );
-    let instance = ty::Instance::resolve(tcx,
-                                        param_env,
-                                        def_id,
-                                        substs).unwrap();
-
-    let cid = GlobalId {
-        instance,
-        promoted: None,
-    };
-    match tcx.const_eval(param_env.and(cid)) {
-        Ok(val) => collect_const(tcx, val, output),
-        Err(ErrorHandled::Reported) => {},
-        Err(ErrorHandled::TooGeneric) => span_bug!(
-            tcx.def_span(def_id), "collection encountered polymorphic constant",
-        ),
-    }
-}
-
 fn collect_const<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     constant: ty::Const<'tcx>,
+    param_substs: SubstsRef<'tcx>,
     output: &mut Vec<MonoItem<'tcx>>,
 ) {
     debug!("visiting const {:?}", constant);
@@ -1278,6 +1251,30 @@
                 collect_miri(tcx, id, output);
             }
         }
+        ConstValue::Unevaluated(did, substs) => {
+            let param_env = ty::ParamEnv::reveal_all();
+            let substs = tcx.subst_and_normalize_erasing_regions(
+                param_substs,
+                param_env,
+                &substs,
+            );
+            let instance = ty::Instance::resolve(tcx,
+                                                param_env,
+                                                did,
+                                                substs).unwrap();
+
+            let cid = GlobalId {
+                instance,
+                promoted: None,
+            };
+            match tcx.const_eval(param_env.and(cid)) {
+                Ok(val) => collect_const(tcx, val, param_substs, output),
+                Err(ErrorHandled::Reported) => {},
+                Err(ErrorHandled::TooGeneric) => span_bug!(
+                    tcx.def_span(did), "collection encountered polymorphic constant",
+                ),
+            }
+        }
         _ => {},
     }
 }
diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs
index 211f9ad..51ba690 100644
--- a/src/librustc_mir/monomorphize/item.rs
+++ b/src/librustc_mir/monomorphize/item.rs
@@ -3,7 +3,7 @@
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::mir::interpret::ConstValue;
 use rustc::session::config::OptLevel;
-use rustc::ty::{self, Ty, TyCtxt, Const, ClosureSubsts, GeneratorSubsts, LazyConst, ParamConst};
+use rustc::ty::{self, Ty, TyCtxt, Const, ClosureSubsts, GeneratorSubsts, ParamConst};
 use rustc::ty::subst::{SubstsRef, InternalSubsts};
 use syntax::ast;
 use syntax::attr::InlineAttr;
@@ -216,9 +216,8 @@
 // These keys are used by the handwritten auto-tests, so they need to be
 // predictable and human-readable.
 //
-// Note: A lot of this could looks very similar to what's already in the
-//       ppaux module. It would be good to refactor things so we only have one
-//       parameterizable implementation for printing types.
+// Note: A lot of this could looks very similar to what's already in `ty::print`.
+// FIXME(eddyb) implement a custom `PrettyPrinter` for this.
 
 /// Same as `unique_type_name()` but with the result pushed onto the given
 /// `output` parameter.
@@ -396,21 +395,17 @@
     }
 
     // FIXME(const_generics): handle debug printing.
-    pub fn push_const_name(&self, c: &LazyConst<'tcx>, output: &mut String, debug: bool) {
-        match c {
-            LazyConst::Unevaluated(..) => output.push_str("_: _"),
-            LazyConst::Evaluated(Const { ty, val }) => {
-                match val {
-                    ConstValue::Infer(..) => output.push_str("_"),
-                    ConstValue::Param(ParamConst { name, .. }) => {
-                        write!(output, "{}", name).unwrap();
-                    }
-                    _ => write!(output, "{:?}", c).unwrap(),
-                }
-                output.push_str(": ");
-                self.push_type_name(ty, output, debug);
+    pub fn push_const_name(&self, c: &Const<'tcx>, output: &mut String, debug: bool) {
+        match c.val {
+            ConstValue::Infer(..) => output.push_str("_"),
+            ConstValue::Param(ParamConst { name, .. }) => {
+                write!(output, "{}", name).unwrap();
             }
+            ConstValue::Unevaluated(..) => output.push_str("_: _"),
+            _ => write!(output, "{:?}", c).unwrap(),
         }
+        output.push_str(": ");
+        self.push_type_name(c.ty, output, debug);
     }
 
     pub fn push_def_path(&self,
diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs
index c0e2186..4a2c05b 100644
--- a/src/librustc_mir/monomorphize/partitioning.rs
+++ b/src/librustc_mir/monomorphize/partitioning.rs
@@ -104,7 +104,7 @@
 use rustc::mir::mono::{Linkage, Visibility, CodegenUnitNameBuilder};
 use rustc::middle::exported_symbols::SymbolExportLevel;
 use rustc::ty::{self, TyCtxt, InstanceDef};
-use rustc::ty::item_path::characteristic_def_id_of_type;
+use rustc::ty::print::characteristic_def_id_of_type;
 use rustc::ty::query::Providers;
 use rustc::util::common::time;
 use rustc::util::nodemap::{DefIdSet, FxHashMap, FxHashSet};
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index 1c6b145..f1fbc80 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -458,9 +458,9 @@
             span: self.span,
             ty: func_ty,
             user_ty: None,
-            literal: tcx.mk_lazy_const(ty::LazyConst::Evaluated(
+            literal: tcx.mk_const(
                 ty::Const::zero_sized(func_ty),
-            )),
+            ),
         });
 
         let ref_loc = self.make_place(
@@ -520,9 +520,9 @@
             span: self.span,
             ty: self.tcx.types.usize,
             user_ty: None,
-            literal: self.tcx.mk_lazy_const(ty::LazyConst::Evaluated(
+            literal: self.tcx.mk_const(
                 ty::Const::from_usize(self.tcx, value),
-            )),
+            ),
         }
     }
 
@@ -762,9 +762,9 @@
                 span,
                 ty,
                 user_ty: None,
-                literal: tcx.mk_lazy_const(ty::LazyConst::Evaluated(
+                literal: tcx.mk_const(
                     ty::Const::zero_sized(ty)
-                )),
+                ),
              }),
              vec![rcvr])
         }
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 23d8138..d816968 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -253,7 +253,7 @@
         source_info: SourceInfo,
     ) -> Option<Const<'tcx>> {
         self.ecx.tcx.span = source_info.span;
-        match self.ecx.eval_lazy_const_to_op(*c.literal, None) {
+        match self.ecx.eval_const_to_op(*c.literal, None) {
             Ok(op) => {
                 Some((op, c.span))
             },
diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs
index 32c027d..d5098bc 100644
--- a/src/librustc_mir/transform/elaborate_drops.rs
+++ b/src/librustc_mir/transform/elaborate_drops.rs
@@ -533,9 +533,9 @@
             span,
             ty: self.tcx.types.bool,
             user_ty: None,
-            literal: self.tcx.mk_lazy_const(ty::LazyConst::Evaluated(
+            literal: self.tcx.mk_const(
                 ty::Const::from_bool(self.tcx, val),
-            )),
+            ),
         })))
     }
 
diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs
index 9494d4b..a853f8d 100644
--- a/src/librustc_mir/transform/erase_regions.rs
+++ b/src/librustc_mir/transform/erase_regions.rs
@@ -32,7 +32,7 @@
         *region = self.tcx.types.re_erased;
     }
 
-    fn visit_const(&mut self, constant: &mut &'tcx ty::LazyConst<'tcx>, _: Location) {
+    fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, _: Location) {
         *constant = self.tcx.erase_regions(constant);
     }
 
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index 1f59802..b22258a 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -26,7 +26,7 @@
 //!     }
 //!
 //! This pass computes the meaning of the state field and the MIR locals which are live
-//! across a suspension point. There are however two hardcoded generator states:
+//! across a suspension point. There are however three hardcoded generator states:
 //!     0 - Generator have not been resumed yet
 //!     1 - Generator has returned / is completed
 //!     2 - Generator has been poisoned
@@ -144,6 +144,13 @@
     Local::new(1)
 }
 
+/// Generator have not been resumed yet
+const UNRESUMED: u32 = 0;
+/// Generator has returned / is completed
+const RETURNED: u32 = 1;
+/// Generator has been poisoned
+const POISONED: u32 = 2;
+
 struct SuspensionPoint {
     state: u32,
     resume: BasicBlock,
@@ -198,11 +205,11 @@
             span: source_info.span,
             ty: self.tcx.types.u32,
             user_ty: None,
-            literal: self.tcx.mk_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_bits(
+            literal: self.tcx.mk_const(ty::Const::from_bits(
                 self.tcx,
                 state_disc.into(),
                 ty::ParamEnv::empty().and(self.tcx.types.u32)
-            ))),
+            )),
         });
         Statement {
             source_info,
@@ -278,7 +285,7 @@
 
                 state
             } else { // Return
-                 1 // state for returned
+                RETURNED // state for returned
             };
             data.statements.push(self.set_state(state, source_info));
             data.terminator.as_mut().unwrap().kind = TerminatorKind::Return;
@@ -590,8 +597,15 @@
     let param_env = tcx.param_env(def_id);
     let gen = self_arg();
 
-    for block in mir.basic_blocks().indices() {
-        let (target, unwind, source_info) = match mir.basic_blocks()[block].terminator() {
+    let mut elaborator = DropShimElaborator {
+        mir: mir,
+        patch: MirPatch::new(mir),
+        tcx,
+        param_env
+    };
+
+    for (block, block_data) in mir.basic_blocks().iter_enumerated() {
+        let (target, unwind, source_info) = match block_data.terminator() {
             &Terminator {
                 source_info,
                 kind: TerminatorKind::Drop {
@@ -602,31 +616,22 @@
             } if local == gen => (target, unwind, source_info),
             _ => continue,
         };
-        let unwind = if let Some(unwind) = unwind {
-            Unwind::To(unwind)
-        } else {
+        let unwind = if block_data.is_cleanup {
             Unwind::InCleanup
+        } else {
+            Unwind::To(unwind.unwrap_or_else(|| elaborator.patch.resume_block()))
         };
-        let patch = {
-            let mut elaborator = DropShimElaborator {
-                mir: &mir,
-                patch: MirPatch::new(mir),
-                tcx,
-                param_env
-            };
-            elaborate_drop(
-                &mut elaborator,
-                source_info,
-                &Place::Base(PlaceBase::Local(gen)),
-                (),
-                target,
-                unwind,
-                block
-            );
-            elaborator.patch
-        };
-        patch.apply(mir);
+        elaborate_drop(
+            &mut elaborator,
+            source_info,
+            &Place::Base(PlaceBase::Local(gen)),
+            (),
+            target,
+            unwind,
+            block,
+        );
     }
+    elaborator.patch.apply(mir);
 }
 
 fn create_generator_drop_shim<'a, 'tcx>(
@@ -643,10 +648,10 @@
 
     let mut cases = create_cases(&mut mir, transform, |point| point.drop);
 
-    cases.insert(0, (0, drop_clean));
+    cases.insert(0, (UNRESUMED, drop_clean));
 
-    // The returned state (1) and the poisoned state (2) falls through to
-    // the default case which is just to return
+    // The returned state and the poisoned state fall through to the default
+    // case which is just to return
 
     insert_switch(tcx, &mut mir, cases, &transform, TerminatorKind::Return);
 
@@ -729,9 +734,9 @@
             span: mir.span,
             ty: tcx.types.bool,
             user_ty: None,
-            literal: tcx.mk_lazy_const(ty::LazyConst::Evaluated(
+            literal: tcx.mk_const(
                 ty::Const::from_bool(tcx, false),
-            )),
+            ),
         }),
         expected: true,
         msg: message,
@@ -762,7 +767,7 @@
     for block in mir.basic_blocks_mut() {
         let source_info = block.terminator().source_info;
         if let &TerminatorKind::Resume = &block.terminator().kind {
-            block.statements.push(transform.set_state(1, source_info));
+            block.statements.push(transform.set_state(POISONED, source_info));
         }
     }
 
@@ -773,12 +778,12 @@
         GeneratorResumedAfterReturn,
     };
 
-    // Jump to the entry point on the 0 state
-    cases.insert(0, (0, BasicBlock::new(0)));
-    // Panic when resumed on the returned (1) state
-    cases.insert(1, (1, insert_panic_block(tcx, mir, GeneratorResumedAfterReturn)));
-    // Panic when resumed on the poisoned (2) state
-    cases.insert(2, (2, insert_panic_block(tcx, mir, GeneratorResumedAfterPanic)));
+    // Jump to the entry point on the unresumed
+    cases.insert(0, (UNRESUMED, BasicBlock::new(0)));
+    // Panic when resumed on the returned state
+    cases.insert(1, (RETURNED, insert_panic_block(tcx, mir, GeneratorResumedAfterReturn)));
+    // Panic when resumed on the poisoned state
+    cases.insert(2, (POISONED, insert_panic_block(tcx, mir, GeneratorResumedAfterPanic)));
 
     insert_switch(tcx, mir, cases, &transform, TerminatorKind::Unreachable);
 
@@ -942,7 +947,7 @@
         mir.generator_layout = Some(layout);
 
         // Insert `drop(generator_struct)` which is used to drop upvars for generators in
-        // the unresumed (0) state.
+        // the unresumed state.
         // This is expanded to a drop ladder in `elaborate_generator_drops`.
         let drop_clean = insert_clean_drop(mir);
 
diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs
index 0cd2cec..8df0d72 100644
--- a/src/librustc_mir/transform/mod.rs
+++ b/src/librustc_mir/transform/mod.rs
@@ -285,6 +285,7 @@
         &simplify_branches::SimplifyBranches::new("after-const-prop"),
         &deaggregator::Deaggregator,
         &copy_prop::CopyPropagation,
+        &simplify_branches::SimplifyBranches::new("after-copy-prop"),
         &remove_noop_landing_pads::RemoveNoopLandingPads,
         &simplify::SimplifyCfg::new("final"),
         &simplify::SimplifyLocals,
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 97d566e..e966898 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -16,6 +16,7 @@
 use rustc::ty::cast::CastTy;
 use rustc::ty::query::Providers;
 use rustc::mir::*;
+use rustc::mir::interpret::ConstValue;
 use rustc::mir::traversal::ReversePostorder;
 use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext, NonMutatingUseContext};
 use rustc::middle::lang_items;
@@ -199,12 +200,12 @@
             Operand::Move(ref place) => Self::in_place(cx, place),
 
             Operand::Constant(ref constant) => {
-                if let ty::LazyConst::Unevaluated(def_id, _) = constant.literal {
+                if let ConstValue::Unevaluated(def_id, _) = constant.literal.val {
                     // Don't peek inside trait associated constants.
-                    if cx.tcx.trait_of_item(*def_id).is_some() {
+                    if cx.tcx.trait_of_item(def_id).is_some() {
                         Self::in_any_value_of_ty(cx, constant.ty).unwrap_or(false)
                     } else {
-                        let (bits, _) = cx.tcx.at(constant.span).mir_const_qualif(*def_id);
+                        let (bits, _) = cx.tcx.at(constant.span).mir_const_qualif(def_id);
 
                         let qualif = PerQualif::decode_from_bits(bits).0[Self::IDX];
 
@@ -1253,7 +1254,7 @@
                                     if !self.span.allows_unstable(&feature.as_str()) {
                                         let mut err = self.tcx.sess.struct_span_err(self.span,
                                             &format!("`{}` is not yet stable as a const fn",
-                                                    self.tcx.item_path_str(def_id)));
+                                                    self.tcx.def_path_str(def_id)));
                                         if nightly_options::is_nightly_build() {
                                             help!(&mut err,
                                                   "add `#![feature({})]` to the \
diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs
index f078316..f9f8abb 100644
--- a/src/librustc_mir/transform/rustc_peek.rs
+++ b/src/librustc_mir/transform/rustc_peek.rs
@@ -29,10 +29,10 @@
         let def_id = src.def_id();
         let id = tcx.hir().as_local_hir_id(def_id).unwrap();
         if !tcx.has_attr(def_id, "rustc_mir") {
-            debug!("skipping rustc_peek::SanityCheck on {}", tcx.item_path_str(def_id));
+            debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id));
             return;
         } else {
-            debug!("running rustc_peek::SanityCheck on {}", tcx.item_path_str(def_id));
+            debug!("running rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id));
         }
 
         let attributes = tcx.get_attrs(def_id);
diff --git a/src/librustc_mir/transform/simplify_branches.rs b/src/librustc_mir/transform/simplify_branches.rs
index 3c4d122..db73e82 100644
--- a/src/librustc_mir/transform/simplify_branches.rs
+++ b/src/librustc_mir/transform/simplify_branches.rs
@@ -30,7 +30,7 @@
                     discr: Operand::Constant(ref c), switch_ty, ref values, ref targets, ..
                 } => {
                     let switch_ty = ParamEnv::empty().and(switch_ty);
-                    let constant = c.literal.map_evaluated(|c| c.assert_bits(tcx, switch_ty));
+                    let constant = c.literal.assert_bits(tcx, switch_ty);
                     if let Some(constant) = constant {
                         let (otherwise, targets) = targets.split_last().unwrap();
                         let mut ret = TerminatorKind::Goto { target: *otherwise };
@@ -47,7 +47,7 @@
                 },
                 TerminatorKind::Assert {
                     target, cond: Operand::Constant(ref c), expected, ..
-                } if (c.literal.map_evaluated(|e| e.assert_bool(tcx)) == Some(true)) == expected =>
+                } if (c.literal.assert_bool(tcx) == Some(true)) == expected =>
                     TerminatorKind::Goto { target },
                 TerminatorKind::FalseEdges { real_target, .. } => {
                     TerminatorKind::Goto { target: real_target }
diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs
index 26fa8d6..37b3833 100644
--- a/src/librustc_mir/util/elaborate_drops.rs
+++ b/src/librustc_mir/util/elaborate_drops.rs
@@ -966,9 +966,9 @@
             span: self.source_info.span,
             ty: self.tcx().types.usize,
             user_ty: None,
-            literal: self.tcx().mk_lazy_const(ty::LazyConst::Evaluated(
+            literal: self.tcx().mk_const(
                 ty::Const::from_usize(self.tcx(), val.into())
-            )),
+            ),
         })
     }
 
diff --git a/src/librustc_mir/util/graphviz.rs b/src/librustc_mir/util/graphviz.rs
index 61b1a5a..69a2adc 100644
--- a/src/librustc_mir/util/graphviz.rs
+++ b/src/librustc_mir/util/graphviz.rs
@@ -127,7 +127,7 @@
                                                mir: &Mir<'_>,
                                                w: &mut W)
                                                -> io::Result<()> {
-    write!(w, "    label=<fn {}(", dot::escape_html(&tcx.item_path_str(def_id)))?;
+    write!(w, "    label=<fn {}(", dot::escape_html(&tcx.def_path_str(def_id)))?;
 
     // fn argument types.
     for (i, arg) in mir.args_iter().enumerate() {
@@ -141,7 +141,7 @@
         )?;
     }
 
-    write!(w, ") -&gt; {}", escape(mir.return_ty()))?;
+    write!(w, ") -&gt; {}", escape(&mir.return_ty()))?;
     write!(w, r#"<br align="left"/>"#)?;
 
     for local in mir.vars_and_temps_iter() {
diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs
index d08fb40..cbdd50c 100644
--- a/src/librustc_mir/util/liveness.rs
+++ b/src/librustc_mir/util/liveness.rs
@@ -29,7 +29,7 @@
 };
 use rustc::mir::Local;
 use rustc::mir::*;
-use rustc::ty::{item_path, TyCtxt};
+use rustc::ty::{self, TyCtxt};
 use rustc_data_structures::bit_set::BitSet;
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use rustc_data_structures::work_queue::WorkQueue;
@@ -265,9 +265,9 @@
     if !dump_enabled(tcx, pass_name, source) {
         return;
     }
-    let node_path = item_path::with_forced_impl_filename_line(|| {
+    let node_path = ty::print::with_forced_impl_filename_line(|| {
         // see notes on #41697 below
-        tcx.item_path_str(source.def_id())
+        tcx.def_path_str(source.def_id())
     });
     dump_matched_mir_node(tcx, pass_name, &node_path, source, mir, result);
 }
diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs
index c3fbee3..13bcdc2 100644
--- a/src/librustc_mir/util/pretty.rs
+++ b/src/librustc_mir/util/pretty.rs
@@ -1,8 +1,8 @@
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
+use rustc::hir::def::CtorKind;
 use rustc::mir::*;
 use rustc::mir::visit::Visitor;
 use rustc::ty::{self, TyCtxt};
-use rustc::ty::item_path;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::indexed_vec::Idx;
 use std::fmt::Display;
@@ -78,9 +78,9 @@
         return;
     }
 
-    let node_path = item_path::with_forced_impl_filename_line(|| {
+    let node_path = ty::print::with_forced_impl_filename_line(|| {
         // see notes on #41697 below
-        tcx.item_path_str(source.def_id())
+        tcx.def_path_str(source.def_id())
     });
     dump_matched_mir_node(
         tcx,
@@ -103,9 +103,9 @@
         None => return false,
         Some(ref filters) => filters,
     };
-    let node_path = item_path::with_forced_impl_filename_line(|| {
+    let node_path = ty::print::with_forced_impl_filename_line(|| {
         // see notes on #41697 below
-        tcx.item_path_str(source.def_id())
+        tcx.def_path_str(source.def_id())
     });
     filters.split('|').any(|or_filter| {
         or_filter.split('&').all(|and_filter| {
@@ -115,7 +115,7 @@
 }
 
 // #41697 -- we use `with_forced_impl_filename_line()` because
-// `item_path_str()` would otherwise trigger `type_of`, and this can
+// `def_path_str()` would otherwise trigger `type_of`, and this can
 // run while we are already attempting to evaluate `type_of`.
 
 fn dump_matched_mir_node<'a, 'gcx, 'tcx, F>(
@@ -317,9 +317,8 @@
     let data = &mir[block];
 
     // Basic block label at the top.
-    let cleanup_text = if data.is_cleanup { " // cleanup" } else { "" };
-    let lbl = format!("{}{:?}: {{", INDENT, block);
-    writeln!(w, "{0:1$}{2}", lbl, ALIGN, cleanup_text)?;
+    let cleanup_text = if data.is_cleanup { " (cleanup)" } else { "" };
+    writeln!(w, "{}{:?}{}: {{", INDENT, block, cleanup_text)?;
 
     // List of statements in the middle.
     let mut current_location = Location {
@@ -417,21 +416,12 @@
         self.push(&format!("+ literal: {:?}", literal));
     }
 
-    fn visit_const(&mut self, constant: &&'tcx ty::LazyConst<'tcx>, _: Location) {
+    fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, _: Location) {
         self.super_const(constant);
-        match constant {
-            ty::LazyConst::Evaluated(constant) => {
-                let ty::Const { ty, val, .. } = constant;
-                self.push("ty::Const");
-                self.push(&format!("+ ty: {:?}", ty));
-                self.push(&format!("+ val: {:?}", val));
-            },
-            ty::LazyConst::Unevaluated(did, substs) => {
-                self.push("ty::LazyConst::Unevaluated");
-                self.push(&format!("+ did: {:?}", did));
-                self.push(&format!("+ substs: {:?}", substs));
-            },
-        }
+        let ty::Const { ty, val, .. } = constant;
+        self.push("ty::Const");
+        self.push(&format!("+ ty: {:?}", ty));
+        self.push(&format!("+ val: {:?}", val));
     }
 
     fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
@@ -597,7 +587,8 @@
     trace!("write_mir_sig: {:?}", src.instance);
     let descr = tcx.describe_def(src.def_id());
     let is_function = match descr {
-        Some(Def::Fn(_)) | Some(Def::Method(_)) | Some(Def::StructCtor(..)) => true,
+        Some(Def::Fn(_)) | Some(Def::Method(_)) | Some(Def::Variant(..)) |
+        Some(Def::StructCtor(_, CtorKind::Fn)) => true,
         _ => tcx.is_closure(src.def_id()),
     };
     match (descr, src.promoted) {
@@ -612,9 +603,9 @@
         _ => bug!("Unexpected def description {:?}", descr),
     }
 
-    item_path::with_forced_impl_filename_line(|| {
+    ty::print::with_forced_impl_filename_line(|| {
         // see notes on #41697 elsewhere
-        write!(w, "{}", tcx.item_path_str(src.def_id()))
+        write!(w, " {}", tcx.def_path_str(src.def_id()))
     })?;
 
     if src.promoted.is_none() && is_function {
diff --git a/src/librustc_passes/layout_test.rs b/src/librustc_passes/layout_test.rs
index 7fe3f5a..373bcf7 100644
--- a/src/librustc_passes/layout_test.rs
+++ b/src/librustc_passes/layout_test.rs
@@ -53,9 +53,7 @@
                 // The `..` are the names of fields to dump.
                 let meta_items = attr.meta_item_list().unwrap_or_default();
                 for meta_item in meta_items {
-                    let name = meta_item.word().map(|mi| mi.name().as_str());
-                    let name = name.as_ref().map(|s| &s[..]).unwrap_or("");
-
+                    let name = meta_item.ident_str().unwrap_or("");
                     match name {
                         "abi" => {
                             self.tcx
@@ -88,7 +86,7 @@
 
                         _ => {
                             self.tcx.sess.span_err(
-                                meta_item.span,
+                                meta_item.span(),
                                 &format!("unrecognized field name `{}`", name),
                             );
                         }
diff --git a/src/librustc_plugin/load.rs b/src/librustc_plugin/load.rs
index 1b88cf0..bd11e0c 100644
--- a/src/librustc_plugin/load.rs
+++ b/src/librustc_plugin/load.rs
@@ -56,10 +56,10 @@
 
             for plugin in plugins {
                 // plugins must have a name and can't be key = value
-                match plugin.name() {
+                match plugin.ident_str() {
                     Some(name) if !plugin.is_value_str() => {
                         let args = plugin.meta_item_list().map(ToOwned::to_owned);
-                        loader.load_plugin(plugin.span, &name.as_str(), args.unwrap_or_default());
+                        loader.load_plugin(plugin.span(), name, args.unwrap_or_default());
                     },
                     _ => call_malformed_plugin_attribute(sess, attr.span),
                 }
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 52514a3..5065c1d 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -134,7 +134,7 @@
             ty::FnDef(def_id, ..) |
             ty::Closure(def_id, ..) |
             ty::Generator(def_id, ..) => {
-                if self.def_id_visitor.visit_def_id(def_id, "type", ty) {
+                if self.def_id_visitor.visit_def_id(def_id, "type", &ty) {
                     return true;
                 }
                 if self.def_id_visitor.shallow() {
@@ -816,7 +816,7 @@
         let def_id = self.tcx.adjust_ident(ident, def.did, current_hir).1;
         if !def.is_enum() && !field.vis.is_accessible_from(def_id, self.tcx) {
             struct_span_err!(self.tcx.sess, span, E0451, "field `{}` of {} `{}` is private",
-                             field.ident, def.variant_descr(), self.tcx.item_path_str(def.did))
+                             field.ident, def.variant_descr(), self.tcx.def_path_str(def.did))
                 .span_label(span, format!("field `{}` is private", field.ident))
                 .emit();
         }
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 5c99270..6fad4b2 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -463,10 +463,9 @@
                 if let Some(attr) = attr::find_by_name(&item.attrs, "proc_macro_derive") {
                     if let Some(trait_attr) =
                             attr.meta_item_list().and_then(|list| list.get(0).cloned()) {
-                        if let Some(ident) = trait_attr.name().map(Ident::with_empty_ctxt) {
-                            let sp = trait_attr.span;
+                        if let Some(ident) = trait_attr.ident() {
                             let def = Def::Macro(def.def_id(), MacroKind::ProcMacroStub);
-                            self.define(parent, ident, MacroNS, (def, vis, sp, expansion));
+                            self.define(parent, ident, MacroNS, (def, vis, ident.span, expansion));
                         }
                     }
                 }
@@ -636,10 +635,9 @@
         // but metadata cannot encode gensyms currently, so we create it here.
         // This is only a guess, two equivalent idents may incorrectly get different gensyms here.
         let ident = ident.gensym_if_underscore();
-        let def_id = def.def_id();
         let expansion = Mark::root(); // FIXME(jseyfried) intercrate hygiene
         match def {
-            Def::Mod(..) | Def::Enum(..) => {
+            Def::Mod(def_id) | Def::Enum(def_id) => {
                 let module = self.new_module(parent,
                                              ModuleKind::Def(def, ident.name),
                                              def_id,
@@ -647,13 +645,14 @@
                                              span);
                 self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion));
             }
-            Def::Variant(..) | Def::TyAlias(..) | Def::ForeignTy(..) => {
+            Def::Variant(..) | Def::TyAlias(..) | Def::ForeignTy(..) | Def::Existential(..) |
+            Def::TraitAlias(..) | Def::PrimTy(..) | Def::ToolMod => {
                 self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion));
             }
             Def::Fn(..) | Def::Static(..) | Def::Const(..) | Def::VariantCtor(..) => {
                 self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, expansion));
             }
-            Def::StructCtor(..) => {
+            Def::StructCtor(def_id, ..) => {
                 self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, expansion));
 
                 if let Some(struct_def_id) =
@@ -662,7 +661,7 @@
                     self.struct_constructors.insert(struct_def_id, (def, vis));
                 }
             }
-            Def::Trait(..) => {
+            Def::Trait(def_id) => {
                 let module_kind = ModuleKind::Def(def, ident.name);
                 let module = self.new_module(parent,
                                              module_kind,
@@ -683,18 +682,14 @@
                 }
                 module.populated.set(true);
             }
-            Def::Existential(..) |
-            Def::TraitAlias(..) => {
-                self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion));
-            }
-            Def::Struct(..) | Def::Union(..) => {
+            Def::Struct(def_id) | Def::Union(def_id) => {
                 self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion));
 
                 // Record field names for error reporting.
                 let field_names = self.cstore.struct_field_names_untracked(def_id);
                 self.insert_field_names(def_id, field_names);
             }
-            Def::Macro(..) => {
+            Def::Macro(..) | Def::NonMacroAttr(..) => {
                 self.define(parent, ident, MacroNS, (def, vis, DUMMY_SP, expansion));
             }
             _ => bug!("unexpected definition: {:?}", def)
@@ -812,14 +807,14 @@
                             break;
                         }
                         MetaItemKind::List(nested_metas) => for nested_meta in nested_metas {
-                            match nested_meta.word() {
-                                Some(word) => single_imports.push((word.name(), word.span)),
-                                None => ill_formed(nested_meta.span),
+                            match nested_meta.ident() {
+                                Some(ident) if nested_meta.is_word() => single_imports.push(ident),
+                                _ => ill_formed(nested_meta.span()),
                             }
                         }
                         MetaItemKind::NameValue(..) => ill_formed(meta.span),
                     }
-                    None => ill_formed(attr.span()),
+                    None => ill_formed(attr.span),
                 }
             }
         }
@@ -850,23 +845,23 @@
                 self.legacy_import_macro(ident.name, imported_binding, span, allow_shadowing);
             });
         } else {
-            for (name, span) in single_imports.iter().cloned() {
-                let ident = Ident::with_empty_ctxt(name);
+            for ident in single_imports.iter().cloned() {
                 let result = self.resolve_ident_in_module(
                     ModuleOrUniformRoot::Module(module),
                     ident,
                     MacroNS,
                     None,
                     false,
-                    span,
+                    ident.span,
                 );
                 if let Ok(binding) = result {
-                    let directive = macro_use_directive(span);
+                    let directive = macro_use_directive(ident.span);
                     self.potentially_unused_imports.push(directive);
                     let imported_binding = self.import(binding, directive);
-                    self.legacy_import_macro(name, imported_binding, span, allow_shadowing);
+                    self.legacy_import_macro(ident.name, imported_binding,
+                                             ident.span, allow_shadowing);
                 } else {
-                    span_err!(self.session, span, E0469, "imported macro not found");
+                    span_err!(self.session, ident.span, E0469, "imported macro not found");
                 }
             }
         }
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index b82aee7..3fea515 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -17,7 +17,7 @@
 use rustc::hir::def_id::DefId;
 use rustc::session::config::Input;
 use rustc::span_bug;
-use rustc::ty::{self, TyCtxt};
+use rustc::ty::{self, DefIdTree, TyCtxt};
 use rustc_data_structures::fx::FxHashSet;
 
 use std::path::Path;
@@ -429,7 +429,8 @@
         vis: ast::Visibility,
         attrs: &'l [Attribute],
     ) {
-        let qualname = format!("::{}", self.tcx.node_path_str(id));
+        let qualname = format!("::{}",
+            self.tcx.def_path_str(self.tcx.hir().local_def_id(id)));
 
         if !self.span.filter_generated(ident.span) {
             let sig = sig::assoc_const_signature(id, ident.name, typ, expr, &self.save_ctxt);
@@ -470,7 +471,8 @@
     ) {
         debug!("process_struct {:?} {:?}", item, item.span);
         let name = item.ident.to_string();
-        let qualname = format!("::{}", self.tcx.node_path_str(item.id));
+        let qualname = format!("::{}",
+            self.tcx.def_path_str(self.tcx.hir().local_def_id(item.id)));
 
         let kind = match item.node {
             ast::ItemKind::Struct(_, _) => DefKind::Struct,
@@ -682,7 +684,8 @@
         methods: &'l [ast::TraitItem],
     ) {
         let name = item.ident.to_string();
-        let qualname = format!("::{}", self.tcx.node_path_str(item.id));
+        let qualname = format!("::{}",
+            self.tcx.def_path_str(self.tcx.hir().local_def_id(item.id)));
         let mut val = name.clone();
         if !generics.params.is_empty() {
             val.push_str(&generic_params_to_string(&generics.params));
@@ -1093,7 +1096,8 @@
             ast::TraitItemKind::Type(ref bounds, ref default_ty) => {
                 // FIXME do something with _bounds (for type refs)
                 let name = trait_item.ident.name.to_string();
-                let qualname = format!("::{}", self.tcx.node_path_str(trait_item.id));
+                let qualname = format!("::{}",
+                    self.tcx.def_path_str(self.tcx.hir().local_def_id(trait_item.id)));
 
                 if !self.span.filter_generated(trait_item.ident.span) {
                     let span = self.span_from_span(trait_item.ident.span);
@@ -1201,7 +1205,7 @@
 
         // The parent def id of a given use tree is always the enclosing item.
         let parent = self.save_ctxt.tcx.hir().opt_local_def_id(id)
-            .and_then(|id| self.save_ctxt.tcx.parent_def_id(id))
+            .and_then(|id| self.save_ctxt.tcx.parent(id))
             .map(id_from_def_id);
 
         match use_tree.kind {
@@ -1300,7 +1304,8 @@
         // only get called for the root module of a crate.
         assert_eq!(id, ast::CRATE_NODE_ID);
 
-        let qualname = format!("::{}", self.tcx.node_path_str(id));
+        let qualname = format!("::{}",
+            self.tcx.def_path_str(self.tcx.hir().local_def_id(id)));
 
         let cm = self.tcx.sess.source_map();
         let filename = cm.span_to_filename(span);
@@ -1350,7 +1355,7 @@
                 if !self.span.filter_generated(name_span) {
                     let span = self.span_from_span(name_span);
                     let parent = self.save_ctxt.tcx.hir().opt_local_def_id(item.id)
-                        .and_then(|id| self.save_ctxt.tcx.parent_def_id(id))
+                        .and_then(|id| self.save_ctxt.tcx.parent(id))
                         .map(id_from_def_id);
                     self.dumper.import(
                         &Access {
@@ -1389,7 +1394,8 @@
                 self.nest_scope(item.id, |v| visit::walk_mod(v, m));
             }
             Ty(ref ty, ref ty_params) => {
-                let qualname = format!("::{}", self.tcx.node_path_str(item.id));
+                let qualname = format!("::{}",
+                    self.tcx.def_path_str(self.tcx.hir().local_def_id(item.id)));
                 let value = ty_to_string(&ty);
                 if !self.span.filter_generated(item.ident.span) {
                     let span = self.span_from_span(item.ident.span);
@@ -1418,7 +1424,8 @@
                 self.process_generic_params(ty_params, &qualname, item.id);
             }
             Existential(ref _bounds, ref ty_params) => {
-                let qualname = format!("::{}", self.tcx.node_path_str(item.id));
+                let qualname = format!("::{}",
+                    self.tcx.def_path_str(self.tcx.hir().local_def_id(item.id)));
                 // FIXME do something with _bounds
                 let value = String::new();
                 if !self.span.filter_generated(item.ident.span) {
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index d80f3e5ce..7ad5b7c 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -20,7 +20,7 @@
 use rustc::middle::privacy::AccessLevels;
 use rustc::middle::cstore::ExternCrate;
 use rustc::session::config::{CrateType, Input, OutputType};
-use rustc::ty::{self, TyCtxt};
+use rustc::ty::{self, DefIdTree, TyCtxt};
 use rustc::{bug, span_bug};
 use rustc_typeck::hir_ty_to_ty;
 use rustc_codegen_utils::link::{filename_for_metadata, out_filename};
@@ -134,7 +134,8 @@
     }
 
     pub fn get_extern_item_data(&self, item: &ast::ForeignItem) -> Option<Data> {
-        let qualname = format!("::{}", self.tcx.node_path_str(item.id));
+        let qualname = format!("::{}",
+            self.tcx.def_path_str(self.tcx.hir().local_def_id(item.id)));
         match item.node {
             ast::ForeignItemKind::Fn(ref decl, ref generics) => {
                 filter!(self.span_utils, item.ident.span);
@@ -184,7 +185,8 @@
     pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
         match item.node {
             ast::ItemKind::Fn(ref decl, .., ref generics, _) => {
-                let qualname = format!("::{}", self.tcx.node_path_str(item.id));
+                let qualname = format!("::{}",
+                    self.tcx.def_path_str(self.tcx.hir().local_def_id(item.id)));
                 filter!(self.span_utils, item.ident.span);
                 Some(Data::DefData(Def {
                     kind: DefKind::Function,
@@ -202,7 +204,8 @@
                 }))
             }
             ast::ItemKind::Static(ref typ, ..) => {
-                let qualname = format!("::{}", self.tcx.node_path_str(item.id));
+                let qualname = format!("::{}",
+                    self.tcx.def_path_str(self.tcx.hir().local_def_id(item.id)));
 
                 filter!(self.span_utils, item.ident.span);
 
@@ -225,7 +228,8 @@
                 }))
             }
             ast::ItemKind::Const(ref typ, _) => {
-                let qualname = format!("::{}", self.tcx.node_path_str(item.id));
+                let qualname = format!("::{}",
+                    self.tcx.def_path_str(self.tcx.hir().local_def_id(item.id)));
                 filter!(self.span_utils, item.ident.span);
 
                 let id = id_from_node_id(item.id, self);
@@ -247,7 +251,8 @@
                 }))
             }
             ast::ItemKind::Mod(ref m) => {
-                let qualname = format!("::{}", self.tcx.node_path_str(item.id));
+                let qualname = format!("::{}",
+                    self.tcx.def_path_str(self.tcx.hir().local_def_id(item.id)));
 
                 let cm = self.tcx.sess.source_map();
                 let filename = cm.span_to_filename(m.inner);
@@ -274,7 +279,8 @@
             }
             ast::ItemKind::Enum(ref def, _) => {
                 let name = item.ident.to_string();
-                let qualname = format!("::{}", self.tcx.node_path_str(item.id));
+                let qualname = format!("::{}",
+                    self.tcx.def_path_str(self.tcx.hir().local_def_id(item.id)));
                 filter!(self.span_utils, item.ident.span);
                 let variants_str = def.variants
                     .iter()
@@ -358,7 +364,9 @@
     pub fn get_field_data(&self, field: &ast::StructField, scope: NodeId) -> Option<Def> {
         if let Some(ident) = field.ident {
             let name = ident.to_string();
-            let qualname = format!("::{}::{}", self.tcx.node_path_str(scope), ident);
+            let qualname = format!("::{}::{}",
+                self.tcx.def_path_str(self.tcx.hir().local_def_id(scope)),
+                ident);
             filter!(self.span_utils, ident.span);
             let def_id = self.tcx.hir().local_def_id(field.id);
             let typ = self.tcx.type_of(def_id).to_string();
@@ -411,7 +419,7 @@
                             if let Some(def_id) = trait_id {
                                 // A method in a trait impl.
                                 qualname.push_str(" as ");
-                                qualname.push_str(&self.tcx.item_path_str(def_id));
+                                qualname.push_str(&self.tcx.def_path_str(def_id));
                                 self.tcx
                                     .associated_items(def_id)
                                     .find(|item| item.ident.name == ident.name)
@@ -451,7 +459,7 @@
                         }
 
                         (
-                            format!("::{}", self.tcx.item_path_str(def_id)),
+                            format!("::{}", self.tcx.def_path_str(def_id)),
                             Some(def_id),
                             None,
                             docs,
@@ -763,7 +771,7 @@
                 // This is a reference to a tuple struct where the def_id points
                 // to an invisible constructor function. That is not a very useful
                 // def, so adjust to point to the tuple struct itself.
-                let parent_def_id = self.tcx.parent_def_id(def_id).unwrap();
+                let parent_def_id = self.tcx.parent(def_id).unwrap();
                 Some(Ref {
                     kind: RefKind::Type,
                     span,
diff --git a/src/librustc_target/spec/mipsisa32r6_unknown_linux_gnu.rs b/src/librustc_target/spec/mipsisa32r6_unknown_linux_gnu.rs
new file mode 100644
index 0000000..f472914
--- /dev/null
+++ b/src/librustc_target/spec/mipsisa32r6_unknown_linux_gnu.rs
@@ -0,0 +1,23 @@
+use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
+
+pub fn target() -> TargetResult {
+    Ok(Target {
+        llvm_target: "mipsisa32r6-unknown-linux-gnu".to_string(),
+        target_endian: "big".to_string(),
+        target_pointer_width: "32".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(),
+        arch: "mips".to_string(),
+        target_os: "linux".to_string(),
+        target_env: "gnu".to_string(),
+        target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
+        options: TargetOptions {
+            cpu: "mips32r6".to_string(),
+            features: "+mips32r6".to_string(),
+            max_atomic_width: Some(32),
+
+            ..super::linux_base::opts()
+        },
+    })
+}
diff --git a/src/librustc_target/spec/mipsisa32r6el_unknown_linux_gnu.rs b/src/librustc_target/spec/mipsisa32r6el_unknown_linux_gnu.rs
new file mode 100644
index 0000000..f4f98d3
--- /dev/null
+++ b/src/librustc_target/spec/mipsisa32r6el_unknown_linux_gnu.rs
@@ -0,0 +1,24 @@
+use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
+
+pub fn target() -> TargetResult {
+    Ok(Target {
+        llvm_target: "mipsisa32r6el-unknown-linux-gnu".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "32".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(),
+        arch: "mips".to_string(),
+        target_os: "linux".to_string(),
+        target_env: "gnu".to_string(),
+        target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
+
+        options: TargetOptions {
+            cpu: "mips32r6".to_string(),
+            features: "+mips32r6".to_string(),
+            max_atomic_width: Some(32),
+
+            ..super::linux_base::opts()
+        },
+    })
+}
diff --git a/src/librustc_target/spec/mipsisa64r6_unknown_linux_gnuabi64.rs b/src/librustc_target/spec/mipsisa64r6_unknown_linux_gnuabi64.rs
new file mode 100644
index 0000000..7faed3a
--- /dev/null
+++ b/src/librustc_target/spec/mipsisa64r6_unknown_linux_gnuabi64.rs
@@ -0,0 +1,24 @@
+use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
+
+pub fn target() -> TargetResult {
+    Ok(Target {
+        llvm_target: "mipsisa64r6-unknown-linux-gnuabi64".to_string(),
+        target_endian: "big".to_string(),
+        target_pointer_width: "64".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(),
+        arch: "mips64".to_string(),
+        target_os: "linux".to_string(),
+        target_env: "gnu".to_string(),
+        target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
+        options: TargetOptions {
+            // NOTE(mips64r6) matches C toolchain
+            cpu: "mips64r6".to_string(),
+            features: "+mips64r6".to_string(),
+            max_atomic_width: Some(64),
+
+            ..super::linux_base::opts()
+        },
+    })
+}
diff --git a/src/librustc_target/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs b/src/librustc_target/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs
new file mode 100644
index 0000000..58a814a
--- /dev/null
+++ b/src/librustc_target/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs
@@ -0,0 +1,24 @@
+use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
+
+pub fn target() -> TargetResult {
+    Ok(Target {
+        llvm_target: "mipsisa64r6el-unknown-linux-gnuabi64".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "64".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(),
+        arch: "mips64".to_string(),
+        target_os: "linux".to_string(),
+        target_env: "gnu".to_string(),
+        target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
+        options: TargetOptions {
+            // NOTE(mips64r6) matches C toolchain
+            cpu: "mips64r6".to_string(),
+            features: "+mips64r6".to_string(),
+            max_atomic_width: Some(64),
+
+            ..super::linux_base::opts()
+        },
+    })
+}
diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs
index 2824d9c..fdb1db6 100644
--- a/src/librustc_target/spec/mod.rs
+++ b/src/librustc_target/spec/mod.rs
@@ -335,6 +335,10 @@
     ("mips-unknown-linux-gnu", mips_unknown_linux_gnu),
     ("mips64-unknown-linux-gnuabi64", mips64_unknown_linux_gnuabi64),
     ("mips64el-unknown-linux-gnuabi64", mips64el_unknown_linux_gnuabi64),
+    ("mipsisa32r6-unknown-linux-gnu", mipsisa32r6_unknown_linux_gnu),
+    ("mipsisa32r6el-unknown-linux-gnu", mipsisa32r6el_unknown_linux_gnu),
+    ("mipsisa64r6-unknown-linux-gnuabi64", mipsisa64r6_unknown_linux_gnuabi64),
+    ("mipsisa64r6el-unknown-linux-gnuabi64", mipsisa64r6el_unknown_linux_gnuabi64),
     ("mipsel-unknown-linux-gnu", mipsel_unknown_linux_gnu),
     ("powerpc-unknown-linux-gnu", powerpc_unknown_linux_gnu),
     ("powerpc-unknown-linux-gnuspe", powerpc_unknown_linux_gnuspe),
diff --git a/src/librustc_target/spec/uefi_base.rs b/src/librustc_target/spec/uefi_base.rs
index 631966c..956767a 100644
--- a/src/librustc_target/spec/uefi_base.rs
+++ b/src/librustc_target/spec/uefi_base.rs
@@ -59,7 +59,7 @@
         singlethread: true,
         emit_debug_gdb_scripts: false,
 
-        linker: Some("lld-link".to_string()),
+        linker: Some("rust-lld".to_string()),
         lld_flavor: LldFlavor::Link,
         pre_link_args,
 
diff --git a/src/librustc_traits/chalk_context/mod.rs b/src/librustc_traits/chalk_context/mod.rs
index 6420f20..334f510 100644
--- a/src/librustc_traits/chalk_context/mod.rs
+++ b/src/librustc_traits/chalk_context/mod.rs
@@ -288,13 +288,10 @@
                     }
                     _ => false,
                 },
-                UnpackedKind::Const(ct) => match ct {
-                    ty::LazyConst::Evaluated(ty::Const {
-                        val: ConstValue::Infer(InferConst::Canonical(debruijn, bound_ct)),
-                        ..
-                    }) => {
-                        debug_assert_eq!(*debruijn, ty::INNERMOST);
-                        cvar == *bound_ct
+                UnpackedKind::Const(ct) => match ct.val {
+                    ConstValue::Infer(InferConst::Canonical(debruijn, bound_ct)) => {
+                        debug_assert_eq!(debruijn, ty::INNERMOST);
+                        cvar == bound_ct
                     }
                     _ => false,
                 }
diff --git a/src/librustc_traits/chalk_context/program_clauses.rs b/src/librustc_traits/chalk_context/program_clauses.rs
index 3f88d0e..8d5d2b8 100644
--- a/src/librustc_traits/chalk_context/program_clauses.rs
+++ b/src/librustc_traits/chalk_context/program_clauses.rs
@@ -239,7 +239,7 @@
 
 fn wf_clause_for_array<'tcx>(
     tcx: ty::TyCtxt<'_, '_, 'tcx>,
-    length: &'tcx ty::LazyConst<'tcx>
+    length: &'tcx ty::Const<'tcx>
 ) -> Clauses<'tcx> {
     let ty = generic_types::bound(tcx, 0);
     let array_ty = tcx.mk_ty(ty::Array(ty, length));
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 89ec92a..df8b1bc 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -12,7 +12,7 @@
 use crate::namespace::Namespace;
 use rustc::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
 use rustc::traits;
-use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable};
+use rustc::ty::{self, DefIdTree, Ty, TyCtxt, ToPredicate, TypeFoldable};
 use rustc::ty::{GenericParamDef, GenericParamDefKind};
 use rustc::ty::subst::{Kind, Subst, InternalSubsts, SubstsRef};
 use rustc::ty::wf::object_region_bounds;
@@ -922,7 +922,7 @@
                                      "the value of the associated type `{}` (from the trait `{}`) \
                                       is already specified",
                                      binding.item_name,
-                                     tcx.item_path_str(assoc_ty.container.id()))
+                                     tcx.def_path_str(assoc_ty.container.id()))
                         .span_label(binding.span, "re-bound here")
                         .span_label(*prev_span, format!("`{}` bound here first", binding.item_name))
                         .emit();
@@ -959,7 +959,9 @@
     /// removing the dummy `Self` type (`TRAIT_OBJECT_DUMMY_SELF`).
     fn trait_ref_to_existential(&self, trait_ref: ty::TraitRef<'tcx>)
                                 -> ty::ExistentialTraitRef<'tcx> {
-        assert_eq!(trait_ref.self_ty().sty, TRAIT_OBJECT_DUMMY_SELF);
+        if trait_ref.self_ty().sty != TRAIT_OBJECT_DUMMY_SELF {
+            bug!("trait_ref_to_existential called on {:?} with non-dummy Self", trait_ref);
+        }
         ty::ExistentialTraitRef::erase_self_ty(self.tcx(), trait_ref)
     }
 
@@ -1069,7 +1071,7 @@
                 format!(
                     "`{}` (from the trait `{}`)",
                     assoc_item.ident,
-                    tcx.item_path_str(trait_def_id),
+                    tcx.def_path_str(trait_def_id),
                 )
             }).collect::<Vec<_>>().join(", ");
             let mut err = struct_span_err!(
@@ -1450,14 +1452,14 @@
                    -> Ty<'tcx>
     {
         let tcx = self.tcx();
-        let trait_def_id = tcx.parent_def_id(item_def_id).unwrap();
+        let trait_def_id = tcx.parent(item_def_id).unwrap();
 
         self.prohibit_generics(slice::from_ref(item_segment));
 
         let self_ty = if let Some(ty) = opt_self_ty {
             ty
         } else {
-            let path_str = tcx.item_path_str(trait_def_id);
+            let path_str = tcx.def_path_str(trait_def_id);
             self.report_ambiguous_associated_type(span,
                                                   "Type",
                                                   &path_str,
@@ -1619,7 +1621,7 @@
                 } else if last >= 1 && segments[last - 1].args.is_some() {
                     // Everything but the penultimate segment should have no
                     // parameters at all.
-                    let enum_def_id = tcx.parent_def_id(def_id).unwrap();
+                    let enum_def_id = tcx.parent(def_id).unwrap();
                     (enum_def_id, last - 1)
                 } else {
                     // FIXME: lint here recommending `Enum::<...>::Variant` form
@@ -1868,16 +1870,19 @@
         &self,
         ast_const: &hir::AnonConst,
         ty: Ty<'tcx>
-    ) -> &'tcx ty::LazyConst<'tcx> {
+    ) -> &'tcx ty::Const<'tcx> {
         debug!("ast_const_to_const(id={:?}, ast_const={:?})", ast_const.hir_id, ast_const);
 
         let tcx = self.tcx();
         let def_id = tcx.hir().local_def_id_from_hir_id(ast_const.hir_id);
 
-        let mut lazy_const = ty::LazyConst::Unevaluated(
-            def_id,
-            InternalSubsts::identity_for_item(tcx, def_id),
-        );
+        let mut const_ = ty::Const {
+            val: ConstValue::Unevaluated(
+                def_id,
+                InternalSubsts::identity_for_item(tcx, def_id),
+            ),
+            ty,
+        };
 
         let expr = &tcx.hir().body(ast_const.body).value;
         if let ExprKind::Path(ref qpath) = expr.node {
@@ -1889,15 +1894,12 @@
                     let generics = tcx.generics_of(item_def_id);
                     let index = generics.param_def_id_to_index[&tcx.hir().local_def_id(node_id)];
                     let name = tcx.hir().name(node_id).as_interned_str();
-                    lazy_const = ty::LazyConst::Evaluated(ty::Const {
-                        val: ConstValue::Param(ty::ParamConst::new(index, name)),
-                        ty,
-                    })
+                    const_.val = ConstValue::Param(ty::ParamConst::new(index, name));
                 }
             }
         };
 
-        tcx.mk_lazy_const(lazy_const)
+        tcx.mk_const(const_)
     }
 
     pub fn impl_trait_ty_to_ty(
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 1a3ade7..c6b6639 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -88,7 +88,7 @@
             // See the examples in `run-pass/match-defbm*.rs`.
             let mut pat_adjustments = vec![];
             while let ty::Ref(_, inner_ty, inner_mutability) = exp_ty.sty {
-                debug!("inspecting {:?} with type {:?}", exp_ty, exp_ty.sty);
+                debug!("inspecting {:?}", exp_ty);
 
                 debug!("current discriminant is Ref, inserting implicit deref");
                 // Preserve the reference type. We'll need it later during HAIR lowering.
@@ -894,7 +894,7 @@
                 subpats.len() < variant.fields.len() && ddpos.is_some() {
             let substs = match pat_ty.sty {
                 ty::Adt(_, substs) => substs,
-                ref ty => bug!("unexpected pattern type {:?}", ty),
+                _ => bug!("unexpected pattern type {:?}", pat_ty),
             };
             for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
                 let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs);
@@ -1001,13 +1001,13 @@
                                            E0026,
                                            "{} `{}` does not have {}",
                                            kind_name,
-                                           tcx.item_path_str(variant.did),
+                                           tcx.def_path_str(variant.did),
                                            field_names);
             if let Some((span, ident)) = inexistent_fields.last() {
                 err.span_label(*span,
                                format!("{} `{}` does not have {} field{}",
                                        kind_name,
-                                       tcx.item_path_str(variant.did),
+                                       tcx.def_path_str(variant.did),
                                        t,
                                        plural));
                 if plural == "" {
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index 0a4c0eb..15ae396 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -2,7 +2,7 @@
 use super::method::MethodCallee;
 use super::{Expectation, FnCtxt, Needs, TupleArgumentsFlag};
 
-use errors::Applicability;
+use errors::{Applicability, DiagnosticBuilder};
 use hir::def::Def;
 use hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
@@ -232,6 +232,32 @@
         None
     }
 
+    /// Give appropriate suggestion when encountering `||{/* not callable */}()`, where the
+    /// likely intention is to call the closure, suggest `(||{})()`. (#55851)
+    fn identify_bad_closure_def_and_call(
+        &self,
+        err: &mut DiagnosticBuilder<'a>,
+        hir_id: hir::HirId,
+        callee_node: &hir::ExprKind,
+        callee_span: Span,
+    ) {
+        let hir_id = self.tcx.hir().get_parent_node_by_hir_id(hir_id);
+        let parent_node = self.tcx.hir().get_by_hir_id(hir_id);
+        if let (
+            hir::Node::Expr(hir::Expr { node: hir::ExprKind::Closure(_, _, _, sp, ..), .. }),
+            hir::ExprKind::Block(..),
+        ) = (parent_node, callee_node) {
+            let start = sp.shrink_to_lo();
+            let end = self.tcx.sess.source_map().next_point(callee_span);
+            err.multipart_suggestion(
+                "if you meant to create this closure and immediately call it, surround the \
+                closure with parenthesis",
+                vec![(start, "(".to_string()), (end, ")".to_string())],
+                Applicability::MaybeIncorrect,
+            );
+        }
+    }
+
     fn confirm_builtin_call(
         &self,
         call_expr: &hir::Expr,
@@ -268,6 +294,13 @@
                         }
                     );
 
+                    self.identify_bad_closure_def_and_call(
+                        &mut err,
+                        call_expr.hir_id,
+                        &callee.node,
+                        callee.span,
+                    );
+
                     if let Some(ref path) = unit_variant {
                         err.span_suggestion(
                             call_expr.span,
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index f79bf4e..e6e5c46 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -719,7 +719,7 @@
                                         trait `{}` has {}",
                                        trait_m.ident,
                                        potentially_plural_count(impl_number_args, "parameter"),
-                                       tcx.item_path_str(trait_m.def_id),
+                                       tcx.def_path_str(trait_m.def_id),
                                        trait_number_args);
         if let Some(trait_span) = trait_span {
             err.span_label(trait_span, format!("trait requires {}",
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index 32ca854..3a7308d 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -130,7 +130,7 @@
                         let sole_field = &variant.fields[0];
                         let sole_field_ty = sole_field.ty(self.tcx, substs);
                         if self.can_coerce(expr_ty, sole_field_ty) {
-                            let variant_path = self.tcx.item_path_str(variant.did);
+                            let variant_path = self.tcx.def_path_str(variant.did);
                             // FIXME #56861: DRYer prelude filtering
                             Some(variant_path.trim_start_matches("std::prelude::v1::").to_string())
                         } else {
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index efae870..1f0ab3a 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -1195,7 +1195,7 @@
         // `report_method_error()`.
         diag.help(&format!(
             "call with fully qualified syntax `{}(...)` to keep using the current method",
-            self.tcx.item_path_str(stable_pick.item.def_id),
+            self.tcx.def_path_str(stable_pick.item.def_id),
         ));
 
         if nightly_options::is_nightly_build() {
@@ -1203,7 +1203,7 @@
                 diag.help(&format!(
                     "add #![feature({})] to the crate attributes to enable `{}`",
                     feature,
-                    self.tcx.item_path_str(candidate.item.def_id),
+                    self.tcx.def_path_str(candidate.item.def_id),
                 ));
             }
         }
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index 4bf6471..b4a1a2d 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -15,7 +15,7 @@
 use rustc::infer::type_variable::TypeVariableOrigin;
 use rustc::traits::Obligation;
 use rustc::ty::{self, Adt, Ty, TyCtxt, ToPolyTraitRef, ToPredicate, TypeFoldable};
-use rustc::ty::item_path::with_crate_prefix;
+use rustc::ty::print::with_crate_prefix;
 use syntax_pos::{Span, FileName};
 use syntax::ast;
 use syntax::util::lev_distance::find_best_match_for_name;
@@ -102,7 +102,7 @@
                             None => String::new(),
                             Some(trait_ref) => {
                                 format!(" of the trait `{}`",
-                                        self.tcx.item_path_str(trait_ref.def_id))
+                                        self.tcx.def_path_str(trait_ref.def_id))
                             }
                         };
 
@@ -135,16 +135,16 @@
                                        item_span,
                                        "candidate #{} is defined in the trait `{}`",
                                        idx + 1,
-                                       self.tcx.item_path_str(trait_did));
+                                       self.tcx.def_path_str(trait_did));
                         } else {
                             span_note!(err,
                                        item_span,
                                        "the candidate is defined in the trait `{}`",
-                                       self.tcx.item_path_str(trait_did));
+                                       self.tcx.def_path_str(trait_did));
                         }
                         err.help(&format!("to disambiguate the method call, write `{}::{}({}{})` \
                                           instead",
-                                          self.tcx.item_path_str(trait_did),
+                                          self.tcx.def_path_str(trait_did),
                                           item_name,
                                           if rcvr_ty.is_region_ptr() && args.is_some() {
                                               if rcvr_ty.is_mutable_pointer() {
@@ -516,7 +516,7 @@
                 };
                 format!(
                     "use {};\n{}",
-                    with_crate_prefix(|| self.tcx.item_path_str(*did)),
+                    with_crate_prefix(|| self.tcx.def_path_str(*did)),
                     additional_newline
                 )
             });
@@ -530,14 +530,14 @@
                         &format!(
                             "\ncandidate #{}: `use {};`",
                             i + 1,
-                            with_crate_prefix(|| self.tcx.item_path_str(*trait_did))
+                            with_crate_prefix(|| self.tcx.def_path_str(*trait_did))
                         )
                     );
                 } else {
                     msg.push_str(
                         &format!(
                             "\n`use {};`",
-                            with_crate_prefix(|| self.tcx.item_path_str(*trait_did))
+                            with_crate_prefix(|| self.tcx.def_path_str(*trait_did))
                         )
                     );
                 }
@@ -638,7 +638,7 @@
             for (i, trait_info) in candidates.iter().enumerate() {
                 msg.push_str(&format!("\ncandidate #{}: `{}`",
                                       i + 1,
-                                      self.tcx.item_path_str(trait_info.def_id)));
+                                      self.tcx.def_path_str(trait_info.def_id)));
             }
             err.note(&msg[..]);
         }
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 28c79ce..899bb6f 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1328,7 +1328,7 @@
     debug!(
         "check_item_type(it.hir_id={}, it.name={})",
         it.hir_id,
-        tcx.item_path_str(tcx.hir().local_def_id_from_hir_id(it.hir_id))
+        tcx.def_path_str(tcx.hir().local_def_id_from_hir_id(it.hir_id))
     );
     let _indenter = indenter();
     match it.node {
@@ -2424,7 +2424,7 @@
         ty
     }
 
-    pub fn to_const(&self, ast_c: &hir::AnonConst, ty: Ty<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
+    pub fn to_const(&self, ast_c: &hir::AnonConst, ty: Ty<'tcx>) -> &'tcx ty::Const<'tcx> {
         AstConv::ast_const_to_const(self, ast_c, ty)
     }
 
@@ -3463,8 +3463,22 @@
             // We won't diverge unless both branches do (or the condition does).
             self.diverges.set(cond_diverges | then_diverges & else_diverges);
         } else {
+            // If this `if` expr is the parent's function return expr, the cause of the type
+            // coercion is the return type, point at it. (#25228)
+            let ret_reason = self.maybe_get_coercion_reason(then_expr.hir_id, sp);
+
             let else_cause = self.cause(sp, ObligationCauseCode::IfExpressionWithNoElse);
-            coerce.coerce_forced_unit(self, &else_cause, &mut |_| (), true);
+            coerce.coerce_forced_unit(self, &else_cause, &mut |err| {
+                if let Some((sp, msg)) = &ret_reason {
+                    err.span_label(*sp, msg.as_str());
+                } else if let ExprKind::Block(block, _) = &then_expr.node {
+                    if let Some(expr) = &block.expr {
+                        err.span_label(expr.span, "found here".to_string());
+                    }
+                }
+                err.note("`if` expressions without `else` evaluate to `()`");
+                err.help("consider adding an `else` block that evaluates to the expected type");
+            }, ret_reason.is_none());
 
             // If the condition is false we can't diverge.
             self.diverges.set(cond_diverges);
@@ -3478,6 +3492,37 @@
         }
     }
 
+    fn maybe_get_coercion_reason(&self, hir_id: hir::HirId, sp: Span) -> Option<(Span, String)> {
+        let node = self.tcx.hir().get_by_hir_id(self.tcx.hir().get_parent_node_by_hir_id(
+            self.tcx.hir().get_parent_node_by_hir_id(hir_id),
+        ));
+        if let Node::Block(block) = node {
+            // check that the body's parent is an fn
+            let parent = self.tcx.hir().get_by_hir_id(
+                self.tcx.hir().get_parent_node_by_hir_id(
+                    self.tcx.hir().get_parent_node_by_hir_id(block.hir_id),
+                ),
+            );
+            if let (Some(expr), Node::Item(hir::Item {
+                node: hir::ItemKind::Fn(..), ..
+            })) = (&block.expr, parent) {
+                // check that the `if` expr without `else` is the fn body's expr
+                if expr.span == sp {
+                    return self.get_fn_decl(hir_id).map(|(fn_decl, _)| (
+                        fn_decl.output.span(),
+                        format!("expected `{}` because of this return type", fn_decl.output),
+                    ));
+                }
+            }
+        }
+        if let Node::Local(hir::Local {
+            ty: Some(_), pat, ..
+        }) = node {
+            return Some((pat.span, "expected because of this assignment".to_string()));
+        }
+        None
+    }
+
     // Check field access expressions
     fn check_field(&self,
                    expr: &'gcx hir::Expr,
@@ -3534,7 +3579,7 @@
         autoderef.unambiguous_final_ty(self);
 
         if let Some((did, field_ty)) = private_candidate {
-            let struct_path = self.tcx().item_path_str(did);
+            let struct_path = self.tcx().def_path_str(did);
             let mut err = struct_span_err!(self.tcx().sess, expr.span, E0616,
                                            "field `{}` of struct `{}` is private",
                                            field, struct_path);
@@ -3885,7 +3930,7 @@
                     ty::Adt(adt, substs) => {
                         Some((adt.variant_of_def(def), adt.did, substs))
                     }
-                    _ => bug!("unexpected type: {:?}", ty.sty)
+                    _ => bug!("unexpected type: {:?}", ty)
                 }
             }
             Def::Struct(..) | Def::Union(..) | Def::TyAlias(..) |
@@ -4594,7 +4639,7 @@
                 if element_ty.references_error() {
                     tcx.types.err
                 } else if let Ok(count) = count {
-                    tcx.mk_ty(ty::Array(t, tcx.mk_lazy_const(ty::LazyConst::Evaluated(count))))
+                    tcx.mk_ty(ty::Array(t, tcx.mk_const(count)))
                 } else {
                     tcx.types.err
                 }
@@ -5226,8 +5271,8 @@
                 debug!("suggest_missing_return_type: return type {:?} node {:?}", ty, ty.node);
                 let sp = ty.span;
                 let ty = AstConv::ast_ty_to_ty(self, ty);
-                debug!("suggest_missing_return_type: return type sty {:?}", ty.sty);
-                debug!("suggest_missing_return_type: expected type sty {:?}", ty.sty);
+                debug!("suggest_missing_return_type: return type {:?}", ty);
+                debug!("suggest_missing_return_type: expected type {:?}", ty);
                 if ty.sty == expected.sty {
                     err.span_label(sp, format!("expected `{}` because of return type",
                                                expected));
@@ -5288,6 +5333,53 @@
         Some(original_span.with_lo(original_span.hi() - BytePos(1)))
     }
 
+    // Rewrite `SelfCtor` to `StructCtor`
+    pub fn rewrite_self_ctor(&self, def: Def, span: Span) -> (Def, DefId, Ty<'tcx>) {
+        let tcx = self.tcx;
+        if let Def::SelfCtor(impl_def_id) = def {
+            let ty = self.impl_self_ty(span, impl_def_id).ty;
+            let adt_def = ty.ty_adt_def();
+
+            match adt_def {
+                Some(adt_def) if adt_def.has_ctor() => {
+                    let variant = adt_def.non_enum_variant();
+                    let def = Def::StructCtor(variant.did, variant.ctor_kind);
+                    (def, variant.did, tcx.type_of(variant.did))
+                }
+                _ => {
+                    let mut err = tcx.sess.struct_span_err(span,
+                        "the `Self` constructor can only be used with tuple or unit structs");
+                    if let Some(adt_def) = adt_def {
+                        match adt_def.adt_kind() {
+                            AdtKind::Enum => {
+                                err.help("did you mean to use one of the enum's variants?");
+                            },
+                            AdtKind::Struct |
+                            AdtKind::Union => {
+                                err.span_suggestion(
+                                    span,
+                                    "use curly brackets",
+                                    String::from("Self { /* fields */ }"),
+                                    Applicability::HasPlaceholders,
+                                );
+                            }
+                        }
+                    }
+                    err.emit();
+
+                    (def, impl_def_id, tcx.types.err)
+                }
+            }
+        } else {
+            let def_id = def.def_id();
+
+            // The things we are substituting into the type should not contain
+            // escaping late-bound regions, and nor should the base type scheme.
+            let ty = tcx.type_of(def_id);
+            (def, def_id, ty)
+        }
+    }
+
     // Instantiates the given path, which must refer to an item with the given
     // number of type parameters and type.
     pub fn instantiate_value_path(&self,
@@ -5307,6 +5399,18 @@
 
         let tcx = self.tcx;
 
+        match def {
+            Def::Local(nid) | Def::Upvar(nid, ..) => {
+                let hid = self.tcx.hir().node_to_hir_id(nid);
+                let ty = self.local_ty(span, hid).decl_ty;
+                let ty = self.normalize_associated_types_in(span, &ty);
+                self.write_ty(hir_id, ty);
+                return (ty, def);
+            }
+            _ => {}
+        }
+
+        let (def, def_id, ty) = self.rewrite_self_ctor(def, span);
         let path_segs = AstConv::def_ids_for_path_segments(self, segments, self_ty, def);
 
         let mut user_self_ty = None;
@@ -5368,17 +5472,6 @@
             user_self_ty = None;
         }
 
-        match def {
-            Def::Local(nid) | Def::Upvar(nid, ..) => {
-                let hid = self.tcx.hir().node_to_hir_id(nid);
-                let ty = self.local_ty(span, hid).decl_ty;
-                let ty = self.normalize_associated_types_in(span, &ty);
-                self.write_ty(hir_id, ty);
-                return (ty, def);
-            }
-            _ => {}
-        }
-
         // Now we have to compare the types that the user *actually*
         // provided against the types that were *expected*. If the user
         // did not provide any types, then we want to substitute inference
@@ -5411,53 +5504,6 @@
             tcx.generics_of(*def_id).has_self
         }).unwrap_or(false);
 
-        let mut new_def = def;
-        let (def_id, ty) = match def {
-            Def::SelfCtor(impl_def_id) => {
-                let ty = self.impl_self_ty(span, impl_def_id).ty;
-                let adt_def = ty.ty_adt_def();
-
-                match adt_def {
-                    Some(adt_def) if adt_def.has_ctor() => {
-                        let variant = adt_def.non_enum_variant();
-                        new_def = Def::StructCtor(variant.did, variant.ctor_kind);
-                        (variant.did, tcx.type_of(variant.did))
-                    }
-                    _ => {
-                        let mut err = tcx.sess.struct_span_err(span,
-                            "the `Self` constructor can only be used with tuple or unit structs");
-                        if let Some(adt_def) = adt_def {
-                            match adt_def.adt_kind() {
-                                AdtKind::Enum => {
-                                    err.help("did you mean to use one of the enum's variants?");
-                                },
-                                AdtKind::Struct |
-                                AdtKind::Union => {
-                                    err.span_suggestion(
-                                        span,
-                                        "use curly brackets",
-                                        String::from("Self { /* fields */ }"),
-                                        Applicability::HasPlaceholders,
-                                    );
-                                }
-                            }
-                        }
-                        err.emit();
-
-                        (impl_def_id, tcx.types.err)
-                    }
-                }
-            }
-            _ => {
-                let def_id = def.def_id();
-
-                // The things we are substituting into the type should not contain
-                // escaping late-bound regions, and nor should the base type scheme.
-                let ty = tcx.type_of(def_id);
-                (def_id, ty)
-            }
-        };
-
         let substs = AstConv::create_substs_for_generic_args(
             tcx,
             def_id,
@@ -5573,7 +5619,7 @@
                ty_substituted);
         self.write_substs(hir_id, substs);
 
-        (ty_substituted, new_def)
+        (ty_substituted, def)
     }
 
     fn check_rustc_args_require_const(&self,
diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs
index 3e6e657..a76dfdd 100644
--- a/src/librustc_typeck/check/upvar.rs
+++ b/src/librustc_typeck/check/upvar.rs
@@ -93,19 +93,20 @@
         );
 
         // Extract the type of the closure.
-        let (closure_def_id, substs) = match self.node_ty(closure_hir_id).sty {
+        let ty = self.node_ty(closure_hir_id);
+        let (closure_def_id, substs) = match ty.sty {
             ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs)),
             ty::Generator(def_id, substs, _) => (def_id, UpvarSubsts::Generator(substs)),
             ty::Error => {
                 // #51714: skip analysis when we have already encountered type errors
                 return;
             }
-            ref t => {
+            _ => {
                 span_bug!(
                     span,
                     "type of closure expr {:?} is not a closure {:?}",
                     closure_hir_id,
-                    t
+                    ty
                 );
             }
         };
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index fde940e..0675fea 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -68,7 +68,7 @@
 
     debug!("check_item_well_formed(it.hir_id={:?}, it.name={})",
            item.hir_id,
-           tcx.item_path_str(def_id));
+           tcx.def_path_str(def_id));
 
     match item.node {
         // Right now we check that every default trait implementation
@@ -506,11 +506,8 @@
                 true
             }
 
-            fn visit_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> bool {
-                if let ty::LazyConst::Evaluated(ty::Const {
-                    val: ConstValue::Param(param),
-                    ..
-                }) = c {
+            fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
+                if let ConstValue::Param(param) = c.val {
                     self.params.insert(param.index);
                 }
                 c.super_visit_with(self)
@@ -618,7 +615,7 @@
     span: Span,
     ty: Ty<'tcx>,
 ) -> Vec<ty::Predicate<'tcx>> {
-    trace!("check_existential_types: {:?}, {:?}", ty, ty.sty);
+    trace!("check_existential_types: {:?}", ty);
     let mut substituted_predicates = Vec::new();
     ty.fold_with(&mut ty::fold::BottomUpFolder {
         tcx: fcx.tcx,
@@ -678,11 +675,8 @@
                                     }
                                 }
 
-                                ty::subst::UnpackedKind::Const(ct) => match ct {
-                                    ty::LazyConst::Evaluated(ty::Const {
-                                        val: ConstValue::Param(_),
-                                        ..
-                                    }) => {}
+                                ty::subst::UnpackedKind::Const(ct) => match ct.val {
+                                    ConstValue::Param(_) => {}
                                     _ => {
                                         tcx.sess
                                             .struct_span_err(
@@ -976,7 +970,7 @@
     if let Some(def_id) = suggested_marker_id {
         err.help(&format!("consider removing `{}` or using a marker such as `{}`",
                           param_name,
-                          tcx.item_path_str(def_id)));
+                          tcx.def_path_str(def_id)));
     }
     err.emit();
 }
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index d001545..4a3d4f3 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -472,7 +472,7 @@
                 instantiated_ty.fold_with(&mut BottomUpFolder {
                     tcx: self.tcx().global_tcx(),
                     fldop: |ty| {
-                        trace!("checking type {:?}: {:#?}", ty, ty.sty);
+                        trace!("checking type {:?}", ty);
                         // find a type parameter
                         if let ty::Param(..) = ty.sty {
                             // look it up in the substitution list
diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs
index 5d86bc5..a2b01e3 100644
--- a/src/librustc_typeck/coherence/builtin.rs
+++ b/src/librustc_typeck/coherence/builtin.rs
@@ -198,8 +198,8 @@
                     if def_a.is_struct() && def_b.is_struct() =>
                 {
                     if def_a != def_b {
-                        let source_path = tcx.item_path_str(def_a.did);
-                        let target_path = tcx.item_path_str(def_b.did);
+                        let source_path = tcx.def_path_str(def_a.did);
+                        let target_path = tcx.def_path_str(def_b.did);
 
                         create_err(
                             &format!(
@@ -388,8 +388,8 @@
             (&ty::Adt(def_a, substs_a), &ty::Adt(def_b, substs_b)) if def_a.is_struct() &&
                                                                       def_b.is_struct() => {
                 if def_a != def_b {
-                    let source_path = gcx.item_path_str(def_a.did);
-                    let target_path = gcx.item_path_str(def_b.did);
+                    let source_path = gcx.def_path_str(def_a.did);
+                    let target_path = gcx.def_path_str(def_b.did);
                     span_err!(gcx.sess,
                               span,
                               E0377,
diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs
index 832c172..d0156db 100644
--- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs
+++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs
@@ -25,7 +25,7 @@
 
         let name_and_namespace = |def_id| {
             let item = self.tcx.associated_item(def_id);
-            (item.ident, Namespace::from(item.kind))
+            (item.ident.modern(), Namespace::from(item.kind))
         };
 
         let impl_items1 = self.tcx.associated_item_def_ids(impl1);
diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs
index 39a2f5d..a5452b4 100644
--- a/src/librustc_typeck/coherence/mod.rs
+++ b/src/librustc_typeck/coherence/mod.rs
@@ -28,7 +28,7 @@
     if let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) {
         debug!("(checking implementation) adding impl for trait '{:?}', item '{}'",
                trait_ref,
-               tcx.item_path_str(impl_def_id));
+               tcx.def_path_str(impl_def_id));
 
         // Skip impls where one of the self type is an error type.
         // This occurs with e.g., resolve failures (#30589).
@@ -204,10 +204,10 @@
                                      E0371,
                                      "the object type `{}` automatically implements the trait `{}`",
                                      trait_ref.self_ty(),
-                                     tcx.item_path_str(trait_def_id))
+                                     tcx.def_path_str(trait_def_id))
                         .span_label(sp, format!("`{}` automatically implements trait `{}`",
                                                 trait_ref.self_ty(),
-                                                tcx.item_path_str(trait_def_id)))
+                                                tcx.def_path_str(trait_def_id)))
                         .emit();
                 }
             }
diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs
index c875b85..7e1c38e 100644
--- a/src/librustc_typeck/coherence/orphan.rs
+++ b/src/librustc_typeck/coherence/orphan.rs
@@ -121,7 +121,7 @@
                                 format!("cross-crate traits with a default impl, like `{}`, \
                                          can only be implemented for a struct/enum type \
                                          defined in the current crate",
-                                        self.tcx.item_path_str(trait_def_id)),
+                                        self.tcx.def_path_str(trait_def_id)),
                                 "can't implement cross-crate trait for type in another crate"
                             ))
                         }
@@ -129,7 +129,7 @@
                     _ => {
                         Some((format!("cross-crate traits with a default impl, like `{}`, can \
                                        only be implemented for a struct/enum type, not `{}`",
-                                      self.tcx.item_path_str(trait_def_id),
+                                      self.tcx.def_path_str(trait_def_id),
                                       self_ty),
                               "can't implement cross-crate trait with a default impl for \
                                non-struct/enum type"))
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index afe6587..10e9613 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -2326,7 +2326,7 @@
         if !item.check_name("enable") {
             let msg = "#[target_feature(..)] only accepts sub-keys of `enable` \
                        currently";
-            tcx.sess.span_err(item.span, &msg);
+            tcx.sess.span_err(item.span(), &msg);
             continue;
         }
 
@@ -2336,7 +2336,7 @@
             None => {
                 let msg = "#[target_feature] attribute must be of the form \
                            #[target_feature(enable = \"..\")]";
-                tcx.sess.span_err(item.span, &msg);
+                tcx.sess.span_err(item.span(), &msg);
                 continue;
             }
         };
@@ -2352,7 +2352,7 @@
                          this target",
                         feature
                     );
-                    let mut err = tcx.sess.struct_span_err(item.span, &msg);
+                    let mut err = tcx.sess.struct_span_err(item.span(), &msg);
 
                     if feature.starts_with("+") {
                         let valid = whitelist.contains_key(&feature[1..]);
@@ -2387,7 +2387,7 @@
                 feature_gate::emit_feature_err(
                     &tcx.sess.parse_sess,
                     feature_gate.as_ref().unwrap(),
-                    item.span,
+                    item.span(),
                     feature_gate::GateIssue::Language,
                     &format!("the target feature `{}` is currently unstable", feature),
                 );
@@ -2549,7 +2549,7 @@
                 } else {
                     span_err!(
                         tcx.sess.diagnostic(),
-                        items[0].span,
+                        items[0].span(),
                         E0535,
                         "invalid argument"
                     );
@@ -2583,7 +2583,7 @@
                 } else if list_contains_name(&items[..], "speed") {
                     OptimizeAttr::Speed
                 } else {
-                    err(items[0].span, "invalid argument");
+                    err(items[0].span(), "invalid argument");
                     OptimizeAttr::None
                 }
             }
diff --git a/src/librustc_typeck/constrained_type_params.rs b/src/librustc_typeck/constrained_type_params.rs
index 4b922c3..c8687f5 100644
--- a/src/librustc_typeck/constrained_type_params.rs
+++ b/src/librustc_typeck/constrained_type_params.rs
@@ -78,12 +78,9 @@
         false
     }
 
-    fn visit_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> bool {
-        if let ty::LazyConst::Evaluated(ty::Const {
-            val: ConstValue::Param(data),
-            ..
-        }) = c {
-            self.parameters.push(Parameter::from(*data));
+    fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
+        if let ConstValue::Param(data) = c.val {
+            self.parameters.push(Parameter::from(data));
         }
         false
     }
diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs
index 49d1115..20eae5d 100644
--- a/src/librustc_typeck/variance/constraints.rs
+++ b/src/librustc_typeck/variance/constraints.rs
@@ -131,7 +131,7 @@
 
     fn build_constraints_for_item(&mut self, def_id: DefId) {
         let tcx = self.tcx();
-        debug!("build_constraints_for_item({})", tcx.item_path_str(def_id));
+        debug!("build_constraints_for_item({})", tcx.def_path_str(def_id));
 
         // Skip items with no generics - there's nothing to infer in them.
         if tcx.generics_of(def_id).count() == 0 {
@@ -452,7 +452,7 @@
     fn add_constraints_from_const(
         &mut self,
         current: &CurrentItem,
-        ct: &ty::LazyConst<'tcx>,
+        ct: &ty::Const<'tcx>,
         variance: VarianceTermPtr<'a>
     ) {
         debug!(
@@ -461,11 +461,9 @@
             variance
         );
 
-        if let ty::LazyConst::Evaluated(ct) = ct {
-            self.add_constraints_from_ty(current, ct.ty, variance);
-            if let ConstValue::Param(ref data) = ct.val {
-                self.add_constraint(current, data.index, variance);
-            }
+        self.add_constraints_from_ty(current, ct.ty, variance);
+        if let ConstValue::Param(ref data) = ct.val {
+            self.add_constraint(current, data.index, variance);
         }
     }
 
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 20fa600..adbe73b 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -435,7 +435,7 @@
                     let new_ty = match &poly_trait.trait_ {
                         &Type::ResolvedPath {
                             ref path,
-                            ref typarams,
+                            ref param_names,
                             ref did,
                             ref is_generic,
                         } => {
@@ -444,7 +444,13 @@
                                                                 .expect("segments were empty");
 
                             let (old_input, old_output) = match last_segment.args {
-                                GenericArgs::AngleBracketed { types, .. } => (types, None),
+                                GenericArgs::AngleBracketed { args, .. } => {
+                                    let types = args.iter().filter_map(|arg| match arg {
+                                        GenericArg::Type(ty) => Some(ty.clone()),
+                                        _ => None,
+                                    }).collect();
+                                    (types, None)
+                                }
                                 GenericArgs::Parenthesized { inputs, output, .. } => {
                                     (inputs, output)
                                 }
@@ -469,7 +475,7 @@
 
                             Type::ResolvedPath {
                                 path: new_path,
-                                typarams: typarams.clone(),
+                                param_names: param_names.clone(),
                                 did: did.clone(),
                                 is_generic: *is_generic,
                             }
@@ -669,7 +675,7 @@
                             match **trait_ {
                                 Type::ResolvedPath {
                                     path: ref trait_path,
-                                    ref typarams,
+                                    ref param_names,
                                     ref did,
                                     ref is_generic,
                                 } => {
@@ -724,7 +730,7 @@
                                         PolyTrait {
                                             trait_: Type::ResolvedPath {
                                                 path: new_trait_path,
-                                                typarams: typarams.clone(),
+                                                param_names: param_names.clone(),
                                                 did: did.clone(),
                                                 is_generic: *is_generic,
                                             },
diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs
index 45e1ea2..6944545 100644
--- a/src/librustdoc/clean/cfg.rs
+++ b/src/librustdoc/clean/cfg.rs
@@ -8,7 +8,7 @@
 use std::ops;
 
 use syntax::symbol::Symbol;
-use syntax::ast::{MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind, LitKind};
+use syntax::ast::{MetaItem, MetaItemKind, NestedMetaItem, LitKind};
 use syntax::parse::ParseSess;
 use syntax::feature_gate::Features;
 
@@ -41,9 +41,9 @@
 impl Cfg {
     /// Parses a `NestedMetaItem` into a `Cfg`.
     fn parse_nested(nested_cfg: &NestedMetaItem) -> Result<Cfg, InvalidCfgError> {
-        match nested_cfg.node {
-            NestedMetaItemKind::MetaItem(ref cfg) => Cfg::parse(cfg),
-            NestedMetaItemKind::Literal(ref lit) => Err(InvalidCfgError {
+        match nested_cfg {
+            NestedMetaItem::MetaItem(ref cfg) => Cfg::parse(cfg),
+            NestedMetaItem::Literal(ref lit) => Err(InvalidCfgError {
                 msg: "unexpected literal",
                 span: lit.span,
             }),
@@ -58,7 +58,13 @@
     /// If the content is not properly formatted, it will return an error indicating what and where
     /// the error is.
     pub fn parse(cfg: &MetaItem) -> Result<Cfg, InvalidCfgError> {
-        let name = cfg.name();
+        let name = match cfg.ident() {
+            Some(ident) => ident.name,
+            None => return Err(InvalidCfgError {
+                msg: "expected a single identifier",
+                span: cfg.span
+            }),
+        };
         match cfg.node {
             MetaItemKind::Word => Ok(Cfg::Cfg(name, None)),
             MetaItemKind::NameValue(ref lit) => match lit.node {
@@ -424,7 +430,7 @@
 
     fn dummy_meta_item_word(name: &str) -> MetaItem {
         MetaItem {
-            ident: Path::from_ident(Ident::from_str(name)),
+            path: Path::from_ident(Ident::from_str(name)),
             node: MetaItemKind::Word,
             span: DUMMY_SP,
         }
@@ -433,12 +439,12 @@
     macro_rules! dummy_meta_item_list {
         ($name:ident, [$($list:ident),* $(,)?]) => {
             MetaItem {
-                ident: Path::from_ident(Ident::from_str(stringify!($name))),
+                path: Path::from_ident(Ident::from_str(stringify!($name))),
                 node: MetaItemKind::List(vec![
                     $(
-                        dummy_spanned(NestedMetaItemKind::MetaItem(
+                        NestedMetaItem::MetaItem(
                             dummy_meta_item_word(stringify!($list)),
-                        )),
+                        ),
                     )*
                 ]),
                 span: DUMMY_SP,
@@ -447,10 +453,10 @@
 
         ($name:ident, [$($list:expr),* $(,)?]) => {
             MetaItem {
-                ident: Path::from_ident(Ident::from_str(stringify!($name))),
+                path: Path::from_ident(Ident::from_str(stringify!($name))),
                 node: MetaItemKind::List(vec![
                     $(
-                        dummy_spanned(NestedMetaItemKind::MetaItem($list)),
+                        NestedMetaItem::MetaItem($list),
                     )*
                 ]),
                 span: DUMMY_SP,
@@ -587,7 +593,7 @@
             assert_eq!(Cfg::parse(&mi), Ok(word_cfg("all")));
 
             let mi = MetaItem {
-                ident: Path::from_ident(Ident::from_str("all")),
+                path: Path::from_ident(Ident::from_str("all")),
                 node: MetaItemKind::NameValue(dummy_spanned(LitKind::Str(
                     Symbol::intern("done"),
                     StrStyle::Cooked,
@@ -622,7 +628,7 @@
     fn test_parse_err() {
         with_globals(|| {
             let mi = MetaItem {
-                ident: Path::from_ident(Ident::from_str("foo")),
+                path: Path::from_ident(Ident::from_str("foo")),
                 node: MetaItemKind::NameValue(dummy_spanned(LitKind::Bool(false))),
                 span: DUMMY_SP,
             };
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index f2bf7ea..ba44817 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -16,12 +16,13 @@
 use rustc::middle::resolve_lifetime as rl;
 use rustc::middle::lang_items;
 use rustc::middle::stability;
-use rustc::mir::interpret::GlobalId;
-use rustc::hir::{self, GenericArg, HirVec};
+use rustc::mir::interpret::{GlobalId, ConstValue};
+use rustc::hir::{self, HirVec};
 use rustc::hir::def::{self, Def, CtorKind};
 use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
-use rustc::ty::subst::{InternalSubsts, SubstsRef};
-use rustc::ty::{self, TyCtxt, Region, RegionVid, Ty, AdtKind};
+use rustc::hir::map::DisambiguatedDefPathData;
+use rustc::ty::subst::{Kind, InternalSubsts, SubstsRef, UnpackedKind};
+use rustc::ty::{self, DefIdTree, TyCtxt, Region, RegionVid, Ty, AdtKind};
 use rustc::ty::fold::TypeFolder;
 use rustc::ty::layout::VariantIdx;
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
@@ -491,7 +492,7 @@
 
     pub fn is_non_exhaustive(&self) -> bool {
         self.attrs.other_attrs.iter()
-            .any(|a| a.name().as_str() == "non_exhaustive")
+            .any(|a| a.check_name("non_exhaustive"))
     }
 
     /// Returns a documentation-level item type from the item.
@@ -507,6 +508,18 @@
             .as_ref()
             .or_else(|| self.stability.as_ref().and_then(|s| s.deprecation.as_ref()))
     }
+    pub fn is_default(&self) -> bool {
+        match self.inner {
+            ItemEnum::MethodItem(ref meth) => {
+                if let Some(defaultness) = meth.defaultness {
+                    defaultness.has_value() && !defaultness.is_final()
+                } else {
+                    false
+                }
+            }
+            _ => false,
+        }
+    }
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
@@ -776,15 +789,15 @@
 impl Attributes {
     /// Extracts the content from an attribute `#[doc(cfg(content))]`.
     fn extract_cfg(mi: &ast::MetaItem) -> Option<&ast::MetaItem> {
-        use syntax::ast::NestedMetaItemKind::MetaItem;
+        use syntax::ast::NestedMetaItem::MetaItem;
 
         if let ast::MetaItemKind::List(ref nmis) = mi.node {
             if nmis.len() == 1 {
-                if let MetaItem(ref cfg_mi) = nmis[0].node {
+                if let MetaItem(ref cfg_mi) = nmis[0] {
                     if cfg_mi.check_name("cfg") {
                         if let ast::MetaItemKind::List(ref cfg_nmis) = cfg_mi.node {
                             if cfg_nmis.len() == 1 {
-                                if let MetaItem(ref content_mi) = cfg_nmis[0].node {
+                                if let MetaItem(ref content_mi) = cfg_nmis[0] {
                                     return Some(content_mi);
                                 }
                             }
@@ -1044,7 +1057,7 @@
         GenericBound::TraitBound(PolyTrait {
             trait_: ResolvedPath {
                 path,
-                typarams: None,
+                param_names: None,
                 did,
                 is_generic: false,
             },
@@ -1088,24 +1101,37 @@
     }
 }
 
-fn external_generic_args(cx: &DocContext<'_>, trait_did: Option<DefId>, has_self: bool,
-                        bindings: Vec<TypeBinding>, substs: SubstsRef<'_>) -> GenericArgs {
-    let lifetimes = substs.regions().filter_map(|v| v.clean(cx)).collect();
-    let types = substs.types().skip(has_self as usize).collect::<Vec<_>>();
+fn external_generic_args(
+    cx: &DocContext<'_>,
+    trait_did: Option<DefId>,
+    has_self: bool,
+    bindings: Vec<TypeBinding>,
+    substs: SubstsRef<'_>,
+) -> GenericArgs {
+    let mut skip_self = has_self;
+    let mut ty_sty = None;
+    let args: Vec<_> = substs.iter().filter_map(|kind| match kind.unpack() {
+        UnpackedKind::Lifetime(lt) => {
+            lt.clean(cx).and_then(|lt| Some(GenericArg::Lifetime(lt)))
+        }
+        UnpackedKind::Type(_) if skip_self => {
+            skip_self = false;
+            None
+        }
+        UnpackedKind::Type(ty) => {
+            ty_sty = Some(&ty.sty);
+            Some(GenericArg::Type(ty.clean(cx)))
+        }
+        UnpackedKind::Const(ct) => Some(GenericArg::Const(ct.clean(cx))),
+    }).collect();
 
     match trait_did {
         // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C
         Some(did) if cx.tcx.lang_items().fn_trait_kind(did).is_some() => {
-            assert_eq!(types.len(), 1);
-            let inputs = match types[0].sty {
-                ty::Tuple(ref tys) => tys.iter().map(|t| t.clean(cx)).collect(),
-                _ => {
-                    return GenericArgs::AngleBracketed {
-                        lifetimes,
-                        types: types.clean(cx),
-                        bindings,
-                    }
-                }
+            assert!(ty_sty.is_some());
+            let inputs = match ty_sty {
+                Some(ty::Tuple(ref tys)) => tys.iter().map(|t| t.clean(cx)).collect(),
+                _ => return GenericArgs::AngleBracketed { args, bindings },
             };
             let output = None;
             // FIXME(#20299) return type comes from a projection now
@@ -1113,17 +1139,10 @@
             //     ty::Tuple(ref v) if v.is_empty() => None, // -> ()
             //     _ => Some(types[1].clean(cx))
             // };
-            GenericArgs::Parenthesized {
-                inputs,
-                output,
-            }
+            GenericArgs::Parenthesized { inputs, output }
         },
         _ => {
-            GenericArgs::AngleBracketed {
-                lifetimes,
-                types: types.clean(cx),
-                bindings,
-            }
+            GenericArgs::AngleBracketed { args, bindings }
         }
     }
 }
@@ -1175,7 +1194,7 @@
             PolyTrait {
                 trait_: ResolvedPath {
                     path,
-                    typarams: None,
+                    param_names: None,
                     did: trait_ref.def_id,
                     is_generic: false,
                 },
@@ -1461,14 +1480,14 @@
     }
 }
 
-impl<'tcx> Clean<GenericParamDef> for ty::GenericParamDef {
+impl Clean<GenericParamDef> for ty::GenericParamDef {
     fn clean(&self, cx: &DocContext<'_>) -> GenericParamDef {
         let (name, kind) = match self.kind {
             ty::GenericParamDefKind::Lifetime => {
                 (self.name.to_string(), GenericParamDefKind::Lifetime)
             }
             ty::GenericParamDefKind::Type { has_default, .. } => {
-                cx.renderinfo.borrow_mut().external_typarams
+                cx.renderinfo.borrow_mut().external_param_names
                              .insert(self.def_id, self.name.clean(cx));
                 let default = if has_default {
                     Some(cx.tcx.type_of(self.def_id).clean(cx))
@@ -1483,7 +1502,10 @@
                 })
             }
             ty::GenericParamDefKind::Const { .. } => {
-                unimplemented!() // FIXME(const_generics)
+                (self.name.clean(cx), GenericParamDefKind::Const {
+                    did: self.def_id,
+                    ty: cx.tcx.type_of(self.def_id).clean(cx),
+                })
             }
         };
 
@@ -1684,9 +1706,7 @@
                         .flat_map(|param| match param.kind {
                             ty::GenericParamDefKind::Lifetime => Some(param.clean(cx)),
                             ty::GenericParamDefKind::Type { .. } => None,
-                            ty::GenericParamDefKind::Const { .. } => {
-                                unimplemented!() // FIXME(const_generics)
-                            }
+                            ty::GenericParamDefKind::Const { .. } => Some(param.clean(cx)),
                         }).chain(simplify::ty_params(stripped_typarams).into_iter())
                         .collect(),
             where_predicates: simplify::where_clauses(cx, where_predicates),
@@ -1699,9 +1719,11 @@
     pub generics: Generics,
     pub decl: FnDecl,
     pub header: hir::FnHeader,
+    pub defaultness: Option<hir::Defaultness>,
 }
 
-impl<'a> Clean<Method> for (&'a hir::MethodSig, &'a hir::Generics, hir::BodyId) {
+impl<'a> Clean<Method> for (&'a hir::MethodSig, &'a hir::Generics, hir::BodyId,
+                            Option<hir::Defaultness>) {
     fn clean(&self, cx: &DocContext<'_>) -> Method {
         let (generics, decl) = enter_impl_trait(cx, || {
             (self.1.clean(cx), (&*self.0.decl, self.2).clean(cx))
@@ -1710,6 +1732,7 @@
             decl,
             generics,
             header: self.0.header,
+            defaultness: self.3,
         }
     }
 }
@@ -2015,7 +2038,7 @@
                                     default.map(|e| print_const_expr(cx, e)))
             }
             hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => {
-                MethodItem((sig, &self.generics, body).clean(cx))
+                MethodItem((sig, &self.generics, body, None).clean(cx))
             }
             hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref names)) => {
                 let (generics, decl) = enter_impl_trait(cx, || {
@@ -2053,7 +2076,7 @@
                                     Some(print_const_expr(cx, expr)))
             }
             hir::ImplItemKind::Method(ref sig, body) => {
-                MethodItem((sig, &self.generics, body).clean(cx))
+                MethodItem((sig, &self.generics, body, Some(self.defaultness)).clean(cx))
             }
             hir::ImplItemKind::Type(ref ty) => TypedefItem(Typedef {
                 type_: ty.clean(cx),
@@ -2136,7 +2159,8 @@
                             abi: sig.abi(),
                             constness,
                             asyncness: hir::IsAsync::NotAsync,
-                        }
+                        },
+                        defaultness: Some(self.defaultness),
                     })
                 } else {
                     TyMethodItem(TyMethod {
@@ -2243,7 +2267,7 @@
     /// Structs/enums/traits (most that'd be an `hir::TyKind::Path`).
     ResolvedPath {
         path: Path,
-        typarams: Option<Vec<GenericBound>>,
+        param_names: Option<Vec<GenericBound>>,
         did: DefId,
         /// `true` if is a `T::Name` path for associated types.
         is_generic: bool,
@@ -2364,12 +2388,15 @@
         }
     }
 
-    pub fn generics(&self) -> Option<&[Type]> {
+    pub fn generics(&self) -> Option<Vec<Type>> {
         match *self {
             ResolvedPath { ref path, .. } => {
                 path.segments.last().and_then(|seg| {
-                    if let GenericArgs::AngleBracketed { ref types, .. } = seg.args {
-                        Some(&**types)
+                    if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
+                        Some(args.iter().filter_map(|arg| match arg {
+                            GenericArg::Type(ty) => Some(ty.clone()),
+                            _ => None,
+                        }).collect())
                     } else {
                         None
                     }
@@ -2550,7 +2577,7 @@
                     promoted: None
                 };
                 let length = match cx.tcx.const_eval(param_env.and(cid)) {
-                    Ok(length) => print_const(cx, ty::LazyConst::Evaluated(length)),
+                    Ok(length) => print_const(cx, length),
                     Err(_) => "_".to_string(),
                 };
                 Array(box ty.clean(cx), length)
@@ -2705,7 +2732,7 @@
             }
             TyKind::TraitObject(ref bounds, ref lifetime) => {
                 match bounds[0].clean(cx).trait_ {
-                    ResolvedPath { path, typarams: None, did, is_generic } => {
+                    ResolvedPath { path, param_names: None, did, is_generic } => {
                         let mut bounds: Vec<self::GenericBound> = bounds[1..].iter().map(|bound| {
                             self::GenericBound::TraitBound(bound.clean(cx),
                                                            hir::TraitBoundModifier::None)
@@ -2713,7 +2740,7 @@
                         if !lifetime.is_elided() {
                             bounds.push(self::GenericBound::Outlives(lifetime.clean(cx)));
                         }
-                        ResolvedPath { path, typarams: Some(bounds), did, is_generic, }
+                        ResolvedPath { path, param_names: Some(bounds), did, is_generic, }
                     }
                     _ => Infer // shouldn't happen
                 }
@@ -2738,14 +2765,14 @@
             ty::Slice(ty) => Slice(box ty.clean(cx)),
             ty::Array(ty, n) => {
                 let mut n = *cx.tcx.lift(&n).expect("array lift failed");
-                if let ty::LazyConst::Unevaluated(def_id, substs) = n {
+                if let ConstValue::Unevaluated(def_id, substs) = n.val {
                     let param_env = cx.tcx.param_env(def_id);
                     let cid = GlobalId {
                         instance: ty::Instance::new(def_id, substs),
                         promoted: None
                     };
                     if let Ok(new_n) = cx.tcx.const_eval(param_env.and(cid)) {
-                        n = ty::LazyConst::Evaluated(new_n);
+                        n = new_n;
                     }
                 };
                 let n = print_const(cx, n);
@@ -2780,7 +2807,7 @@
                                          None, false, vec![], substs);
                 ResolvedPath {
                     path,
-                    typarams: None,
+                    param_names: None,
                     did,
                     is_generic: false,
                 }
@@ -2791,7 +2818,7 @@
                                          None, false, vec![], InternalSubsts::empty());
                 ResolvedPath {
                     path: path,
-                    typarams: None,
+                    param_names: None,
                     did: did,
                     is_generic: false,
                 }
@@ -2812,8 +2839,8 @@
 
                 inline::record_extern_fqn(cx, did, TypeKind::Trait);
 
-                let mut typarams = vec![];
-                reg.clean(cx).map(|b| typarams.push(GenericBound::Outlives(b)));
+                let mut param_names = vec![];
+                reg.clean(cx).map(|b| param_names.push(GenericBound::Outlives(b)));
                 for did in dids {
                     let empty = cx.tcx.intern_substs(&[]);
                     let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
@@ -2822,13 +2849,13 @@
                     let bound = GenericBound::TraitBound(PolyTrait {
                         trait_: ResolvedPath {
                             path,
-                            typarams: None,
+                            param_names: None,
                             did,
                             is_generic: false,
                         },
                         generic_params: Vec::new(),
                     }, hir::TraitBoundModifier::None);
-                    typarams.push(bound);
+                    param_names.push(bound);
                 }
 
                 let mut bindings = vec![];
@@ -2843,7 +2870,7 @@
                     false, bindings, substs);
                 ResolvedPath {
                     path,
-                    typarams: Some(typarams),
+                    param_names: Some(param_names),
                     did,
                     is_generic: false,
                 }
@@ -2920,6 +2947,15 @@
     }
 }
 
+impl<'tcx> Clean<Constant> for ty::Const<'tcx> {
+    fn clean(&self, cx: &DocContext<'_>) -> Constant {
+        Constant {
+            type_: self.ty.clean(cx),
+            expr: format!("{:?}", self.val), // FIXME(const_generics)
+        }
+    }
+}
+
 impl Clean<Item> for hir::StructField {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         let local_did = cx.tcx.hir().local_def_id_from_hir_id(self.hir_id);
@@ -3228,10 +3264,26 @@
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+pub enum GenericArg {
+    Lifetime(Lifetime),
+    Type(Type),
+    Const(Constant),
+}
+
+impl fmt::Display for GenericArg {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            GenericArg::Lifetime(lt) => lt.fmt(f),
+            GenericArg::Type(ty) => ty.fmt(f),
+            GenericArg::Const(ct) => ct.fmt(f),
+        }
+    }
+}
+
+#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
 pub enum GenericArgs {
     AngleBracketed {
-        lifetimes: Vec<Lifetime>,
-        types: Vec<Type>,
+        args: Vec<GenericArg>,
         bindings: Vec<TypeBinding>,
     },
     Parenthesized {
@@ -3249,27 +3301,19 @@
                 output: if output != Type::Tuple(Vec::new()) { Some(output) } else { None }
             }
         } else {
-            let (mut lifetimes, mut types) = (vec![], vec![]);
-            let mut elided_lifetimes = true;
-            for arg in &self.args {
-                match arg {
-                    GenericArg::Lifetime(lt) => {
-                        if !lt.is_elided() {
-                            elided_lifetimes = false;
-                        }
-                        lifetimes.push(lt.clean(cx));
-                    }
-                    GenericArg::Type(ty) => {
-                        types.push(ty.clean(cx));
-                    }
-                    GenericArg::Const(..) => {
-                        unimplemented!() // FIXME(const_generics)
-                    }
-                }
-            }
+            let elide_lifetimes = self.args.iter().all(|arg| match arg {
+                hir::GenericArg::Lifetime(lt) => lt.is_elided(),
+                _ => true,
+            });
             GenericArgs::AngleBracketed {
-                lifetimes: if elided_lifetimes { vec![] } else { lifetimes },
-                types,
+                args: self.args.iter().filter_map(|arg| match arg {
+                    hir::GenericArg::Lifetime(lt) if !elide_lifetimes => {
+                        Some(GenericArg::Lifetime(lt.clean(cx)))
+                    }
+                    hir::GenericArg::Lifetime(_) => None,
+                    hir::GenericArg::Type(ty) => Some(GenericArg::Type(ty.clean(cx))),
+                    hir::GenericArg::Const(ct) => Some(GenericArg::Const(ct.clean(cx))),
+                }).collect(),
                 bindings: self.bindings.clean(cx),
             }
         }
@@ -3293,8 +3337,8 @@
 
 fn strip_type(ty: Type) -> Type {
     match ty {
-        Type::ResolvedPath { path, typarams, did, is_generic } => {
-            Type::ResolvedPath { path: strip_path(&path), typarams, did, is_generic }
+        Type::ResolvedPath { path, param_names, did, is_generic } => {
+            Type::ResolvedPath { path: strip_path(&path), param_names, did, is_generic }
         }
         Type::Tuple(inner_tys) => {
             Type::Tuple(inner_tys.iter().map(|t| strip_type(t.clone())).collect())
@@ -3321,9 +3365,8 @@
         PathSegment {
             name: s.name.clone(),
             args: GenericArgs::AngleBracketed {
-                lifetimes: Vec::new(),
-                types: Vec::new(),
-                bindings: Vec::new(),
+                args: vec![],
+                bindings: vec![],
             }
         }
     }).collect();
@@ -3474,7 +3517,7 @@
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
 pub struct Constant {
     pub type_: Type,
     pub expr: String,
@@ -3682,7 +3725,7 @@
     fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
 
         let please_inline = self.vis.node.is_pub() && self.attrs.iter().any(|a| {
-            a.name() == "doc" && match a.meta_item_list() {
+            a.check_name("doc") && match a.meta_item_list() {
                 Some(l) => attr::list_contains_name(&l, "inline"),
                 None => false,
             }
@@ -3721,7 +3764,7 @@
         // #[doc(no_inline)] attribute is present.
         // Don't inline doc(hidden) imports so they can be stripped at a later stage.
         let mut denied = !self.vis.node.is_pub() || self.attrs.iter().any(|a| {
-            a.name() == "doc" && match a.meta_item_list() {
+            a.check_name("doc") && match a.meta_item_list() {
                 Some(l) => attr::list_contains_name(&l, "no_inline") ||
                            attr::list_contains_name(&l, "hidden"),
                 None => false,
@@ -3899,16 +3942,16 @@
     }
 }
 
-fn print_const(cx: &DocContext<'_>, n: ty::LazyConst<'_>) -> String {
-    match n {
-        ty::LazyConst::Unevaluated(def_id, _) => {
+fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
+    match n.val {
+        ConstValue::Unevaluated(def_id, _) => {
             if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(def_id) {
                 print_const_expr(cx, cx.tcx.hir().body_owned_by(hir_id))
             } else {
                 inline::print_inlined_const(cx, def_id)
             }
         },
-        ty::LazyConst::Evaluated(n) => {
+        _ => {
             let mut s = String::new();
             ::rustc::mir::fmt_const_val(&mut s, n).expect("fmt_const_val failed");
             // array lengths are obviously usize
@@ -3954,7 +3997,7 @@
         _ => false,
     };
     let did = register_def(&*cx, path.def);
-    ResolvedPath { path: path, typarams: None, did: did, is_generic: is_generic }
+    ResolvedPath { path: path, param_names: None, did: did, is_generic: is_generic }
 }
 
 pub fn register_def(cx: &DocContext<'_>, def: Def) -> DefId {
@@ -3971,7 +4014,7 @@
         Def::ForeignTy(i) => (i, TypeKind::Foreign),
         Def::Const(i) => (i, TypeKind::Const),
         Def::Static(i, _) => (i, TypeKind::Static),
-        Def::Variant(i) => (cx.tcx.parent_def_id(i).expect("cannot get parent def id"),
+        Def::Variant(i) => (cx.tcx.parent(i).expect("cannot get parent def id"),
                             TypeKind::Enum),
         Def::Macro(i, mac_kind) => match mac_kind {
             MacroKind::Bang => (i, TypeKind::Macro),
@@ -4223,32 +4266,113 @@
     }
 }
 
-pub fn get_path_for_type<F>(tcx: TyCtxt<'_, '_, '_>, def_id: DefId, def_ctor: F) -> hir::Path
-where F: Fn(DefId) -> Def {
-    #[derive(Debug)]
-    struct AbsolutePathBuffer {
-        names: Vec<String>,
+pub fn get_path_for_type(
+    tcx: TyCtxt<'_, '_, '_>,
+    def_id: DefId,
+    def_ctor: impl Fn(DefId) -> Def,
+) -> hir::Path {
+    use rustc::ty::print::Printer;
+
+    struct AbsolutePathPrinter<'a, 'tcx> {
+        tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 
-    impl ty::item_path::ItemPathBuffer for AbsolutePathBuffer {
-        fn root_mode(&self) -> &ty::item_path::RootMode {
-            const ABSOLUTE: &'static ty::item_path::RootMode = &ty::item_path::RootMode::Absolute;
-            ABSOLUTE
+    impl Printer<'tcx, 'tcx> for AbsolutePathPrinter<'_, 'tcx> {
+        type Error = !;
+
+        type Path = Vec<String>;
+        type Region = ();
+        type Type = ();
+        type DynExistential = ();
+
+        fn tcx(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
+            self.tcx
         }
 
-        fn push(&mut self, text: &str) {
-            self.names.push(text.to_owned());
+        fn print_region(
+            self,
+            _region: ty::Region<'_>,
+        ) -> Result<Self::Region, Self::Error> {
+            Ok(())
+        }
+
+        fn print_type(
+            self,
+            _ty: Ty<'tcx>,
+        ) -> Result<Self::Type, Self::Error> {
+            Ok(())
+        }
+
+        fn print_dyn_existential(
+            self,
+            _predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
+        ) -> Result<Self::DynExistential, Self::Error> {
+            Ok(())
+        }
+
+        fn path_crate(
+            self,
+            cnum: CrateNum,
+        ) -> Result<Self::Path, Self::Error> {
+            Ok(vec![self.tcx.original_crate_name(cnum).to_string()])
+        }
+        fn path_qualified(
+            self,
+            self_ty: Ty<'tcx>,
+            trait_ref: Option<ty::TraitRef<'tcx>>,
+        ) -> Result<Self::Path, Self::Error> {
+            // This shouldn't ever be needed, but just in case:
+            Ok(vec![match trait_ref {
+                Some(trait_ref) => format!("{:?}", trait_ref),
+                None => format!("<{}>", self_ty),
+            }])
+        }
+
+        fn path_append_impl(
+            self,
+            print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+            _disambiguated_data: &DisambiguatedDefPathData,
+            self_ty: Ty<'tcx>,
+            trait_ref: Option<ty::TraitRef<'tcx>>,
+        ) -> Result<Self::Path, Self::Error> {
+            let mut path = print_prefix(self)?;
+
+            // This shouldn't ever be needed, but just in case:
+            path.push(match trait_ref {
+                Some(trait_ref) => {
+                    format!("<impl {} for {}>", trait_ref, self_ty)
+                }
+                None => format!("<impl {}>", self_ty),
+            });
+
+            Ok(path)
+        }
+        fn path_append(
+            self,
+            print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+            disambiguated_data: &DisambiguatedDefPathData,
+        ) -> Result<Self::Path, Self::Error> {
+            let mut path = print_prefix(self)?;
+            path.push(disambiguated_data.data.as_interned_str().to_string());
+            Ok(path)
+        }
+        fn path_generic_args(
+            self,
+            print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+            _args: &[Kind<'tcx>],
+        ) -> Result<Self::Path, Self::Error> {
+            print_prefix(self)
         }
     }
 
-    let mut apb = AbsolutePathBuffer { names: vec![] };
-
-    tcx.push_item_path(&mut apb, def_id, false);
+    let names = AbsolutePathPrinter { tcx: tcx.global_tcx() }
+        .print_def_path(def_id, &[])
+        .unwrap();
 
     hir::Path {
         span: DUMMY_SP,
         def: def_ctor(def_id),
-        segments: hir::HirVec::from_vec(apb.names.iter().map(|s| hir::PathSegment {
+        segments: hir::HirVec::from_vec(names.iter().map(|s| hir::PathSegment {
             ident: ast::Ident::from_str(&s),
             hir_id: None,
             def: None,
@@ -4299,9 +4423,9 @@
         match bound.clone() {
             GenericBound::Outlives(l) => SimpleBound::Outlives(l),
             GenericBound::TraitBound(t, mod_) => match t.trait_ {
-                Type::ResolvedPath { path, typarams, .. } => {
+                Type::ResolvedPath { path, param_names, .. } => {
                     SimpleBound::TraitBound(path.segments,
-                                            typarams
+                                            param_names
                                                 .map_or_else(|| Vec::new(), |v| v.iter()
                                                         .map(|p| SimpleBound::from(p.clone()))
                                                         .collect()),
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 47dbbc2..1982a16 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -236,8 +236,16 @@
                 ty::GenericParamDefKind::Type { .. } => {
                     args.push(hir::GenericArg::Type(self.ty_param_to_ty(param.clone())));
                 }
-                ty::GenericParamDefKind::Const { .. } => {
-                    unimplemented!() // FIXME(const_generics)
+                ty::GenericParamDefKind::Const => {
+                    args.push(hir::GenericArg::Const(hir::ConstArg {
+                        value: hir::AnonConst {
+                            hir_id: hir::DUMMY_HIR_ID,
+                            body: hir::BodyId {
+                                hir_id: hir::DUMMY_HIR_ID,
+                            }
+                        },
+                        span: DUMMY_SP,
+                    }))
                 }
             }
         }
@@ -521,8 +529,7 @@
             for attr in krate.module.as_ref().unwrap().attrs.lists("doc") {
                 let diag = ctxt.sess().diagnostic();
 
-                let name = attr.name().map(|s| s.as_str());
-                let name = name.as_ref().map(|s| &s[..]);
+                let name = attr.ident_str();
                 if attr.is_word() {
                     if name == Some("no_default_passes") {
                         report_deprecated_attr("no_default_passes", diag);
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index d204a17..3d8af7c 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -45,6 +45,7 @@
 /// Wrapper struct for emitting a comma-separated list of items
 pub struct CommaSep<'a, T>(pub &'a [T]);
 pub struct AbiSpace(pub Abi);
+pub struct DefaultSpace(pub bool);
 
 /// Wrapper struct for properly emitting a function or method declaration.
 pub struct Function<'a> {
@@ -259,6 +260,14 @@
     }
 }
 
+impl fmt::Display for clean::Constant {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Display::fmt(&self.expr, f)?;
+        f.write_str(": ")?;
+        fmt::Display::fmt(&self.type_, f)
+    }
+}
+
 impl fmt::Display for clean::PolyTrait {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         if !self.generic_params.is_empty() {
@@ -300,32 +309,23 @@
 impl fmt::Display for clean::GenericArgs {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match *self {
-            clean::GenericArgs::AngleBracketed {
-                ref lifetimes, ref types, ref bindings
-            } => {
-                if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() {
+            clean::GenericArgs::AngleBracketed { ref args, ref bindings } => {
+                if !args.is_empty() || !bindings.is_empty() {
                     if f.alternate() {
                         f.write_str("<")?;
                     } else {
                         f.write_str("&lt;")?;
                     }
                     let mut comma = false;
-                    for lifetime in lifetimes {
-                        if comma {
-                            f.write_str(", ")?;
-                        }
-                        comma = true;
-                        write!(f, "{}", *lifetime)?;
-                    }
-                    for ty in types {
+                    for arg in args {
                         if comma {
                             f.write_str(", ")?;
                         }
                         comma = true;
                         if f.alternate() {
-                            write!(f, "{:#}", *ty)?;
+                            write!(f, "{:#}", *arg)?;
                         } else {
-                            write!(f, "{}", *ty)?;
+                            write!(f, "{}", *arg)?;
                         }
                     }
                     for binding in bindings {
@@ -521,8 +521,8 @@
 
 /// Helper to render type parameters
 fn tybounds(w: &mut fmt::Formatter<'_>,
-            typarams: &Option<Vec<clean::GenericBound>>) -> fmt::Result {
-    match *typarams {
+            param_names: &Option<Vec<clean::GenericBound>>) -> fmt::Result {
+    match *param_names {
         Some(ref params) => {
             for param in params {
                 write!(w, " + ")?;
@@ -559,13 +559,13 @@
         clean::Generic(ref name) => {
             f.write_str(name)
         }
-        clean::ResolvedPath{ did, ref typarams, ref path, is_generic } => {
-            if typarams.is_some() {
+        clean::ResolvedPath{ did, ref param_names, ref path, is_generic } => {
+            if param_names.is_some() {
                 f.write_str("dyn ")?;
             }
             // Paths like T::Output and Self::Output should be rendered with all segments
             resolved_path(f, did, path, is_generic, use_absolute)?;
-            tybounds(f, typarams)
+            tybounds(f, param_names)
         }
         clean::Infer => write!(f, "_"),
         clean::Primitive(prim) => primitive_link(f, prim, prim.as_str()),
@@ -663,7 +663,7 @@
                         }
                     }
                 }
-                clean::ResolvedPath { typarams: Some(ref v), .. } if !v.is_empty() => {
+                clean::ResolvedPath { param_names: Some(ref v), .. } if !v.is_empty() => {
                     write!(f, "{}{}{}(", amp, lt, m)?;
                     fmt_type(&ty, f, use_absolute)?;
                     write!(f, ")")
@@ -717,7 +717,7 @@
                 //        the ugliness comes from inlining across crates where
                 //        everything comes in as a fully resolved QPath (hard to
                 //        look at).
-                box clean::ResolvedPath { did, ref typarams, .. } => {
+                box clean::ResolvedPath { did, ref param_names, .. } => {
                     match href(did) {
                         Some((ref url, _, ref path)) if !f.alternate() => {
                             write!(f,
@@ -731,8 +731,8 @@
                         _ => write!(f, "{}", name)?,
                     }
 
-                    // FIXME: `typarams` are not rendered, and this seems bad?
-                    drop(typarams);
+                    // FIXME: `param_names` are not rendered, and this seems bad?
+                    drop(param_names);
                     Ok(())
                 }
                 _ => {
@@ -771,7 +771,7 @@
             fmt::Display::fmt(ty, f)?;
         } else {
             match *ty {
-                clean::ResolvedPath { typarams: None, ref path, is_generic: false, .. } => {
+                clean::ResolvedPath { param_names: None, ref path, is_generic: false, .. } => {
                     let last = path.segments.last().unwrap();
                     fmt::Display::fmt(&last.name, f)?;
                     fmt::Display::fmt(&last.args, f)?;
@@ -1057,3 +1057,13 @@
         }
     }
 }
+
+impl fmt::Display for DefaultSpace {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        if self.0 {
+            write!(f, "default ")
+        } else {
+            Ok(())
+        }
+    }
+}
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index d711e45..445ce06 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -61,7 +61,7 @@
 use crate::fold::DocFolder;
 use crate::html::escape::Escape;
 use crate::html::format::{AsyncSpace, ConstnessSpace};
-use crate::html::format::{GenericBounds, WhereClause, href, AbiSpace};
+use crate::html::format::{GenericBounds, WhereClause, href, AbiSpace, DefaultSpace};
 use crate::html::format::{VisSpace, Function, UnsafetySpace, MutableSpace};
 use crate::html::format::fmt_impl_for_trait_page;
 use crate::html::item_type::ItemType;
@@ -271,7 +271,7 @@
     /// Mapping of typaram ids to the name of the type parameter. This is used
     /// when pretty-printing a type (so pretty-printing doesn't have to
     /// painfully maintain a context like this)
-    pub typarams: FxHashMap<DefId, String>,
+    pub param_names: FxHashMap<DefId, String>,
 
     /// Maps a type ID to all known implementations for that type. This is only
     /// recognized for intra-crate `ResolvedPath` types, and is used to print
@@ -368,7 +368,7 @@
 pub struct RenderInfo {
     pub inlined: FxHashSet<DefId>,
     pub external_paths: crate::core::ExternalPaths,
-    pub external_typarams: FxHashMap<DefId, String>,
+    pub external_param_names: FxHashMap<DefId, String>,
     pub exact_paths: FxHashMap<DefId, Vec<String>>,
     pub access_levels: AccessLevels<DefId>,
     pub deref_trait_did: Option<DefId>,
@@ -562,8 +562,7 @@
     // going to emit HTML
     if let Some(attrs) = krate.module.as_ref().map(|m| &m.attrs) {
         for attr in attrs.lists("doc") {
-            let name = attr.name().map(|s| s.as_str());
-            match (name.as_ref().map(|s| &s[..]), attr.value_str()) {
+            match (attr.ident_str(), attr.value_str()) {
                 (Some("html_favicon_url"), Some(s)) => {
                     scx.layout.favicon = s.to_string();
                 }
@@ -602,7 +601,7 @@
     let RenderInfo {
         inlined: _,
         external_paths,
-        external_typarams,
+        external_param_names,
         exact_paths,
         access_levels,
         deref_trait_did,
@@ -636,7 +635,7 @@
         deref_mut_trait_did,
         owned_box_did,
         masked_crates: mem::replace(&mut krate.masked_crates, Default::default()),
-        typarams: external_typarams,
+        param_names: external_param_names,
         aliases: Default::default(),
     };
 
@@ -1117,11 +1116,7 @@
     // with rustdoc running in parallel.
     all_indexes.sort();
     let mut w = try_err!(File::create(&dst), &dst);
-    if options.enable_minification {
-        try_err!(writeln!(&mut w, "var N=null,E=\"\",T=\"t\",U=\"u\",searchIndex={{}};"), &dst);
-    } else {
-        try_err!(writeln!(&mut w, "var searchIndex={{}};"), &dst);
-    }
+    try_err!(writeln!(&mut w, "var N=null,E=\"\",T=\"t\",U=\"u\",searchIndex={{}};"), &dst);
     try_err!(write_minify_replacer(&mut w,
                                    &format!("{}\n{}", variables.join(""), all_indexes.join("\n")),
                                    options.enable_minification),
@@ -1756,7 +1751,7 @@
                 clean::GenericParamDefKind::Lifetime => {}
                 clean::GenericParamDefKind::Type { did, .. } |
                 clean::GenericParamDefKind::Const { did, .. } => {
-                    self.typarams.insert(did, param.name.clone());
+                    self.param_names.insert(did, param.name.clone());
                 }
             }
         }
@@ -3434,11 +3429,12 @@
             }
         };
         let mut header_len = format!(
-            "{}{}{}{}{:#}fn {}{:#}",
+            "{}{}{}{}{}{:#}fn {}{:#}",
             VisSpace(&meth.visibility),
             ConstnessSpace(header.constness),
             UnsafetySpace(header.unsafety),
             AsyncSpace(header.asyncness),
+            DefaultSpace(meth.is_default()),
             AbiSpace(header.abi),
             name,
             *g
@@ -3450,12 +3446,13 @@
             (0, true)
         };
         render_attributes(w, meth)?;
-        write!(w, "{}{}{}{}{}fn <a href='{href}' class='fnname'>{name}</a>\
+        write!(w, "{}{}{}{}{}{}fn <a href='{href}' class='fnname'>{name}</a>\
                    {generics}{decl}{where_clause}",
                VisSpace(&meth.visibility),
                ConstnessSpace(header.constness),
                UnsafetySpace(header.unsafety),
                AsyncSpace(header.asyncness),
+               DefaultSpace(meth.is_default()),
                AbiSpace(header.abi),
                href = href,
                name = name,
@@ -3718,19 +3715,19 @@
 }
 
 fn render_attribute(attr: &ast::MetaItem) -> Option<String> {
-    let name = attr.name();
+    let path = attr.path.to_string();
 
     if attr.is_word() {
-        Some(name.to_string())
+        Some(path)
     } else if let Some(v) = attr.value_str() {
-        Some(format!("{} = {:?}", name, v.as_str()))
+        Some(format!("{} = {:?}", path, v.as_str()))
     } else if let Some(values) = attr.meta_item_list() {
         let display: Vec<_> = values.iter().filter_map(|attr| {
             attr.meta_item().and_then(|mi| render_attribute(mi))
         }).collect();
 
         if display.len() > 0 {
-            Some(format!("{}({})", name, display.join(", ")))
+            Some(format!("{}({})", path, display.join(", ")))
         } else {
             None
         }
@@ -3754,8 +3751,7 @@
     let mut attrs = String::new();
 
     for attr in &it.attrs.other_attrs {
-        let name = attr.name();
-        if !ATTRIBUTE_WHITELIST.contains(&&*name.as_str()) {
+        if !attr.ident_str().map_or(false, |name| ATTRIBUTE_WHITELIST.contains(&name)) {
             continue;
         }
         if let Some(s) = render_attribute(&attr.meta().unwrap()) {
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index 1849e53..fef6910 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -2077,16 +2077,22 @@
     }
 
     var toggle = createSimpleToggle(false);
+    var hideMethodDocs = getCurrentValue("rustdoc-method-docs") !== "false";
+    var pageId = getPageId();
 
     var func = function(e) {
         var next = e.nextElementSibling;
         if (!next) {
             return;
         }
-        if (hasClass(next, "docblock") ||
-            (hasClass(next, "stability") &&
-             hasClass(next.nextElementSibling, "docblock"))) {
-            insertAfter(toggle.cloneNode(true), e.childNodes[e.childNodes.length - 1]);
+        if (hasClass(next, "docblock") === true ||
+            (hasClass(next, "stability") === true &&
+             hasClass(next.nextElementSibling, "docblock") === true)) {
+            var newToggle = toggle.cloneNode(true);
+            insertAfter(newToggle, e.childNodes[e.childNodes.length - 1]);
+            if (hideMethodDocs === true && hasClass(e, "method") === true) {
+                collapseDocs(newToggle, "hide", pageId);
+            }
         }
     };
 
@@ -2107,17 +2113,16 @@
     onEachLazy(document.getElementsByClassName("associatedconstant"), func);
     onEachLazy(document.getElementsByClassName("impl"), funcImpl);
     var impl_call = function() {};
-    if (getCurrentValue("rustdoc-method-docs") !== "false") {
+    if (hideMethodDocs === true) {
         impl_call = function(e, newToggle, pageId) {
             if (e.id.match(/^impl(?:-\d+)?$/) === null) {
                 // Automatically minimize all non-inherent impls
-                if (hasClass(e, "impl")) {
+                if (hasClass(e, "impl") === true) {
                     collapseDocs(newToggle, "hide", pageId);
                 }
             }
         };
     }
-    var pageId = getPageId();
     var newToggle = document.createElement("a");
     newToggle.href = "javascript:void(0)";
     newToggle.className = "collapse-toggle hidden-default collapsed";
@@ -2163,7 +2168,7 @@
             var inner_toggle = newToggle.cloneNode(true);
             inner_toggle.onclick = toggleClicked;
             e.insertBefore(inner_toggle, e.firstChild);
-            impl_call(e, inner_toggle, pageId);
+            impl_call(e.previousSibling, inner_toggle, pageId);
         }
     });
 
@@ -2265,30 +2270,6 @@
     onEachLazy(document.getElementsByClassName("docblock"), buildToggleWrapper);
     onEachLazy(document.getElementsByClassName("sub-variant"), buildToggleWrapper);
 
-    // In the search display, allows to switch between tabs.
-    function printTab(nb) {
-        if (nb === 0 || nb === 1 || nb === 2) {
-            currentTab = nb;
-        }
-        var nb_copy = nb;
-        onEachLazy(document.getElementById("titles").childNodes, function(elem) {
-            if (nb_copy === 0) {
-                addClass(elem, "selected");
-            } else {
-                removeClass(elem, "selected");
-            }
-            nb_copy -= 1;
-        });
-        onEachLazy(document.getElementById("results").childNodes, function(elem) {
-            if (nb === 0) {
-                elem.style.display = "";
-            } else {
-                elem.style.display = "none";
-            }
-            nb -= 1;
-        });
-    }
-
     function createToggleWrapper(tog) {
         var span = document.createElement("span");
         span.className = "toggle-label";
@@ -2374,6 +2355,30 @@
         };
     });
 
+    // In the search display, allows to switch between tabs.
+    function printTab(nb) {
+        if (nb === 0 || nb === 1 || nb === 2) {
+            currentTab = nb;
+        }
+        var nb_copy = nb;
+        onEachLazy(document.getElementById("titles").childNodes, function(elem) {
+            if (nb_copy === 0) {
+                addClass(elem, "selected");
+            } else {
+                removeClass(elem, "selected");
+            }
+            nb_copy -= 1;
+        });
+        onEachLazy(document.getElementById("results").childNodes, function(elem) {
+            if (nb === 0) {
+                elem.style.display = "";
+            } else {
+                elem.style.display = "none";
+            }
+            nb -= 1;
+        });
+    }
+
     function putBackSearch(search_input) {
         if (search_input.value !== "") {
             addClass(main, "hidden");
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index f11e268..fccf5a6 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -5,8 +5,10 @@
 
 #![feature(bind_by_move_pattern_guards)]
 #![feature(rustc_private)]
+#![feature(arbitrary_self_types)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
+#![feature(in_band_lifetimes)]
 #![feature(nll)]
 #![feature(set_stdio)]
 #![feature(test)]
@@ -16,6 +18,7 @@
 #![feature(const_fn)]
 #![feature(drain_filter)]
 #![feature(inner_deref)]
+#![feature(never_type)]
 
 #![recursion_limit="256"]
 
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index fefff1f..7c1a614 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -1,7 +1,8 @@
-use rustc::lint as lint;
-use rustc::hir;
-use rustc::hir::def::Def;
+use errors::Applicability;
+use rustc::hir::def::{Def, Namespace::{self, *}, PerNS};
 use rustc::hir::def_id::DefId;
+use rustc::hir;
+use rustc::lint as lint;
 use rustc::ty;
 use syntax;
 use syntax::ast::{self, Ident};
@@ -35,22 +36,9 @@
     }
 }
 
-#[derive(Debug)]
-enum PathKind {
-    /// Either a value or type, but not a macro
-    Unknown,
-    /// Macro
-    Macro,
-    /// Values, functions, consts, statics (everything in the value namespace)
-    Value,
-    /// Types, traits (everything in the type namespace)
-    Type,
-}
-
 struct LinkCollector<'a, 'tcx> {
     cx: &'a DocContext<'tcx>,
     mod_ids: Vec<ast::NodeId>,
-    is_nightly_build: bool,
 }
 
 impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
@@ -58,16 +46,14 @@
         LinkCollector {
             cx,
             mod_ids: Vec::new(),
-            is_nightly_build: UnstableFeatures::from_environment().is_nightly_build(),
         }
     }
 
-    /// Resolves a given string as a path, along with whether or not it is
-    /// in the value namespace. Also returns an optional URL fragment in the case
-    /// of variants and methods.
+    /// Resolves a string as a path within a particular namespace. Also returns an optional
+    /// URL fragment in the case of variants and methods.
     fn resolve(&self,
                path_str: &str,
-               is_val: bool,
+               ns: Namespace,
                current_item: &Option<String>,
                parent_id: Option<ast::NodeId>)
         -> Result<(Def, Option<String>), ()>
@@ -78,11 +64,11 @@
         // path.
         if let Some(id) = parent_id.or(self.mod_ids.last().cloned()) {
             // FIXME: `with_scope` requires the `NodeId` of a module.
-            let result = cx.enter_resolver(|resolver| resolver.with_scope(id,
-                |resolver| {
-                    resolver.resolve_str_path_error(DUMMY_SP,
-                                                    &path_str, is_val)
-            }));
+            let result = cx.enter_resolver(|resolver| {
+                resolver.with_scope(id, |resolver| {
+                    resolver.resolve_str_path_error(DUMMY_SP, &path_str, ns == ValueNS)
+                })
+            });
 
             if let Ok(result) = result {
                 // In case this is a trait item, skip the
@@ -95,16 +81,16 @@
                     _ => return Ok((result.def, None))
                 };
 
-                if value != is_val {
+                if value != (ns == ValueNS) {
                     return Err(())
                 }
-            } else if let Some(prim) = is_primitive(path_str, is_val) {
+            } else if let Some(prim) = is_primitive(path_str, ns) {
                 return Ok((prim, Some(path_str.to_owned())))
             } else {
                 // If resolution failed, it may still be a method
                 // because methods are not handled by the resolver
                 // If so, bail when we're not looking for a value.
-                if !is_val {
+                if ns != ValueNS {
                     return Err(())
                 }
             }
@@ -128,7 +114,7 @@
                     path = name.clone();
                 }
             }
-            if let Some(prim) = is_primitive(&path, false) {
+            if let Some(prim) = is_primitive(&path, TypeNS) {
                 let did = primitive_impl(cx, &path).ok_or(())?;
                 return cx.tcx.associated_items(did)
                     .find(|item| item.ident.name == item_name)
@@ -152,8 +138,8 @@
                                      .find(|item| item.ident.name == item_name);
                     if let Some(item) = item {
                         let out = match item.kind {
-                            ty::AssociatedKind::Method if is_val => "method",
-                            ty::AssociatedKind::Const if is_val => "associatedconstant",
+                            ty::AssociatedKind::Method if ns == ValueNS => "method",
+                            ty::AssociatedKind::Const if ns == ValueNS => "associatedconstant",
                             _ => return Err(())
                         };
                         Ok((ty.def, Some(format!("{}.{}", out, item_name))))
@@ -190,9 +176,9 @@
                                  .find(|item| item.ident.name == item_name);
                     if let Some(item) = item {
                         let kind = match item.kind {
-                            ty::AssociatedKind::Const if is_val => "associatedconstant",
-                            ty::AssociatedKind::Type if !is_val => "associatedtype",
-                            ty::AssociatedKind::Method if is_val => {
+                            ty::AssociatedKind::Const if ns == ValueNS => "associatedconstant",
+                            ty::AssociatedKind::Type if ns == TypeNS => "associatedtype",
+                            ty::AssociatedKind::Method if ns == ValueNS => {
                                 if item.defaultness.has_value() {
                                     "method"
                                 } else {
@@ -279,39 +265,41 @@
 
         look_for_tests(&cx, &dox, &item, true);
 
-        if !self.is_nightly_build {
-            return None;
-        }
-
         for (ori_link, link_range) in markdown_links(&dox) {
             // Bail early for real links.
             if ori_link.contains('/') {
                 continue;
             }
+
+            // [] is mostly likely not supposed to be a link
+            if ori_link.is_empty() {
+                continue;
+            }
+
             let link = ori_link.replace("`", "");
             let (def, fragment) = {
-                let mut kind = PathKind::Unknown;
+                let mut kind = None;
                 let path_str = if let Some(prefix) =
                     ["struct@", "enum@", "type@",
                      "trait@", "union@"].iter()
                                       .find(|p| link.starts_with(**p)) {
-                    kind = PathKind::Type;
+                    kind = Some(TypeNS);
                     link.trim_start_matches(prefix)
                 } else if let Some(prefix) =
                     ["const@", "static@",
                      "value@", "function@", "mod@",
                      "fn@", "module@", "method@"]
                         .iter().find(|p| link.starts_with(**p)) {
-                    kind = PathKind::Value;
+                    kind = Some(ValueNS);
                     link.trim_start_matches(prefix)
                 } else if link.ends_with("()") {
-                    kind = PathKind::Value;
+                    kind = Some(ValueNS);
                     link.trim_end_matches("()")
                 } else if link.starts_with("macro@") {
-                    kind = PathKind::Macro;
+                    kind = Some(MacroNS);
                     link.trim_start_matches("macro@")
                 } else if link.ends_with('!') {
-                    kind = PathKind::Macro;
+                    kind = Some(MacroNS);
                     link.trim_end_matches('!')
                 } else {
                     &link[..]
@@ -323,8 +311,8 @@
                 }
 
                 match kind {
-                    PathKind::Value => {
-                        if let Ok(def) = self.resolve(path_str, true, &current_item, parent_node) {
+                    Some(ns @ ValueNS) => {
+                        if let Ok(def) = self.resolve(path_str, ns, &current_item, parent_node) {
                             def
                         } else {
                             resolution_failure(cx, &item.attrs, path_str, &dox, link_range);
@@ -334,8 +322,8 @@
                             continue;
                         }
                     }
-                    PathKind::Type => {
-                        if let Ok(def) = self.resolve(path_str, false, &current_item, parent_node) {
+                    Some(ns @ TypeNS) => {
+                        if let Ok(def) = self.resolve(path_str, ns, &current_item, parent_node) {
                             def
                         } else {
                             resolution_failure(cx, &item.attrs, path_str, &dox, link_range);
@@ -343,62 +331,49 @@
                             continue;
                         }
                     }
-                    PathKind::Unknown => {
+                    None => {
                         // Try everything!
-                        if let Some(macro_def) = macro_resolve(cx, path_str) {
-                            if let Ok(type_def) =
-                                self.resolve(path_str, false, &current_item, parent_node)
-                            {
-                                let (type_kind, article, type_disambig)
-                                    = type_ns_kind(type_def.0, path_str);
-                                ambiguity_error(cx, &item.attrs, path_str,
-                                                article, type_kind, &type_disambig,
-                                                "a", "macro", &format!("macro@{}", path_str));
-                                continue;
-                            } else if let Ok(value_def) =
-                                self.resolve(path_str, true, &current_item, parent_node)
-                            {
-                                let (value_kind, value_disambig)
-                                    = value_ns_kind(value_def.0, path_str)
-                                        .expect("struct and mod cases should have been \
-                                                 caught in previous branch");
-                                ambiguity_error(cx, &item.attrs, path_str,
-                                                "a", value_kind, &value_disambig,
-                                                "a", "macro", &format!("macro@{}", path_str));
-                            }
-                            (macro_def, None)
-                        } else if let Ok(type_def) =
-                            self.resolve(path_str, false, &current_item, parent_node)
-                        {
-                            // It is imperative we search for not-a-value first
-                            // Otherwise we will find struct ctors for when we are looking
-                            // for structs, and the link won't work if there is something in
-                            // both namespaces.
-                            if let Ok(value_def) =
-                                self.resolve(path_str, true, &current_item, parent_node)
-                            {
-                                let kind = value_ns_kind(value_def.0, path_str);
-                                if let Some((value_kind, value_disambig)) = kind {
-                                    let (type_kind, article, type_disambig)
-                                        = type_ns_kind(type_def.0, path_str);
-                                    ambiguity_error(cx, &item.attrs, path_str,
-                                                    article, type_kind, &type_disambig,
-                                                    "a", value_kind, &value_disambig);
-                                    continue;
-                                }
-                            }
-                            type_def
-                        } else if let Ok(value_def) =
-                            self.resolve(path_str, true, &current_item, parent_node)
-                        {
-                            value_def
-                        } else {
+                        let candidates = PerNS {
+                            macro_ns: macro_resolve(cx, path_str).map(|def| (def, None)),
+                            type_ns: self
+                                .resolve(path_str, TypeNS, &current_item, parent_node)
+                                .ok(),
+                            value_ns: self
+                                .resolve(path_str, ValueNS, &current_item, parent_node)
+                                .ok()
+                                .and_then(|(def, fragment)| {
+                                    // Constructors are picked up in the type namespace.
+                                    match def {
+                                        Def::StructCtor(..)
+                                        | Def::VariantCtor(..)
+                                        | Def::SelfCtor(..) => None,
+                                        _ => Some((def, fragment))
+                                    }
+                                }),
+                        };
+
+                        if candidates.is_empty() {
                             resolution_failure(cx, &item.attrs, path_str, &dox, link_range);
                             // this could just be a normal link
                             continue;
                         }
+
+                        let is_unambiguous = candidates.clone().present_items().count() == 1;
+                        if is_unambiguous {
+                            candidates.present_items().next().unwrap()
+                        } else {
+                            ambiguity_error(
+                                cx,
+                                &item.attrs,
+                                path_str,
+                                &dox,
+                                link_range,
+                                candidates.map(|candidate| candidate.map(|(def, _)| def)),
+                            );
+                            continue;
+                        }
                     }
-                    PathKind::Macro => {
+                    Some(MacroNS) => {
                         if let Some(def) = macro_resolve(cx, path_str) {
                             (def, None)
                         } else {
@@ -505,59 +480,114 @@
     diag.emit();
 }
 
-fn ambiguity_error(cx: &DocContext<'_>, attrs: &Attributes,
-                   path_str: &str,
-                   article1: &str, kind1: &str, disambig1: &str,
-                   article2: &str, kind2: &str, disambig2: &str) {
+fn ambiguity_error(
+    cx: &DocContext<'_>,
+    attrs: &Attributes,
+    path_str: &str,
+    dox: &str,
+    link_range: Option<Range<usize>>,
+    candidates: PerNS<Option<Def>>,
+) {
     let sp = span_of_attrs(attrs);
-    cx.sess()
-      .struct_span_warn(sp,
-                        &format!("`{}` is both {} {} and {} {}",
-                                 path_str, article1, kind1,
-                                 article2, kind2))
-      .help(&format!("try `{}` if you want to select the {}, \
-                      or `{}` if you want to \
-                      select the {}",
-                      disambig1, kind1, disambig2,
-                      kind2))
-      .emit();
-}
 
-/// Given a def, returns its name and disambiguator
-/// for a value namespace.
-///
-/// Returns `None` for things which cannot be ambiguous since
-/// they exist in both namespaces (structs and modules).
-fn value_ns_kind(def: Def, path_str: &str) -> Option<(&'static str, String)> {
-    match def {
-        // Structs, variants, and mods exist in both namespaces; skip them.
-        Def::StructCtor(..) | Def::Mod(..) | Def::Variant(..) |
-        Def::VariantCtor(..) | Def::SelfCtor(..)
-            => None,
-        Def::Fn(..)
-            => Some(("function", format!("{}()", path_str))),
-        Def::Method(..)
-            => Some(("method", format!("{}()", path_str))),
-        Def::Const(..)
-            => Some(("const", format!("const@{}", path_str))),
-        Def::Static(..)
-            => Some(("static", format!("static@{}", path_str))),
-        _ => Some(("value", format!("value@{}", path_str))),
+    let mut msg = format!("`{}` is ", path_str);
+
+    let candidates = [TypeNS, ValueNS, MacroNS].iter().filter_map(|&ns| {
+        candidates[ns].map(|def| (def, ns))
+    }).collect::<Vec<_>>();
+    match candidates.as_slice() {
+        [(first_def, _), (second_def, _)] => {
+            msg += &format!(
+                "both {} {} and {} {}",
+                first_def.article(),
+                first_def.kind_name(),
+                second_def.article(),
+                second_def.kind_name(),
+            );
+        }
+        _ => {
+            let mut candidates = candidates.iter().peekable();
+            while let Some((def, _)) = candidates.next() {
+                if candidates.peek().is_some() {
+                    msg += &format!("{} {}, ", def.article(), def.kind_name());
+                } else {
+                    msg += &format!("and {} {}", def.article(), def.kind_name());
+                }
+            }
+        }
     }
-}
 
-/// Given a def, returns its name, the article to be used, and a disambiguator
-/// for the type namespace.
-fn type_ns_kind(def: Def, path_str: &str) -> (&'static str, &'static str, String) {
-    let (kind, article) = match def {
-        // We can still have non-tuple structs.
-        Def::Struct(..) => ("struct", "a"),
-        Def::Enum(..) => ("enum", "an"),
-        Def::Trait(..) => ("trait", "a"),
-        Def::Union(..) => ("union", "a"),
-        _ => ("type", "a"),
-    };
-    (kind, article, format!("{}@{}", kind, path_str))
+    let mut diag = cx.tcx.struct_span_lint_hir(
+        lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
+        hir::CRATE_HIR_ID,
+        sp,
+        &msg,
+    );
+
+    if let Some(link_range) = link_range {
+        if let Some(sp) = super::source_span_for_markdown_range(cx, dox, &link_range, attrs) {
+            diag.set_span(sp);
+            diag.span_label(sp, "ambiguous link");
+
+            for (def, ns) in candidates {
+                let (action, mut suggestion) = match def {
+                    Def::Method(..) | Def::Fn(..) => {
+                        ("add parentheses", format!("{}()", path_str))
+                    }
+                    Def::Macro(..) => {
+                        ("add an exclamation mark", format!("{}!", path_str))
+                    }
+                    _ => {
+                        let type_ = match (def, ns) {
+                            (Def::Const(..), _) => "const",
+                            (Def::Static(..), _) => "static",
+                            (Def::Struct(..), _) => "struct",
+                            (Def::Enum(..), _) => "enum",
+                            (Def::Union(..), _) => "union",
+                            (Def::Trait(..), _) => "trait",
+                            (Def::Mod(..), _) => "module",
+                            (_, TypeNS) => "type",
+                            (_, ValueNS) => "value",
+                            (_, MacroNS) => "macro",
+                        };
+
+                        // FIXME: if this is an implied shortcut link, it's bad style to suggest `@`
+                        ("prefix with the item type", format!("{}@{}", type_, path_str))
+                    }
+                };
+
+                if dox.bytes().nth(link_range.start) == Some(b'`') {
+                    suggestion = format!("`{}`", suggestion);
+                }
+
+                diag.span_suggestion(
+                    sp,
+                    &format!("to link to the {}, {}", def.kind_name(), action),
+                    suggestion,
+                    Applicability::MaybeIncorrect,
+                );
+            }
+        } else {
+            // blah blah blah\nblah\nblah [blah] blah blah\nblah blah
+            //                       ^     ~~~~
+            //                       |     link_range
+            //                       last_new_line_offset
+            let last_new_line_offset = dox[..link_range.start].rfind('\n').map_or(0, |n| n + 1);
+            let line = dox[last_new_line_offset..].lines().next().unwrap_or("");
+
+            // Print the line containing the `link_range` and manually mark it with '^'s.
+            diag.note(&format!(
+                "the link appears in this line:\n\n{line}\n\
+                 {indicator: <before$}{indicator:^<found$}",
+                line=line,
+                indicator="",
+                before=link_range.start - last_new_line_offset,
+                found=link_range.len(),
+            ));
+        }
+    }
+
+    diag.emit();
 }
 
 /// Given an enum variant's def, return the def of its enum and the associated fragment.
@@ -594,11 +624,11 @@
     ("char",  Def::PrimTy(hir::PrimTy::Char)),
 ];
 
-fn is_primitive(path_str: &str, is_val: bool) -> Option<Def> {
-    if is_val {
-        None
-    } else {
+fn is_primitive(path_str: &str, ns: Namespace) -> Option<Def> {
+    if ns == TypeNS {
         PRIMITIVES.iter().find(|x| x.0 == path_str).map(|x| x.1)
+    } else {
+        None
     }
 }
 
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 0c99f6d..b4db121 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -178,9 +178,10 @@
             Some(kind) => {
                 let name = if kind == MacroKind::Derive {
                     item.attrs.lists("proc_macro_derive")
-                              .filter_map(|mi| mi.name())
+                              .filter_map(|mi| mi.ident())
                               .next()
                               .expect("proc-macro derives require a name")
+                              .name
                 } else {
                     name
                 };
@@ -193,8 +194,8 @@
 
                     if let Some(list) = mi.meta_item_list() {
                         for inner_mi in list {
-                            if let Some(name) = inner_mi.name() {
-                                helpers.push(name);
+                            if let Some(ident) = inner_mi.ident() {
+                                helpers.push(ident.name);
                             }
                         }
                     }
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index 928de29..1d45df4 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -19,7 +19,7 @@
 use super::table::BucketState::{Empty, Full};
 use super::table::Fallibility::{Fallible, Infallible};
 
-const MIN_NONZERO_RAW_CAPACITY: usize = 32;     // must be a power of two
+const MIN_NONZERO_RAW_CAPACITY: usize = 32; // must be a power of two
 
 /// The default behavior of HashMap implements a maximum load factor of 90.9%.
 #[derive(Clone)]
diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs
index f2111f2..c026de3 100644
--- a/src/libstd/collections/hash/set.rs
+++ b/src/libstd/collections/hash/set.rs
@@ -8,7 +8,7 @@
 use super::map::{self, HashMap, Keys, RandomState};
 
 // Future Optimization (FIXME!)
-// =============================
+// ============================
 //
 // Iteration over zero sized values is a noop. There is no need
 // for `bucket.val` in the case of HashSet. I suppose we would need HKT
diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs
index f6cd9e8..2fabe30 100644
--- a/src/libstd/f32.rs
+++ b/src/libstd/f32.rs
@@ -32,11 +32,13 @@
     /// # Examples
     ///
     /// ```
-    /// let f = 3.99_f32;
+    /// let f = 3.7_f32;
     /// let g = 3.0_f32;
+    /// let h = -3.7_f32;
     ///
     /// assert_eq!(f.floor(), 3.0);
     /// assert_eq!(g.floor(), 3.0);
+    /// assert_eq!(h.floor(), -4.0);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -104,11 +106,13 @@
     /// # Examples
     ///
     /// ```
-    /// let f = 3.3_f32;
-    /// let g = -3.7_f32;
+    /// let f = 3.7_f32;
+    /// let g = 3.0_f32;
+    /// let h = -3.7_f32;
     ///
     /// assert_eq!(f.trunc(), 3.0);
-    /// assert_eq!(g.trunc(), -3.0);
+    /// assert_eq!(g.trunc(), 3.0);
+    /// assert_eq!(h.trunc(), -3.0);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -956,6 +960,27 @@
     pub fn atanh(self) -> f32 {
         0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
     }
+    /// Returns max if self is greater than max, and min if self is less than min.
+    /// Otherwise this returns self.  Panics if min > max, min equals NaN, or max equals NaN.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(clamp)]
+    /// assert!((-3.0f32).clamp(-2.0f32, 1.0f32) == -2.0f32);
+    /// assert!((0.0f32).clamp(-2.0f32, 1.0f32) == 0.0f32);
+    /// assert!((2.0f32).clamp(-2.0f32, 1.0f32) == 1.0f32);
+    /// ```
+    #[unstable(feature = "clamp", issue = "44095")]
+    #[inline]
+    pub fn clamp(self, min: f32, max: f32) -> f32 {
+        assert!(min <= max);
+        let mut x = self;
+        if x < min { x = min; }
+        if x > max { x = max; }
+        x
+    }
+
 }
 
 #[cfg(test)]
diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs
index 8ff97ab..a471117 100644
--- a/src/libstd/f64.rs
+++ b/src/libstd/f64.rs
@@ -32,11 +32,13 @@
     /// # Examples
     ///
     /// ```
-    /// let f = 3.99_f64;
+    /// let f = 3.7_f64;
     /// let g = 3.0_f64;
+    /// let h = -3.7_f64;
     ///
     /// assert_eq!(f.floor(), 3.0);
     /// assert_eq!(g.floor(), 3.0);
+    /// assert_eq!(h.floor(), -4.0);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -84,11 +86,13 @@
     /// # Examples
     ///
     /// ```
-    /// let f = 3.3_f64;
-    /// let g = -3.7_f64;
+    /// let f = 3.7_f64;
+    /// let g = 3.0_f64;
+    /// let h = -3.7_f64;
     ///
     /// assert_eq!(f.trunc(), 3.0);
-    /// assert_eq!(g.trunc(), -3.0);
+    /// assert_eq!(g.trunc(), 3.0);
+    /// assert_eq!(h.trunc(), -3.0);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -878,6 +882,27 @@
         0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
     }
 
+    /// Returns max if self is greater than max, and min if self is less than min.
+    /// Otherwise this returns self.  Panics if min > max, min equals NaN, or max equals NaN.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(clamp)]
+    /// assert!((-3.0f64).clamp(-2.0f64, 1.0f64) == -2.0f64);
+    /// assert!((0.0f64).clamp(-2.0f64, 1.0f64) == 0.0f64);
+    /// assert!((2.0f64).clamp(-2.0f64, 1.0f64) == 1.0f64);
+    /// ```
+    #[unstable(feature = "clamp", issue = "44095")]
+    #[inline]
+    pub fn clamp(self, min: f64, max: f64) -> f64 {
+        assert!(min <= max);
+        let mut x = self;
+        if x < min { x = min; }
+        if x > max { x = max; }
+        x
+    }
+
     // Solaris/Illumos requires a wrapper around log, log2, and log10 functions
     // because of their non-standard behavior (e.g., log(-n) returns -Inf instead
     // of expected NaN).
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
index 25f2dd7..8c3d0da 100644
--- a/src/libstd/fs.rs
+++ b/src/libstd/fs.rs
@@ -211,7 +211,7 @@
     recursive: bool,
 }
 
-/// How large a buffer to pre-allocate before reading the entire file.
+/// Indicates how large a buffer to pre-allocate before reading the entire file.
 fn initial_buffer_size(file: &File) -> usize {
     // Allocate one extra byte so the buffer doesn't need to grow before the
     // final `read` call at the end of the file.  Don't worry about `usize`
@@ -1581,7 +1581,8 @@
 /// `O_CLOEXEC` is set for returned file descriptors.
 /// On Windows, this function currently corresponds to `CopyFileEx`. Alternate
 /// NTFS streams are copied but only the size of the main stream is returned by
-/// this function.
+/// this function. On MacOS, this function corresponds to `copyfile` with
+/// `COPYFILE_ALL`.
 /// Note that, this [may change in the future][changes].
 ///
 /// [changes]: ../io/index.html#platform-specific-behavior
@@ -2837,6 +2838,26 @@
     }
 
     #[test]
+    fn copy_file_follows_dst_symlink() {
+        let tmp = tmpdir();
+        if !got_symlink_permission(&tmp) { return };
+
+        let in_path = tmp.join("in.txt");
+        let out_path = tmp.join("out.txt");
+        let out_path_symlink = tmp.join("out_symlink.txt");
+
+        check!(fs::write(&in_path, "foo"));
+        check!(fs::write(&out_path, "bar"));
+        check!(symlink_file(&out_path, &out_path_symlink));
+
+        check!(fs::copy(&in_path, &out_path_symlink));
+
+        assert!(check!(out_path_symlink.symlink_metadata()).file_type().is_symlink());
+        assert_eq!(check!(fs::read(&out_path_symlink)), b"foo".to_vec());
+        assert_eq!(check!(fs::read(&out_path)), b"foo".to_vec());
+    }
+
+    #[test]
     fn symlinks_work() {
         let tmpdir = tmpdir();
         if !got_symlink_permission(&tmpdir) { return };
diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs
index a14c10d..4668e3e 100644
--- a/src/libstd/io/buffered.rs
+++ b/src/libstd/io/buffered.rs
@@ -193,6 +193,13 @@
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn into_inner(self) -> R { self.inner }
+
+    /// Invalidates all data in the internal buffer.
+    #[inline]
+    fn discard_buffer(&mut self) {
+        self.pos = 0;
+        self.cap = 0;
+    }
 }
 
 impl<R: Seek> BufReader<R> {
@@ -227,6 +234,7 @@
         // (larger than our internal buffer), bypass our internal buffer
         // entirely.
         if self.pos == self.cap && buf.len() >= self.buf.len() {
+            self.discard_buffer();
             return self.inner.read(buf);
         }
         let nread = {
@@ -240,6 +248,7 @@
     fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
         let total_len = bufs.iter().map(|b| b.len()).sum::<usize>();
         if self.pos == self.cap && total_len >= self.buf.len() {
+            self.discard_buffer();
             return self.inner.read_vectored(bufs);
         }
         let nread = {
@@ -325,14 +334,14 @@
             } else {
                 // seek backwards by our remainder, and then by the offset
                 self.inner.seek(SeekFrom::Current(-remainder))?;
-                self.pos = self.cap; // empty the buffer
+                self.discard_buffer();
                 result = self.inner.seek(SeekFrom::Current(n))?;
             }
         } else {
             // Seeking with Start/End doesn't care about our buffer length.
             result = self.inner.seek(pos)?;
         }
-        self.pos = self.cap; // empty the buffer
+        self.discard_buffer();
         Ok(result)
     }
 }
@@ -1069,6 +1078,40 @@
     }
 
     #[test]
+    fn test_buffered_reader_invalidated_after_read() {
+        let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4];
+        let mut reader = BufReader::with_capacity(3, io::Cursor::new(inner));
+
+        assert_eq!(reader.fill_buf().ok(), Some(&[5, 6, 7][..]));
+        reader.consume(3);
+
+        let mut buffer = [0, 0, 0, 0, 0];
+        assert_eq!(reader.read(&mut buffer).ok(), Some(5));
+        assert_eq!(buffer, [0, 1, 2, 3, 4]);
+
+        assert!(reader.seek_relative(-2).is_ok());
+        let mut buffer = [0, 0];
+        assert_eq!(reader.read(&mut buffer).ok(), Some(2));
+        assert_eq!(buffer, [3, 4]);
+    }
+
+    #[test]
+    fn test_buffered_reader_invalidated_after_seek() {
+        let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4];
+        let mut reader = BufReader::with_capacity(3, io::Cursor::new(inner));
+
+        assert_eq!(reader.fill_buf().ok(), Some(&[5, 6, 7][..]));
+        reader.consume(3);
+
+        assert!(reader.seek(SeekFrom::Current(5)).is_ok());
+
+        assert!(reader.seek_relative(-2).is_ok());
+        let mut buffer = [0, 0];
+        assert_eq!(reader.read(&mut buffer).ok(), Some(2));
+        assert_eq!(buffer, [3, 4]);
+    }
+
+    #[test]
     fn test_buffered_reader_seek_underflow() {
         // gimmick reader that yields its position modulo 256 for each byte
         struct PositionReader {
diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs
index 873da08..247d45c 100644
--- a/src/libstd/io/cursor.rs
+++ b/src/libstd/io/cursor.rs
@@ -212,6 +212,14 @@
                            "invalid seek to a negative or overflowing position"))
         }
     }
+
+    fn stream_len(&mut self) -> io::Result<u64> {
+        Ok(self.inner.as_ref().len() as u64)
+    }
+
+    fn stream_position(&mut self) -> io::Result<u64> {
+        Ok(self.pos)
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index e3e2754..4c88fc8 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -390,6 +390,28 @@
     ret
 }
 
+pub(crate) fn default_read_vectored<F>(read: F, bufs: &mut [IoVecMut<'_>]) -> Result<usize>
+where
+    F: FnOnce(&mut [u8]) -> Result<usize>
+{
+    let buf = bufs
+        .iter_mut()
+        .find(|b| !b.is_empty())
+        .map_or(&mut [][..], |b| &mut **b);
+    read(buf)
+}
+
+pub(crate) fn default_write_vectored<F>(write: F, bufs: &[IoVec<'_>]) -> Result<usize>
+where
+    F: FnOnce(&[u8]) -> Result<usize>
+{
+    let buf = bufs
+        .iter()
+        .find(|b| !b.is_empty())
+        .map_or(&[][..], |b| &**b);
+    write(buf)
+}
+
 /// The `Read` trait allows for reading bytes from a source.
 ///
 /// Implementors of the `Read` trait are called 'readers'.
@@ -528,14 +550,11 @@
     /// written to possibly being only partially filled. This method must behave
     /// as a single call to `read` with the buffers concatenated would.
     ///
-    /// The default implementation simply passes the first nonempty buffer to
-    /// `read`.
+    /// The default implementation calls `read` with either the first nonempty
+    /// buffer provided, or an empty one if none exists.
     #[unstable(feature = "iovec", issue = "58452")]
     fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> Result<usize> {
-        match bufs.iter_mut().find(|b| !b.is_empty()) {
-            Some(buf) => self.read(buf),
-            None => Ok(0),
-        }
+        default_read_vectored(|b| self.read(b), bufs)
     }
 
     /// Determines if this `Read`er can work with buffers of uninitialized
@@ -1107,14 +1126,11 @@
     /// read from possibly being only partially consumed. This method must
     /// behave as a call to `write` with the buffers concatenated would.
     ///
-    /// The default implementation simply passes the first nonempty buffer to
-    /// `write`.
+    /// The default implementation calls `write` with either the first nonempty
+    /// buffer provided, or an empty one if none exists.
     #[unstable(feature = "iovec", issue = "58452")]
     fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> Result<usize> {
-        match bufs.iter().find(|b| !b.is_empty()) {
-            Some(buf) => self.write(buf),
-            None => Ok(0),
-        }
+        default_write_vectored(|b| self.write(b), bufs)
     }
 
     /// Flush this output stream, ensuring that all intermediately buffered
@@ -1329,6 +1345,85 @@
     /// [`SeekFrom::Start`]: enum.SeekFrom.html#variant.Start
     #[stable(feature = "rust1", since = "1.0.0")]
     fn seek(&mut self, pos: SeekFrom) -> Result<u64>;
+
+    /// Returns the length of this stream (in bytes).
+    ///
+    /// This method is implemented using up to three seek operations. If this
+    /// method returns successfully, the seek position is unchanged (i.e. the
+    /// position before calling this method is the same as afterwards).
+    /// However, if this method returns an error, the seek position is
+    /// unspecified.
+    ///
+    /// If you need to obtain the length of *many* streams and you don't care
+    /// about the seek position afterwards, you can reduce the number of seek
+    /// operations by simply calling `seek(SeekFrom::End(0))` and using its
+    /// return value (it is also the stream length).
+    ///
+    /// Note that length of a stream can change over time (for example, when
+    /// data is appended to a file). So calling this method multiple times does
+    /// not necessarily return the same length each time.
+    ///
+    ///
+    /// # Example
+    ///
+    /// ```no_run
+    /// #![feature(seek_convenience)]
+    /// use std::{
+    ///     io::{self, Seek},
+    ///     fs::File,
+    /// };
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let mut f = File::open("foo.txt")?;
+    ///
+    ///     let len = f.stream_len()?;
+    ///     println!("The file is currently {} bytes long", len);
+    ///     Ok(())
+    /// }
+    /// ```
+    #[unstable(feature = "seek_convenience", issue = "0")]
+    fn stream_len(&mut self) -> Result<u64> {
+        let old_pos = self.stream_position()?;
+        let len = self.seek(SeekFrom::End(0))?;
+
+        // Avoid seeking a third time when we were already at the end of the
+        // stream. The branch is usually way cheaper than a seek operation.
+        if old_pos != len {
+            self.seek(SeekFrom::Start(old_pos))?;
+        }
+
+        Ok(len)
+    }
+
+    /// Returns the current seek position from the start of the stream.
+    ///
+    /// This is equivalent to `self.seek(SeekFrom::Current(0))`.
+    ///
+    ///
+    /// # Example
+    ///
+    /// ```no_run
+    /// #![feature(seek_convenience)]
+    /// use std::{
+    ///     io::{self, BufRead, BufReader, Seek},
+    ///     fs::File,
+    /// };
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let mut f = BufReader::new(File::open("foo.txt")?);
+    ///
+    ///     let before = f.stream_position()?;
+    ///     f.read_line(&mut String::new())?;
+    ///     let after = f.stream_position()?;
+    ///
+    ///     println!("The first line was {} bytes long", after - before);
+    ///     Ok(())
+    /// }
+    /// ```
+    #[unstable(feature = "seek_convenience", issue = "0")]
+    fn stream_position(&mut self) -> Result<u64> {
+        self.seek(SeekFrom::Current(0))
+    }
 }
 
 /// Enumeration of possible methods to seek within an I/O object.
@@ -2157,8 +2252,7 @@
 mod tests {
     use crate::io::prelude::*;
     use crate::io;
-    use super::Cursor;
-    use super::repeat;
+    use super::{Cursor, SeekFrom, repeat};
 
     #[test]
     #[cfg_attr(target_os = "emscripten", ignore)]
@@ -2380,4 +2474,50 @@
             super::read_to_end(&mut lr, &mut vec)
         });
     }
+
+    #[test]
+    fn seek_len() -> io::Result<()> {
+        let mut c = Cursor::new(vec![0; 15]);
+        assert_eq!(c.stream_len()?, 15);
+
+        c.seek(SeekFrom::End(0))?;
+        let old_pos = c.stream_position()?;
+        assert_eq!(c.stream_len()?, 15);
+        assert_eq!(c.stream_position()?, old_pos);
+
+        c.seek(SeekFrom::Start(7))?;
+        c.seek(SeekFrom::Current(2))?;
+        let old_pos = c.stream_position()?;
+        assert_eq!(c.stream_len()?, 15);
+        assert_eq!(c.stream_position()?, old_pos);
+
+        Ok(())
+    }
+
+    #[test]
+    fn seek_position() -> io::Result<()> {
+        // All `asserts` are duplicated here to make sure the method does not
+        // change anything about the seek state.
+        let mut c = Cursor::new(vec![0; 15]);
+        assert_eq!(c.stream_position()?, 0);
+        assert_eq!(c.stream_position()?, 0);
+
+        c.seek(SeekFrom::End(0))?;
+        assert_eq!(c.stream_position()?, 15);
+        assert_eq!(c.stream_position()?, 15);
+
+
+        c.seek(SeekFrom::Start(7))?;
+        c.seek(SeekFrom::Current(2))?;
+        assert_eq!(c.stream_position()?, 9);
+        assert_eq!(c.stream_position()?, 9);
+
+        c.seek(SeekFrom::End(-3))?;
+        c.seek(SeekFrom::Current(1))?;
+        c.seek(SeekFrom::Current(-5))?;
+        assert_eq!(c.stream_position()?, 8);
+        assert_eq!(c.stream_position()?, 8);
+
+        Ok(())
+    }
 }
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index e31680f..296c4c8 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -221,7 +221,7 @@
 
 #![cfg_attr(test, feature(print_internals, set_stdio, test, update_panic_count))]
 #![cfg_attr(all(target_vendor = "fortanix", target_env = "sgx"),
-            feature(global_asm, range_contains, slice_index_methods,
+            feature(global_asm, slice_index_methods,
                     decl_macro, coerce_unsized, sgx_platform, ptr_wrapping_offset_from))]
 
 // std is implemented with unstable features, many of which are internal
@@ -245,6 +245,7 @@
 #![feature(cfg_target_thread_local)]
 #![feature(char_error_internals)]
 #![feature(checked_duration_since)]
+#![feature(clamp)]
 #![feature(compiler_builtins_lib)]
 #![feature(concat_idents)]
 #![feature(const_cstr_unchecked)]
@@ -300,6 +301,7 @@
 #![feature(stmt_expr_attributes)]
 #![feature(str_internals)]
 #![feature(thread_local)]
+#![feature(todo_macro)]
 #![feature(toowned_clone_into)]
 #![feature(try_reserve)]
 #![feature(unboxed_closures)]
@@ -322,7 +324,7 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::{assert_eq, assert_ne, debug_assert, debug_assert_eq, debug_assert_ne};
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use core::{unreachable, unimplemented, write, writeln, r#try};
+pub use core::{unreachable, unimplemented, write, writeln, r#try, todo};
 
 #[allow(unused_imports)] // macros from `alloc` are not used on all platforms
 #[macro_use]
diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs
index 9d0eb2e..d5dc5f7 100644
--- a/src/libstd/macros.rs
+++ b/src/libstd/macros.rs
@@ -305,10 +305,16 @@
 /// let _ = dbg!(a); // <-- `a` is moved again; error!
 /// ```
 ///
+/// You can also use `dbg!()` without a value to just print the
+/// file and line whenever it's reached.
+///
 /// [stderr]: https://en.wikipedia.org/wiki/Standard_streams#Standard_error_(stderr)
 #[macro_export]
 #[stable(feature = "dbg_macro", since = "1.32.0")]
 macro_rules! dbg {
+    () => {
+        eprintln!("[{}:{}]", file!(), line!());
+    };
     ($val:expr) => {
         // Use of `match` here is intentional because it affects the lifetimes
         // of temporaries - https://stackoverflow.com/a/48732525/1063961
diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs
index edc9d66..b42a812 100644
--- a/src/libstd/net/udp.rs
+++ b/src/libstd/net/udp.rs
@@ -180,6 +180,37 @@
         }
     }
 
+    /// Returns the socket address of the remote peer this socket was connected to.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(udp_peer_addr)]
+    /// use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, UdpSocket};
+    ///
+    /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
+    /// socket.connect("192.168.0.1:41203").expect("couldn't connect to address");
+    /// assert_eq!(socket.peer_addr().unwrap(),
+    ///            SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(192, 168, 0, 1), 41203)));
+    /// ```
+    ///
+    /// If the socket isn't connected, it will return a [`NotConnected`] error.
+    ///
+    /// [`NotConnected`]: ../../std/io/enum.ErrorKind.html#variant.NotConnected
+    ///
+    /// ```no_run
+    /// #![feature(udp_peer_addr)]
+    /// use std::net::UdpSocket;
+    ///
+    /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
+    /// assert_eq!(socket.peer_addr().unwrap_err().kind(),
+    ///            ::std::io::ErrorKind::NotConnected);
+    /// ```
+    #[unstable(feature = "udp_peer_addr", issue = "59127")]
+    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
+        self.0.peer_addr()
+    }
+
     /// Returns the socket address that this socket was created from.
     ///
     /// # Examples
@@ -865,7 +896,7 @@
     }
 
     #[test]
-    fn socket_name_ip4() {
+    fn socket_name() {
         each_ip(&mut |addr, _| {
             let server = t!(UdpSocket::bind(&addr));
             assert_eq!(addr, t!(server.local_addr()));
@@ -873,6 +904,16 @@
     }
 
     #[test]
+    fn socket_peer() {
+        each_ip(&mut |addr1, addr2| {
+            let server = t!(UdpSocket::bind(&addr1));
+            assert_eq!(server.peer_addr().unwrap_err().kind(), ErrorKind::NotConnected);
+            t!(server.connect(&addr2));
+            assert_eq!(addr2, t!(server.peer_addr()));
+        })
+    }
+
+    #[test]
     fn udp_clone_smoke() {
         each_ip(&mut |addr1, addr2| {
             let sock1 = t!(UdpSocket::bind(&addr1));
diff --git a/src/libstd/os/fortanix_sgx/mod.rs b/src/libstd/os/fortanix_sgx/mod.rs
index bca22e7..4e30b1e 100644
--- a/src/libstd/os/fortanix_sgx/mod.rs
+++ b/src/libstd/os/fortanix_sgx/mod.rs
@@ -43,3 +43,8 @@
 }
 
 pub use crate::sys::ext::{io, arch, ffi};
+
+/// Functions for querying thread-related information.
+pub mod thread {
+    pub use crate::sys::abi::thread::current;
+}
diff --git a/src/libstd/process.rs b/src/libstd/process.rs
index 5684000..ad86acb 100644
--- a/src/libstd/process.rs
+++ b/src/libstd/process.rs
@@ -8,7 +8,7 @@
 //!
 //! The [`Command`] struct is used to configure and spawn processes:
 //!
-//! ```
+//! ```no_run
 //! use std::process::Command;
 //!
 //! let output = Command::new("echo")
diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs
index 5ebb617..c383f21 100644
--- a/src/libstd/sync/condvar.rs
+++ b/src/libstd/sync/condvar.rs
@@ -190,7 +190,7 @@
     /// // Wait for the thread to start up.
     /// let &(ref lock, ref cvar) = &*pair;
     /// let mut started = lock.lock().unwrap();
-    /// // As long as the value inside the `Mutex` is false, we wait.
+    /// // As long as the value inside the `Mutex<bool>` is `false`, we wait.
     /// while !*started {
     ///     started = cvar.wait(started).unwrap();
     /// }
@@ -254,7 +254,7 @@
     ///
     /// // Wait for the thread to start up.
     /// let &(ref lock, ref cvar) = &*pair;
-    /// // As long as the value inside the `Mutex` is false, we wait.
+    /// // As long as the value inside the `Mutex<bool>` is `false`, we wait.
     /// let _guard = cvar.wait_until(lock.lock().unwrap(), |started| { *started }).unwrap();
     /// ```
     #[unstable(feature = "wait_until", issue = "47960")]
@@ -311,7 +311,7 @@
     /// // Wait for the thread to start up.
     /// let &(ref lock, ref cvar) = &*pair;
     /// let mut started = lock.lock().unwrap();
-    /// // As long as the value inside the `Mutex` is false, we wait.
+    /// // As long as the value inside the `Mutex<bool>` is `false`, we wait.
     /// loop {
     ///     let result = cvar.wait_timeout_ms(started, 10).unwrap();
     ///     // 10 milliseconds have passed, or maybe the value changed!
@@ -384,7 +384,7 @@
     /// // wait for the thread to start up
     /// let &(ref lock, ref cvar) = &*pair;
     /// let mut started = lock.lock().unwrap();
-    /// // as long as the value inside the `Mutex` is false, we wait
+    /// // as long as the value inside the `Mutex<bool>` is `false`, we wait
     /// loop {
     ///     let result = cvar.wait_timeout(started, Duration::from_millis(10)).unwrap();
     ///     // 10 milliseconds have passed, or maybe the value changed!
@@ -518,7 +518,7 @@
     /// // Wait for the thread to start up.
     /// let &(ref lock, ref cvar) = &*pair;
     /// let mut started = lock.lock().unwrap();
-    /// // As long as the value inside the `Mutex` is false, we wait.
+    /// // As long as the value inside the `Mutex<bool>` is `false`, we wait.
     /// while !*started {
     ///     started = cvar.wait(started).unwrap();
     /// }
@@ -558,7 +558,7 @@
     /// // Wait for the thread to start up.
     /// let &(ref lock, ref cvar) = &*pair;
     /// let mut started = lock.lock().unwrap();
-    /// // As long as the value inside the `Mutex` is false, we wait.
+    /// // As long as the value inside the `Mutex<bool>` is `false`, we wait.
     /// while !*started {
     ///     started = cvar.wait(started).unwrap();
     /// }
diff --git a/src/libstd/sys/cloudabi/shims/net.rs b/src/libstd/sys/cloudabi/shims/net.rs
index 6d2a496..4364a13 100644
--- a/src/libstd/sys/cloudabi/shims/net.rs
+++ b/src/libstd/sys/cloudabi/shims/net.rs
@@ -159,6 +159,10 @@
         unsupported()
     }
 
+    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
+        match self.0 {}
+    }
+
     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
         match self.0 {}
     }
diff --git a/src/libstd/sys/redox/net/tcp.rs b/src/libstd/sys/redox/net/tcp.rs
index 5081c3d..3f2f616 100644
--- a/src/libstd/sys/redox/net/tcp.rs
+++ b/src/libstd/sys/redox/net/tcp.rs
@@ -35,10 +35,7 @@
     }
 
     pub fn read_vectored(&self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
-        match bufs.iter_mut().find(|b| !b.is_empty()) {
-            Some(buf) => self.read(buf),
-            None => Ok(0),
-        }
+        io::default_read_vectored(|b| self.read(b), bufs)
     }
 
     pub fn write(&self, buf: &[u8]) -> Result<usize> {
@@ -46,10 +43,7 @@
     }
 
     pub fn write_vectored(&self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
-        match bufs.iter().find(|b| !b.is_empty()) {
-            Some(buf) => self.write(buf),
-            None => Ok(0),
-        }
+        io::default_write_vectored(|b| self.write(b), bufs)
     }
 
     pub fn take_error(&self) -> Result<Option<Error>> {
diff --git a/src/libstd/sys/redox/net/udp.rs b/src/libstd/sys/redox/net/udp.rs
index b1a60b1..274123d 100644
--- a/src/libstd/sys/redox/net/udp.rs
+++ b/src/libstd/sys/redox/net/udp.rs
@@ -72,6 +72,11 @@
         Ok(None)
     }
 
+    pub fn peer_addr(&self) -> Result<SocketAddr> {
+        let path = self.0.path()?;
+        Ok(path_to_peer_addr(path.to_str().unwrap_or("")))
+    }
+
     pub fn socket_addr(&self) -> Result<SocketAddr> {
         let path = self.0.path()?;
         Ok(path_to_local_addr(path.to_str().unwrap_or("")))
diff --git a/src/libstd/sys/sgx/abi/thread.rs b/src/libstd/sys/sgx/abi/thread.rs
index 86fe09d..c17fa2d 100644
--- a/src/libstd/sys/sgx/abi/thread.rs
+++ b/src/libstd/sys/sgx/abi/thread.rs
@@ -4,6 +4,7 @@
 /// all currently running threads in the enclave, and it is guaranteed to be
 /// constant for the lifetime of the thread. More specifically for SGX, there
 /// is a one-to-one correspondence of the ID to the address of the TCS.
+#[unstable(feature = "sgx_platform", issue = "56975")]
 pub fn current() -> Tcs {
     extern "C" { fn get_tcs_addr() -> Tcs; }
     unsafe { get_tcs_addr() }
diff --git a/src/libstd/sys/sgx/net.rs b/src/libstd/sys/sgx/net.rs
index e5e42e3..81f33c1 100644
--- a/src/libstd/sys/sgx/net.rs
+++ b/src/libstd/sys/sgx/net.rs
@@ -103,24 +103,16 @@
         self.inner.inner.read(buf)
     }
 
-    pub fn read_vectored(&self, buf: &mut [IoVecMut<'_>]) -> io::Result<usize> {
-        let buf = match buf.get_mut(0) {
-            Some(buf) => buf,
-            None => return Ok(0),
-        };
-        self.read(buf)
+    pub fn read_vectored(&self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+        io::default_read_vectored(|b| self.read(b), bufs)
     }
 
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
         self.inner.inner.write(buf)
     }
 
-    pub fn write_vectored(&self, buf: &[IoVec<'_>]) -> io::Result<usize> {
-        let buf = match buf.get(0) {
-            Some(buf) => buf,
-            None => return Ok(0),
-        };
-        self.write(buf)
+    pub fn write_vectored(&self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+        io::default_write_vectored(|b| self.write(b), bufs)
     }
 
     pub fn peer_addr(&self) -> io::Result<SocketAddr> {
@@ -257,6 +249,10 @@
         unsupported()
     }
 
+    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
+        match self.0 {}
+    }
+
     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
         match self.0 {}
     }
diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs
index 3b80b47..7ff098b 100644
--- a/src/libstd/sys/unix/fs.rs
+++ b/src/libstd/sys/unix/fs.rs
@@ -827,7 +827,10 @@
     Ok(PathBuf::from(OsString::from_vec(buf)))
 }
 
-#[cfg(not(any(target_os = "linux", target_os = "android")))]
+#[cfg(not(any(target_os = "linux",
+              target_os = "android",
+              target_os = "macos",
+              target_os = "ios")))]
 pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
     use crate::fs::File;
     if !from.is_file() {
@@ -937,3 +940,85 @@
     writer.set_permissions(perm)?;
     Ok(written)
 }
+
+#[cfg(any(target_os = "macos", target_os = "ios"))]
+pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
+    const COPYFILE_ACL: u32 = 1 << 0;
+    const COPYFILE_STAT: u32 = 1 << 1;
+    const COPYFILE_XATTR: u32 = 1 << 2;
+    const COPYFILE_DATA: u32 = 1 << 3;
+
+    const COPYFILE_SECURITY: u32 = COPYFILE_STAT | COPYFILE_ACL;
+    const COPYFILE_METADATA: u32 = COPYFILE_SECURITY | COPYFILE_XATTR;
+    const COPYFILE_ALL: u32 = COPYFILE_METADATA | COPYFILE_DATA;
+
+    const COPYFILE_STATE_COPIED: u32 = 8;
+
+    #[allow(non_camel_case_types)]
+    type copyfile_state_t = *mut libc::c_void;
+    #[allow(non_camel_case_types)]
+    type copyfile_flags_t = u32;
+
+    extern "C" {
+        fn copyfile(
+            from: *const libc::c_char,
+            to: *const libc::c_char,
+            state: copyfile_state_t,
+            flags: copyfile_flags_t,
+        ) -> libc::c_int;
+        fn copyfile_state_alloc() -> copyfile_state_t;
+        fn copyfile_state_free(state: copyfile_state_t) -> libc::c_int;
+        fn copyfile_state_get(
+            state: copyfile_state_t,
+            flag: u32,
+            dst: *mut libc::c_void,
+        ) -> libc::c_int;
+    }
+
+    struct FreeOnDrop(copyfile_state_t);
+    impl Drop for FreeOnDrop {
+        fn drop(&mut self) {
+            // The code below ensures that `FreeOnDrop` is never a null pointer
+            unsafe {
+                // `copyfile_state_free` returns -1 if the `to` or `from` files
+                // cannot be closed. However, this is not considerd this an
+                // error.
+                copyfile_state_free(self.0);
+            }
+        }
+    }
+
+    if !from.is_file() {
+        return Err(Error::new(ErrorKind::InvalidInput,
+                              "the source path is not an existing regular file"))
+    }
+
+    // We ensure that `FreeOnDrop` never contains a null pointer so it is
+    // always safe to call `copyfile_state_free`
+    let state = unsafe {
+        let state = copyfile_state_alloc();
+        if state.is_null() {
+            return Err(crate::io::Error::last_os_error());
+        }
+        FreeOnDrop(state)
+    };
+
+    cvt(unsafe {
+        copyfile(
+            cstr(from)?.as_ptr(),
+            cstr(to)?.as_ptr(),
+            state.0,
+            COPYFILE_ALL,
+        )
+    })?;
+
+    let mut bytes_copied: libc::off_t = 0;
+    cvt(unsafe {
+        copyfile_state_get(
+            state.0,
+            COPYFILE_STATE_COPIED,
+            &mut bytes_copied as *mut libc::off_t as *mut libc::c_void,
+        )
+    })?;
+    Ok(bytes_copied as u64)
+}
diff --git a/src/libstd/sys/unix/l4re.rs b/src/libstd/sys/unix/l4re.rs
index b9e7253..b3dd1cf 100644
--- a/src/libstd/sys/unix/l4re.rs
+++ b/src/libstd/sys/unix/l4re.rs
@@ -292,6 +292,10 @@
 
         pub fn into_socket(self) -> Socket { self.inner }
 
+        pub fn peer_addr(&self) -> io::Result<SocketAddr> {
+            unimpl!();
+        }
+
         pub fn socket_addr(&self) -> io::Result<SocketAddr> {
             unimpl!();
         }
@@ -463,4 +467,3 @@
         }
     }
 }
-
diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs
index 8c60bdd..561279e8 100644
--- a/src/libstd/sys/unix/stack_overflow.rs
+++ b/src/libstd/sys/unix/stack_overflow.rs
@@ -140,6 +140,7 @@
     #[cfg(any(target_os = "linux",
               target_os = "macos",
               target_os = "bitrig",
+              target_os = "freebsd",
               target_os = "netbsd",
               target_os = "openbsd",
               target_os = "solaris"))]
@@ -147,8 +148,7 @@
         libc::stack_t { ss_sp: get_stackp(), ss_flags: 0, ss_size: SIGSTKSZ }
     }
 
-    #[cfg(any(target_os = "freebsd",
-              target_os = "dragonfly"))]
+    #[cfg(target_os = "dragonfly")]
     unsafe fn get_stack() -> libc::stack_t {
         libc::stack_t { ss_sp: get_stackp() as *mut i8, ss_flags: 0, ss_size: SIGSTKSZ }
     }
diff --git a/src/libstd/sys/wasm/alloc.rs b/src/libstd/sys/wasm/alloc.rs
index b909854..c1af6ec 100644
--- a/src/libstd/sys/wasm/alloc.rs
+++ b/src/libstd/sys/wasm/alloc.rs
@@ -49,7 +49,6 @@
 
 #[cfg(target_feature = "atomics")]
 mod lock {
-    use crate::arch::wasm32;
     use crate::sync::atomic::{AtomicI32, Ordering::SeqCst};
 
     static LOCKED: AtomicI32 = AtomicI32::new(0);
@@ -61,14 +60,76 @@
             if LOCKED.swap(1, SeqCst) == 0 {
                 return DropLock
             }
-            unsafe {
-                let r = wasm32::i32_atomic_wait(
-                    &LOCKED as *const AtomicI32 as *mut i32,
-                    1,  // expected value
-                    -1, // timeout
-                );
-                debug_assert!(r == 0 || r == 1);
-            }
+            // Ok so here's where things get a little depressing. At this point
+            // in time we need to synchronously acquire a lock, but we're
+            // contending with some other thread. Typically we'd execute some
+            // form of `i32.atomic.wait` like so:
+            //
+            //     unsafe {
+            //         let r = core::arch::wasm32::i32_atomic_wait(
+            //             &LOCKED as *const AtomicI32 as *mut i32,
+            //             1,  //     expected value
+            //             -1, //     timeout
+            //         );
+            //         debug_assert!(r == 0 || r == 1);
+            //     }
+            //
+            // Unfortunately though in doing so we would cause issues for the
+            // main thread. The main thread in a web browser *cannot ever
+            // block*, no exceptions. This means that the main thread can't
+            // actually execute the `i32.atomic.wait` instruction.
+            //
+            // As a result if we want to work within the context of browsers we
+            // need to figure out some sort of allocation scheme for the main
+            // thread where when there's contention on the global malloc lock we
+            // do... something.
+            //
+            // Possible ideas include:
+            //
+            // 1. Attempt to acquire the global lock. If it fails, fall back to
+            //    memory allocation via `memory.grow`. Later just ... somehow
+            //    ... inject this raw page back into the main allocator as it
+            //    gets sliced up over time. This strategy has the downside of
+            //    forcing allocation of a page to happen whenever the main
+            //    thread contents with other threads, which is unfortunate.
+            //
+            // 2. Maintain a form of "two level" allocator scheme where the main
+            //    thread has its own allocator. Somehow this allocator would
+            //    also be balanced with a global allocator, not only to have
+            //    allocations cross between threads but also to ensure that the
+            //    two allocators stay "balanced" in terms of free'd memory and
+            //    such. This, however, seems significantly complicated.
+            //
+            // Out of a lack of other ideas, the current strategy implemented
+            // here is to simply spin. Typical spin loop algorithms have some
+            // form of "hint" here to the CPU that it's what we're doing to
+            // ensure that the CPU doesn't get too hot, but wasm doesn't have
+            // such an instruction.
+            //
+            // To be clear, spinning here is not a great solution.
+            // Another thread with the lock may take quite a long time to wake
+            // up. For example it could be in `memory.grow` or it could be
+            // evicted from the CPU for a timeslice like 10ms. For these periods
+            // of time our thread will "helpfully" sit here and eat CPU time
+            // until it itself is evicted or the lock holder finishes. This
+            // means we're just burning and wasting CPU time to no one's
+            // benefit.
+            //
+            // Spinning does have the nice properties, though, of being
+            // semantically correct, being fair to all threads for memory
+            // allocation, and being simple enough to implement.
+            //
+            // This will surely (hopefully) be replaced in the future with a
+            // real memory allocator that can handle the restriction of the main
+            // thread.
+            //
+            //
+            // FIXME: We can also possibly add an optimization here to detect
+            // when a thread is the main thread or not and block on all
+            // non-main-thread threads. Currently, however, we have no way
+            // of knowing which wasm thread is on the browser main thread, but
+            // if we could figure out we could at least somewhat mitigate the
+            // cost of this spinning.
         }
     }
 
@@ -76,12 +137,16 @@
         fn drop(&mut self) {
             let r = LOCKED.swap(0, SeqCst);
             debug_assert_eq!(r, 1);
-            unsafe {
-                wasm32::atomic_notify(
-                    &LOCKED as *const AtomicI32 as *mut i32,
-                    1, // only one thread
-                );
-            }
+
+            // Note that due to the above logic we don't actually need to wake
+            // anyone up, but if we did it'd likely look something like this:
+            //
+            //     unsafe {
+            //         core::arch::wasm32::atomic_notify(
+            //             &LOCKED as *const AtomicI32 as *mut i32,
+            //             1, //     only one thread
+            //         );
+            //     }
         }
     }
 }
diff --git a/src/libstd/sys/wasm/net.rs b/src/libstd/sys/wasm/net.rs
index a2ea2df..c85dd00 100644
--- a/src/libstd/sys/wasm/net.rs
+++ b/src/libstd/sys/wasm/net.rs
@@ -156,6 +156,10 @@
         unsupported()
     }
 
+    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
+        match self.0 {}
+    }
+
     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
         match self.0 {}
     }
diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs
index 07f4f5f..b387278 100644
--- a/src/libstd/sys/windows/pipe.rs
+++ b/src/libstd/sys/windows/pipe.rs
@@ -37,9 +37,9 @@
 ///
 /// The ours/theirs pipes are *not* specifically readable or writable. Each
 /// one only supports a read or a write, but which is which depends on the
-/// boolean flag given. If `ours_readable` is true then `ours` is readable where
-/// `theirs` is writable. Conversely if `ours_readable` is false then `ours` is
-/// writable where `theirs` is readable.
+/// boolean flag given. If `ours_readable` is `true`, then `ours` is readable and
+/// `theirs` is writable. Conversely, if `ours_readable` is `false`, then `ours`
+/// is writable and `theirs` is readable.
 ///
 /// Also note that the `ours` pipe is always a handle opened up in overlapped
 /// mode. This means that technically speaking it should only ever be used
diff --git a/src/libstd/sys_common/net.rs b/src/libstd/sys_common/net.rs
index b9505aaa..b77bcee 100644
--- a/src/libstd/sys_common/net.rs
+++ b/src/libstd/sys_common/net.rs
@@ -472,6 +472,12 @@
 
     pub fn into_socket(self) -> Socket { self.inner }
 
+    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
+        sockname(|buf, len| unsafe {
+            c::getpeername(*self.inner.as_inner(), buf, len)
+        })
+    }
+
     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
         sockname(|buf, len| unsafe {
             c::getsockname(*self.inner.as_inner(), buf, len)
diff --git a/src/libstd/time.rs b/src/libstd/time.rs
index 6d7093a..4c86f70 100644
--- a/src/libstd/time.rs
+++ b/src/libstd/time.rs
@@ -712,13 +712,6 @@
         assert_almost_eq!(a - second + second, a);
         assert_almost_eq!(a.checked_sub(second).unwrap().checked_add(second).unwrap(), a);
 
-        // A difference of 80 and 800 years cannot fit inside a 32-bit time_t
-        if !(cfg!(unix) && crate::mem::size_of::<libc::time_t>() <= 4) {
-            let eighty_years = second * 60 * 60 * 24 * 365 * 80;
-            assert_almost_eq!(a - eighty_years + eighty_years, a);
-            assert_almost_eq!(a - (eighty_years * 10) + (eighty_years * 10), a);
-        }
-
         let one_second_from_epoch = UNIX_EPOCH + Duration::new(1, 0);
         let one_second_from_epoch2 = UNIX_EPOCH + Duration::new(0, 500_000_000)
             + Duration::new(0, 500_000_000);
@@ -747,8 +740,8 @@
     #[test]
     fn since_epoch() {
         let ts = SystemTime::now();
-        let a = ts.duration_since(UNIX_EPOCH).unwrap();
-        let b = ts.duration_since(UNIX_EPOCH - Duration::new(1, 0)).unwrap();
+        let a = ts.duration_since(UNIX_EPOCH + Duration::new(1, 0)).unwrap();
+        let b = ts.duration_since(UNIX_EPOCH).unwrap();
         assert!(b > a);
         assert_eq!(b - a, Duration::new(1, 0));
 
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index a01a5bb..1a0da73 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -443,14 +443,11 @@
     pub span: Span,
 }
 
-/// A spanned compile-time attribute list item.
-pub type NestedMetaItem = Spanned<NestedMetaItemKind>;
-
 /// Possible values inside of compile-time attribute lists.
 ///
 /// E.g., the '..' in `#[name(..)]`.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
-pub enum NestedMetaItemKind {
+pub enum NestedMetaItem {
     /// A full MetaItem, for recursive meta items.
     MetaItem(MetaItem),
     /// A literal.
@@ -464,7 +461,7 @@
 /// E.g., `#[test]`, `#[derive(..)]`, `#[rustfmt::skip]` or `#[feature = "foo"]`.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct MetaItem {
-    pub ident: Path,
+    pub path: Path,
     pub node: MetaItemKind,
     pub span: Span,
 }
@@ -2207,7 +2204,7 @@
 impl Item {
     /// Return the span that encompasses the attributes.
     pub fn span_with_attributes(&self) -> Span {
-        self.attrs.iter().fold(self.span, |acc, attr| acc.to(attr.span()))
+        self.attrs.iter().fold(self.span, |acc, attr| acc.to(attr.span))
     }
 }
 
diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs
index f7a0009..cdfb83c 100644
--- a/src/libsyntax/attr/builtin.rs
+++ b/src/libsyntax/attr/builtin.rs
@@ -1,6 +1,6 @@
 //! Parsing and validation of builtin attributes
 
-use crate::ast::{self, Attribute, MetaItem, Name, NestedMetaItemKind};
+use crate::ast::{self, Attribute, MetaItem, NestedMetaItem};
 use crate::feature_gate::{Features, GatedCfg};
 use crate::parse::ParseSess;
 
@@ -10,8 +10,8 @@
 use super::{mark_used, MetaItemKind};
 
 enum AttrError {
-    MultipleItem(Name),
-    UnknownMetaItem(Name, &'static [&'static str]),
+    MultipleItem(String),
+    UnknownMetaItem(String, &'static [&'static str]),
     MissingSince,
     MissingFeature,
     MultipleStabilityLevels,
@@ -155,10 +155,7 @@
     attrs.iter().any(|item| {
         item.check_name("feature") &&
         item.meta_item_list().map(|list| {
-            list.iter().any(|mi| {
-                mi.word().map(|w| w.name() == feature_name)
-                         .unwrap_or(false)
-            })
+            list.iter().any(|mi| mi.is_word() && mi.check_name(feature_name))
         }).unwrap_or(false)
     })
 }
@@ -206,7 +203,7 @@
             let meta = meta.as_ref().unwrap();
             let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
                 if item.is_some() {
-                    handle_errors(sess, meta.span, AttrError::MultipleItem(meta.name()));
+                    handle_errors(sess, meta.span, AttrError::MultipleItem(meta.path.to_string()));
                     return false
                 }
                 if let Some(v) = meta.value_str() {
@@ -225,9 +222,9 @@
                     )+
                     for meta in metas {
                         if let Some(mi) = meta.meta_item() {
-                            match &*mi.name().as_str() {
+                            match mi.ident_str() {
                                 $(
-                                    stringify!($name)
+                                    Some(stringify!($name))
                                         => if !get(mi, &mut $name) { continue 'outer },
                                 )+
                                 _ => {
@@ -235,7 +232,7 @@
                                     handle_errors(
                                         sess,
                                         mi.span,
-                                        AttrError::UnknownMetaItem(mi.name(), expected),
+                                        AttrError::UnknownMetaItem(mi.path.to_string(), expected),
                                     );
                                     continue 'outer
                                 }
@@ -243,7 +240,7 @@
                         } else {
                             handle_errors(
                                 sess,
-                                meta.span,
+                                meta.span(),
                                 AttrError::UnsupportedLiteral(
                                     "unsupported literal",
                                     false,
@@ -255,7 +252,7 @@
                 }
             }
 
-            match &*meta.name().as_str() {
+            match meta.ident_str().expect("not a stability level") {
                 "rustc_deprecated" => {
                     if rustc_depr.is_some() {
                         span_err!(diagnostic, item_sp, E0540,
@@ -274,11 +271,11 @@
                             })
                         }
                         (None, _) => {
-                            handle_errors(sess, attr.span(), AttrError::MissingSince);
+                            handle_errors(sess, attr.span, AttrError::MissingSince);
                             continue
                         }
                         _ => {
-                            span_err!(diagnostic, attr.span(), E0543, "missing 'reason'");
+                            span_err!(diagnostic, attr.span, E0543, "missing 'reason'");
                             continue
                         }
                     }
@@ -294,13 +291,13 @@
                     if let Some(feature) = feature {
                         rustc_const_unstable = Some(feature);
                     } else {
-                        span_err!(diagnostic, attr.span(), E0629, "missing 'feature'");
+                        span_err!(diagnostic, attr.span, E0629, "missing 'feature'");
                         continue
                     }
                 }
                 "unstable" => {
                     if stab.is_some() {
-                        handle_errors(sess, attr.span(), AttrError::MultipleStabilityLevels);
+                        handle_errors(sess, attr.span, AttrError::MultipleStabilityLevels);
                         break
                     }
 
@@ -309,16 +306,16 @@
                     let mut issue = None;
                     for meta in metas {
                         if let Some(mi) = meta.meta_item() {
-                            match &*mi.name().as_str() {
-                                "feature" => if !get(mi, &mut feature) { continue 'outer },
-                                "reason" => if !get(mi, &mut reason) { continue 'outer },
-                                "issue" => if !get(mi, &mut issue) { continue 'outer },
+                            match mi.ident_str() {
+                                Some("feature") => if !get(mi, &mut feature) { continue 'outer },
+                                Some("reason") => if !get(mi, &mut reason) { continue 'outer },
+                                Some("issue") => if !get(mi, &mut issue) { continue 'outer },
                                 _ => {
                                     handle_errors(
                                         sess,
-                                        meta.span,
+                                        meta.span(),
                                         AttrError::UnknownMetaItem(
-                                            mi.name(),
+                                            mi.path.to_string(),
                                             &["feature", "reason", "issue"]
                                         ),
                                     );
@@ -328,7 +325,7 @@
                         } else {
                             handle_errors(
                                 sess,
-                                meta.span,
+                                meta.span(),
                                 AttrError::UnsupportedLiteral(
                                     "unsupported literal",
                                     false,
@@ -347,7 +344,7 @@
                                         if let Ok(issue) = issue.as_str().parse() {
                                             issue
                                         } else {
-                                            span_err!(diagnostic, attr.span(), E0545,
+                                            span_err!(diagnostic, attr.span, E0545,
                                                       "incorrect 'issue'");
                                             continue
                                         }
@@ -360,42 +357,44 @@
                             })
                         }
                         (None, _, _) => {
-                            handle_errors(sess, attr.span(), AttrError::MissingFeature);
+                            handle_errors(sess, attr.span, AttrError::MissingFeature);
                             continue
                         }
                         _ => {
-                            span_err!(diagnostic, attr.span(), E0547, "missing 'issue'");
+                            span_err!(diagnostic, attr.span, E0547, "missing 'issue'");
                             continue
                         }
                     }
                 }
                 "stable" => {
                     if stab.is_some() {
-                        handle_errors(sess, attr.span(), AttrError::MultipleStabilityLevels);
+                        handle_errors(sess, attr.span, AttrError::MultipleStabilityLevels);
                         break
                     }
 
                     let mut feature = None;
                     let mut since = None;
                     for meta in metas {
-                        match &meta.node {
-                            NestedMetaItemKind::MetaItem(mi) => {
-                                match &*mi.name().as_str() {
-                                    "feature" => if !get(mi, &mut feature) { continue 'outer },
-                                    "since" => if !get(mi, &mut since) { continue 'outer },
+                        match meta {
+                            NestedMetaItem::MetaItem(mi) => {
+                                match mi.ident_str() {
+                                    Some("feature") =>
+                                        if !get(mi, &mut feature) { continue 'outer },
+                                    Some("since") =>
+                                        if !get(mi, &mut since) { continue 'outer },
                                     _ => {
                                         handle_errors(
                                             sess,
-                                            meta.span,
+                                            meta.span(),
                                             AttrError::UnknownMetaItem(
-                                                mi.name(), &["since", "note"],
+                                                mi.path.to_string(), &["since", "note"],
                                             ),
                                         );
                                         continue 'outer
                                     }
                                 }
                             },
-                            NestedMetaItemKind::Literal(lit) => {
+                            NestedMetaItem::Literal(lit) => {
                                 handle_errors(
                                     sess,
                                     lit.span,
@@ -422,11 +421,11 @@
                             })
                         }
                         (None, _) => {
-                            handle_errors(sess, attr.span(), AttrError::MissingFeature);
+                            handle_errors(sess, attr.span, AttrError::MissingFeature);
                             continue
                         }
                         _ => {
-                            handle_errors(sess, attr.span(), AttrError::MissingSince);
+                            handle_errors(sess, attr.span, AttrError::MissingSince);
                             continue
                         }
                     }
@@ -483,8 +482,8 @@
             gated_cfg.check_and_emit(sess, feats);
         }
         let error = |span, msg| { sess.span_diagnostic.span_err(span, msg); true };
-        if cfg.ident.segments.len() != 1 {
-            return error(cfg.ident.span, "`cfg` predicate key must be an identifier");
+        if cfg.path.segments.len() != 1 {
+            return error(cfg.path.span, "`cfg` predicate key must be an identifier");
         }
         match &cfg.node {
             MetaItemKind::List(..) => {
@@ -502,7 +501,8 @@
                 true
             }
             MetaItemKind::NameValue(..) | MetaItemKind::Word => {
-                sess.config.contains(&(cfg.name(), cfg.value_str()))
+                let ident = cfg.ident().expect("multi-segment cfg predicate");
+                sess.config.contains(&(ident.name, cfg.value_str()))
             }
         }
     })
@@ -520,7 +520,7 @@
                 if !mi.is_meta_item() {
                     handle_errors(
                         sess,
-                        mi.span,
+                        mi.span(),
                         AttrError::UnsupportedLiteral(
                             "unsupported literal",
                             false
@@ -532,14 +532,14 @@
 
             // The unwraps below may look dangerous, but we've already asserted
             // that they won't fail with the loop above.
-            match &*cfg.name().as_str() {
-                "any" => mis.iter().any(|mi| {
+            match cfg.ident_str() {
+                Some("any") => mis.iter().any(|mi| {
                     eval_condition(mi.meta_item().unwrap(), sess, eval)
                 }),
-                "all" => mis.iter().all(|mi| {
+                Some("all") => mis.iter().all(|mi| {
                     eval_condition(mi.meta_item().unwrap(), sess, eval)
                 }),
-                "not" => {
+                Some("not") => {
                     if mis.len() != 1 {
                         span_err!(sess.span_diagnostic, cfg.span, E0536, "expected 1 cfg-pattern");
                         return false;
@@ -547,8 +547,9 @@
 
                     !eval_condition(mis[0].meta_item().unwrap(), sess, eval)
                 },
-                p => {
-                    span_err!(sess.span_diagnostic, cfg.span, E0537, "invalid predicate `{}`", p);
+                _ => {
+                    span_err!(sess.span_diagnostic, cfg.span, E0537,
+                              "invalid predicate `{}`", cfg.path);
                     false
                 }
             }
@@ -602,7 +603,9 @@
             MetaItemKind::List(list) => {
                 let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
                     if item.is_some() {
-                        handle_errors(sess, meta.span, AttrError::MultipleItem(meta.name()));
+                        handle_errors(
+                            sess, meta.span, AttrError::MultipleItem(meta.path.to_string())
+                        );
                         return false
                     }
                     if let Some(v) = meta.value_str() {
@@ -630,22 +633,23 @@
                 let mut since = None;
                 let mut note = None;
                 for meta in list {
-                    match &meta.node {
-                        NestedMetaItemKind::MetaItem(mi) => {
-                            match &*mi.name().as_str() {
-                                "since" => if !get(mi, &mut since) { continue 'outer },
-                                "note" => if !get(mi, &mut note) { continue 'outer },
+                    match meta {
+                        NestedMetaItem::MetaItem(mi) => {
+                            match mi.ident_str() {
+                                Some("since") => if !get(mi, &mut since) { continue 'outer },
+                                Some("note") => if !get(mi, &mut note) { continue 'outer },
                                 _ => {
                                     handle_errors(
                                         sess,
-                                        meta.span,
-                                        AttrError::UnknownMetaItem(mi.name(), &["since", "note"]),
+                                        meta.span(),
+                                        AttrError::UnknownMetaItem(mi.path.to_string(),
+                                                                   &["since", "note"]),
                                     );
                                     continue 'outer
                                 }
                             }
                         }
-                        NestedMetaItemKind::Literal(lit) => {
+                        NestedMetaItem::Literal(lit) => {
                             handle_errors(
                                 sess,
                                 lit.span,
@@ -714,7 +718,7 @@
                 if !item.is_meta_item() {
                     handle_errors(
                         sess,
-                        item.span,
+                        item.span(),
                         AttrError::UnsupportedLiteral(
                             "meta item in `repr` must be an identifier",
                             false,
@@ -724,19 +728,13 @@
                 }
 
                 let mut recognised = false;
-                if let Some(mi) = item.word() {
-                    let word = &*mi.name().as_str();
-                    let hint = match word {
-                        "C" => Some(ReprC),
-                        "packed" => Some(ReprPacked(1)),
-                        "simd" => Some(ReprSimd),
-                        "transparent" => Some(ReprTransparent),
-                        _ => match int_type_of_word(word) {
-                            Some(ity) => Some(ReprInt(ity)),
-                            None => {
-                                None
-                            }
-                        }
+                if item.is_word() {
+                    let hint = match item.ident_str() {
+                        Some("C") => Some(ReprC),
+                        Some("packed") => Some(ReprPacked(1)),
+                        Some("simd") => Some(ReprSimd),
+                        Some("transparent") => Some(ReprTransparent),
+                        name => name.and_then(|name| int_type_of_word(name)).map(ReprInt),
                     };
 
                     if let Some(h) = hint {
@@ -777,20 +775,20 @@
                         };
                     }
                     if let Some(literal_error) = literal_error {
-                        span_err!(diagnostic, item.span, E0589,
+                        span_err!(diagnostic, item.span(), E0589,
                                   "invalid `repr(align)` attribute: {}", literal_error);
                     }
                 } else {
                     if let Some(meta_item) = item.meta_item() {
-                        if meta_item.name() == "align" {
+                        if meta_item.check_name("align") {
                             if let MetaItemKind::NameValue(ref value) = meta_item.node {
                                 recognised = true;
-                                let mut err = struct_span_err!(diagnostic, item.span, E0693,
+                                let mut err = struct_span_err!(diagnostic, item.span(), E0693,
                                     "incorrect `repr(align)` attribute format");
                                 match value.node {
                                     ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => {
                                         err.span_suggestion(
-                                            item.span,
+                                            item.span(),
                                             "use parentheses instead",
                                             format!("align({})", int),
                                             Applicability::MachineApplicable
@@ -798,7 +796,7 @@
                                     }
                                     ast::LitKind::Str(s, _) => {
                                         err.span_suggestion(
-                                            item.span,
+                                            item.span(),
                                             "use parentheses instead",
                                             format!("align({})", s),
                                             Applicability::MachineApplicable
@@ -813,7 +811,7 @@
                 }
                 if !recognised {
                     // Not a word we recognize
-                    span_err!(diagnostic, item.span, E0552,
+                    span_err!(diagnostic, item.span(), E0552,
                               "unrecognized representation hint");
                 }
             }
diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs
index b5fc850..1a8faa4 100644
--- a/src/libsyntax/attr/mod.rs
+++ b/src/libsyntax/attr/mod.rs
@@ -13,7 +13,7 @@
 
 use crate::ast;
 use crate::ast::{AttrId, Attribute, AttrStyle, Name, Ident, Path, PathSegment};
-use crate::ast::{MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind};
+use crate::ast::{MetaItem, MetaItemKind, NestedMetaItem};
 use crate::ast::{Lit, LitKind, Expr, ExprKind, Item, Local, Stmt, StmtKind, GenericParam};
 use crate::mut_visit::visit_clobber;
 use crate::source_map::{BytePos, Spanned, respan, dummy_spanned};
@@ -64,36 +64,33 @@
 }
 
 impl NestedMetaItem {
-    /// Returns the MetaItem if self is a NestedMetaItemKind::MetaItem.
+    /// Returns the MetaItem if self is a NestedMetaItem::MetaItem.
     pub fn meta_item(&self) -> Option<&MetaItem> {
-        match self.node {
-            NestedMetaItemKind::MetaItem(ref item) => Some(item),
+        match *self {
+            NestedMetaItem::MetaItem(ref item) => Some(item),
             _ => None
         }
     }
 
-    /// Returns the Lit if self is a NestedMetaItemKind::Literal.
+    /// Returns the Lit if self is a NestedMetaItem::Literal.
     pub fn literal(&self) -> Option<&Lit> {
-        match self.node {
-            NestedMetaItemKind::Literal(ref lit) => Some(lit),
+        match *self {
+            NestedMetaItem::Literal(ref lit) => Some(lit),
             _ => None
         }
     }
 
-    /// Returns the Span for `self`.
-    pub fn span(&self) -> Span {
-        self.span
-    }
-
     /// Returns `true` if this list item is a MetaItem with a name of `name`.
     pub fn check_name(&self, name: &str) -> bool {
         self.meta_item().map_or(false, |meta_item| meta_item.check_name(name))
     }
 
-    /// Returns the name of the meta item, e.g., `foo` in `#[foo]`,
-    /// `#[foo="bar"]` and `#[foo(bar)]`, if self is a MetaItem
-    pub fn name(&self) -> Option<Name> {
-        self.meta_item().and_then(|meta_item| Some(meta_item.name()))
+    /// For a single-segment meta-item returns its name, otherwise returns `None`.
+    pub fn ident(&self) -> Option<Ident> {
+        self.meta_item().and_then(|meta_item| meta_item.ident())
+    }
+    pub fn ident_str(&self) -> Option<&str> {
+        self.ident().map(|name| name.as_str().get())
     }
 
     /// Gets the string value if self is a MetaItem and the MetaItem is a
@@ -108,25 +105,14 @@
             |meta_item| meta_item.meta_item_list().and_then(
                 |meta_item_list| {
                     if meta_item_list.len() == 1 {
-                        let nested_item = &meta_item_list[0];
-                        if nested_item.is_literal() {
-                            Some((meta_item.name(), nested_item.literal().unwrap()))
-                        } else {
-                            None
+                        if let Some(ident) = meta_item.ident() {
+                            if let Some(lit) = meta_item_list[0].literal() {
+                                return Some((ident.name, lit));
+                            }
                         }
                     }
-                    else {
-                        None
-                    }}))
-    }
-
-    /// Returns a MetaItem if self is a MetaItem with Kind Word.
-    pub fn word(&self) -> Option<&MetaItem> {
-        self.meta_item().and_then(|meta_item| if meta_item.is_word() {
-            Some(meta_item)
-        } else {
-            None
-        })
+                    None
+                }))
     }
 
     /// Gets a list of inner meta items from a list MetaItem type.
@@ -146,7 +132,7 @@
 
     /// Returns `true` if self is a MetaItem and the meta item is a word.
     pub fn is_word(&self) -> bool {
-        self.word().is_some()
+        self.meta_item().map_or(false, |meta_item| meta_item.is_word())
     }
 
     /// Returns `true` if self is a MetaItem and the meta item is a ValueString.
@@ -160,10 +146,6 @@
     }
 }
 
-fn name_from_path(path: &Path) -> Name {
-    path.segments.last().expect("empty path in attribute").ident.name
-}
-
 impl Attribute {
     /// Returns `true` if the attribute's path matches the argument. If it matches, then the
     /// attribute is marked as used.
@@ -177,10 +159,16 @@
         matches
     }
 
-    /// Returns the **last** segment of the name of this attribute.
-    /// e.g., `foo` for `#[foo]`, `skip` for `#[rustfmt::skip]`.
-    pub fn name(&self) -> Name {
-        name_from_path(&self.path)
+    /// For a single-segment attribute returns its name, otherwise returns `None`.
+    pub fn ident(&self) -> Option<Ident> {
+        if self.path.segments.len() == 1 {
+            Some(self.path.segments[0].ident)
+        } else {
+            None
+        }
+    }
+    pub fn ident_str(&self) -> Option<&str> {
+        self.ident().map(|name| name.as_str().get())
     }
 
     pub fn value_str(&self) -> Option<Symbol> {
@@ -195,11 +183,7 @@
     }
 
     pub fn is_word(&self) -> bool {
-        self.path.segments.len() == 1 && self.tokens.is_empty()
-    }
-
-    pub fn span(&self) -> Span {
-        self.span
+        self.tokens.is_empty()
     }
 
     pub fn is_meta_item_list(&self) -> bool {
@@ -213,8 +197,16 @@
 }
 
 impl MetaItem {
-    pub fn name(&self) -> Name {
-        name_from_path(&self.ident)
+    /// For a single-segment meta-item returns its name, otherwise returns `None`.
+    pub fn ident(&self) -> Option<Ident> {
+        if self.path.segments.len() == 1 {
+            Some(self.path.segments[0].ident)
+        } else {
+            None
+        }
+    }
+    pub fn ident_str(&self) -> Option<&str> {
+        self.ident().map(|name| name.as_str().get())
     }
 
     // #[attribute(name = "value")]
@@ -252,10 +244,8 @@
         }
     }
 
-    pub fn span(&self) -> Span { self.span }
-
     pub fn check_name(&self, name: &str) -> bool {
-        self.name() == name
+        self.path == name
     }
 
     pub fn is_value_str(&self) -> bool {
@@ -265,14 +255,6 @@
     pub fn is_meta_item_list(&self) -> bool {
         self.meta_item_list().is_some()
     }
-
-    pub fn is_scoped(&self) -> Option<Ident> {
-        if self.ident.segments.len() > 1 {
-            Some(self.ident.segments[0].ident)
-        } else {
-            None
-        }
-    }
 }
 
 impl Attribute {
@@ -280,7 +262,7 @@
     pub fn meta(&self) -> Option<MetaItem> {
         let mut tokens = self.tokens.trees().peekable();
         Some(MetaItem {
-            ident: self.path.clone(),
+            path: self.path.clone(),
             node: if let Some(node) = MetaItemKind::from_tokens(&mut tokens) {
                 if tokens.peek().is_some() {
                     return None;
@@ -326,7 +308,7 @@
 
     pub fn parse_meta<'a>(&self, sess: &'a ParseSess) -> PResult<'a, MetaItem> {
         Ok(MetaItem {
-            ident: self.path.clone(),
+            path: self.path.clone(),
             node: self.parse(sess, |parser| parser.parse_meta_item_kind())?,
             span: self.span,
         })
@@ -364,19 +346,19 @@
 }
 
 pub fn mk_name_value_item(span: Span, ident: Ident, value: ast::Lit) -> MetaItem {
-    MetaItem { ident: Path::from_ident(ident), span, node: MetaItemKind::NameValue(value) }
+    MetaItem { path: Path::from_ident(ident), span, node: MetaItemKind::NameValue(value) }
 }
 
 pub fn mk_list_item(span: Span, ident: Ident, items: Vec<NestedMetaItem>) -> MetaItem {
-    MetaItem { ident: Path::from_ident(ident), span, node: MetaItemKind::List(items) }
+    MetaItem { path: Path::from_ident(ident), span, node: MetaItemKind::List(items) }
 }
 
 pub fn mk_word_item(ident: Ident) -> MetaItem {
-    MetaItem { ident: Path::from_ident(ident), span: ident.span, node: MetaItemKind::Word }
+    MetaItem { path: Path::from_ident(ident), span: ident.span, node: MetaItemKind::Word }
 }
 
 pub fn mk_nested_word_item(ident: Ident) -> NestedMetaItem {
-    respan(ident.span, NestedMetaItemKind::MetaItem(mk_word_item(ident)))
+    NestedMetaItem::MetaItem(mk_word_item(ident))
 }
 
 pub fn mk_attr_id() -> AttrId {
@@ -400,7 +382,7 @@
     Attribute {
         id,
         style: ast::AttrStyle::Inner,
-        path: item.ident,
+        path: item.path,
         tokens: item.node.tokens(item.span),
         is_sugared_doc: false,
         span: sp,
@@ -417,7 +399,7 @@
     Attribute {
         id,
         style: ast::AttrStyle::Outer,
-        path: item.ident,
+        path: item.path,
         tokens: item.node.tokens(item.span),
         is_sugared_doc: false,
         span: sp,
@@ -468,7 +450,7 @@
     fn tokens(&self) -> TokenStream {
         let mut idents = vec![];
         let mut last_pos = BytePos(0 as u32);
-        for (i, segment) in self.ident.segments.iter().enumerate() {
+        for (i, segment) in self.path.segments.iter().enumerate() {
             let is_first = i == 0;
             if !is_first {
                 let mod_sep_span = Span::new(last_pos,
@@ -488,7 +470,7 @@
         where I: Iterator<Item = TokenTree>,
     {
         // FIXME: Share code with `parse_path`.
-        let ident = match tokens.next() {
+        let path = match tokens.next() {
             Some(TokenTree::Token(span, token @ Token::Ident(..))) |
             Some(TokenTree::Token(span, token @ Token::ModSep)) => 'arm: {
                 let mut segments = if let Token::Ident(ident, _) = token {
@@ -529,11 +511,11 @@
         let node = MetaItemKind::from_tokens(tokens)?;
         let hi = match node {
             MetaItemKind::NameValue(ref lit) => lit.span.hi(),
-            MetaItemKind::List(..) => list_closing_paren_pos.unwrap_or(ident.span.hi()),
-            _ => ident.span.hi(),
+            MetaItemKind::List(..) => list_closing_paren_pos.unwrap_or(path.span.hi()),
+            _ => path.span.hi(),
         };
-        let span = ident.span.with_hi(hi);
-        Some(MetaItem { ident, node, span })
+        let span = path.span.with_hi(hi);
+        Some(MetaItem { path, node, span })
     }
 }
 
@@ -552,7 +534,7 @@
                     if i > 0 {
                         tokens.push(TokenTree::Token(span, Token::Comma).into());
                     }
-                    item.node.tokens().append_to_tree_and_joint_vec(&mut tokens);
+                    item.tokens().append_to_tree_and_joint_vec(&mut tokens);
                 }
                 TokenTree::Delimited(
                     DelimSpan::from_single(span),
@@ -586,8 +568,8 @@
         let mut tokens = delimited.into_trees().peekable();
         let mut result = Vec::new();
         while let Some(..) = tokens.peek() {
-            let item = NestedMetaItemKind::from_tokens(&mut tokens)?;
-            result.push(respan(item.span(), item));
+            let item = NestedMetaItem::from_tokens(&mut tokens)?;
+            result.push(item);
             match tokens.next() {
                 None | Some(TokenTree::Token(_, Token::Comma)) => {}
                 _ => return None,
@@ -597,32 +579,32 @@
     }
 }
 
-impl NestedMetaItemKind {
-    fn span(&self) -> Span {
+impl NestedMetaItem {
+    pub fn span(&self) -> Span {
         match *self {
-            NestedMetaItemKind::MetaItem(ref item) => item.span,
-            NestedMetaItemKind::Literal(ref lit) => lit.span,
+            NestedMetaItem::MetaItem(ref item) => item.span,
+            NestedMetaItem::Literal(ref lit) => lit.span,
         }
     }
 
     fn tokens(&self) -> TokenStream {
         match *self {
-            NestedMetaItemKind::MetaItem(ref item) => item.tokens(),
-            NestedMetaItemKind::Literal(ref lit) => lit.tokens(),
+            NestedMetaItem::MetaItem(ref item) => item.tokens(),
+            NestedMetaItem::Literal(ref lit) => lit.tokens(),
         }
     }
 
-    fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<NestedMetaItemKind>
+    fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<NestedMetaItem>
         where I: Iterator<Item = TokenTree>,
     {
         if let Some(TokenTree::Token(span, token)) = tokens.peek().cloned() {
             if let Some(node) = LitKind::from_token(token) {
                 tokens.next();
-                return Some(NestedMetaItemKind::Literal(respan(span, node)));
+                return Some(NestedMetaItem::Literal(respan(span, node)));
             }
         }
 
-        MetaItem::from_tokens(tokens).map(NestedMetaItemKind::MetaItem)
+        MetaItem::from_tokens(tokens).map(NestedMetaItem::MetaItem)
     }
 }
 
diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs
index 4e4432a..c300ffc 100644
--- a/src/libsyntax/config.rs
+++ b/src/libsyntax/config.rs
@@ -24,8 +24,8 @@
 }
 
 // `cfg_attr`-process the crate's attributes and compute the crate's features.
-pub fn features(mut krate: ast::Crate, sess: &ParseSess, edition: Edition)
-                -> (ast::Crate, Features) {
+pub fn features(mut krate: ast::Crate, sess: &ParseSess, edition: Edition,
+                allow_features: &Option<Vec<String>>) -> (ast::Crate, Features) {
     let features;
     {
         let mut strip_unconfigured = StripUnconfigured {
@@ -43,7 +43,7 @@
             return (krate, Features::new());
         }
 
-        features = get_features(&sess.span_diagnostic, &krate.attrs, edition);
+        features = get_features(&sess.span_diagnostic, &krate.attrs, edition, allow_features);
 
         // Avoid reconfiguring malformed `cfg_attr`s
         if err_count == sess.span_diagnostic.err_count() {
@@ -181,13 +181,13 @@
             if nested_meta_items.is_empty() {
                 return error(meta_item.span, "`cfg` predicate is not specified", "");
             } else if nested_meta_items.len() > 1 {
-                return error(nested_meta_items.last().unwrap().span,
+                return error(nested_meta_items.last().unwrap().span(),
                              "multiple `cfg` predicates are specified", "");
             }
 
             match nested_meta_items[0].meta_item() {
                 Some(meta_item) => attr::cfg_matches(meta_item, self.sess, self.features),
-                None => error(nested_meta_items[0].span,
+                None => error(nested_meta_items[0].span(),
                               "`cfg` predicate key cannot be a literal", ""),
             }
         })
diff --git a/src/libsyntax/diagnostic_list.rs b/src/libsyntax/diagnostic_list.rs
index 2c367f1..ac24475 100644
--- a/src/libsyntax/diagnostic_list.rs
+++ b/src/libsyntax/diagnostic_list.rs
@@ -378,6 +378,21 @@
 
 "##,
 
+E0725: r##"
+A feature attribute named a feature that was disallowed in the compiler
+command line flags.
+
+Erroneous code example:
+
+```ignore (can't specify compiler flags from doctests)
+#![feature(never_type)] // error: the feature `never_type` is not in
+                        // the list of allowed features
+```
+
+Delete the offending feature attribute, or add it to the list of allowed
+features in the `-Z allow_features` flag.
+"##,
+
 }
 
 register_diagnostics! {
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index b805213..8235867 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -601,7 +601,7 @@
                 res
             }
             ProcMacroDerive(..) | BuiltinDerive(..) => {
-                self.cx.span_err(attr.span, &format!("`{}` is a derive mode", attr.path));
+                self.cx.span_err(attr.span, &format!("`{}` is a derive macro", attr.path));
                 self.cx.trace_macros_diag();
                 invoc.fragment_kind.dummy(attr.span)
             }
@@ -822,7 +822,7 @@
             }
 
             ProcMacroDerive(..) | BuiltinDerive(..) => {
-                self.cx.span_err(path.span, &format!("`{}` is a derive mode", path));
+                self.cx.span_err(path.span, &format!("`{}` is a derive macro", path));
                 self.cx.trace_macros_diag();
                 kind.dummy(span)
             }
@@ -929,7 +929,7 @@
                 invoc.expansion_data.mark.set_expn_info(expn_info);
                 let span = span.with_ctxt(self.cx.backtrace());
                 let dummy = ast::MetaItem { // FIXME(jseyfried) avoid this
-                    ident: Path::from_ident(keywords::Invalid.ident()),
+                    path: Path::from_ident(keywords::Invalid.ident()),
                     span: DUMMY_SP,
                     node: ast::MetaItemKind::Word,
                 };
@@ -1520,23 +1520,23 @@
                             self.cx.source_map().new_source_file(filename.into(), src);
 
                             let include_info = vec![
-                                dummy_spanned(ast::NestedMetaItemKind::MetaItem(
+                                ast::NestedMetaItem::MetaItem(
                                     attr::mk_name_value_item_str(
                                         Ident::from_str("file"),
                                         dummy_spanned(file),
                                     ),
-                                )),
-                                dummy_spanned(ast::NestedMetaItemKind::MetaItem(
+                                ),
+                                ast::NestedMetaItem::MetaItem(
                                     attr::mk_name_value_item_str(
                                         Ident::from_str("contents"),
                                         dummy_spanned(src_interned),
                                     ),
-                                )),
+                                ),
                             ];
 
                             let include_ident = Ident::from_str("include");
                             let item = attr::mk_list_item(DUMMY_SP, include_ident, include_info);
-                            items.push(dummy_spanned(ast::NestedMetaItemKind::MetaItem(item)));
+                            items.push(ast::NestedMetaItem::MetaItem(item));
                         }
                         Err(e) => {
                             let lit = it
@@ -1569,7 +1569,7 @@
                     }
                 } else {
                     let mut err = self.cx.struct_span_err(
-                        it.span,
+                        it.span(),
                         &format!("expected path to external documentation"),
                     );
 
@@ -1590,7 +1590,7 @@
                     };
 
                     err.span_suggestion(
-                        it.span,
+                        it.span(),
                         "provide a file path with `=`",
                         format!("include = \"{}\"", path),
                         applicability,
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index bd64bb0..1291204 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -380,9 +380,14 @@
             .map(|attr| attr
                 .meta_item_list()
                 .map(|list| list.iter()
-                    .map(|it| it.name().unwrap_or_else(|| sess.span_diagnostic.span_bug(
-                        it.span, "allow internal unstable expects feature names",
-                    )))
+                    .filter_map(|it| {
+                        let name = it.ident().map(|ident| ident.name);
+                        if name.is_none() {
+                            sess.span_diagnostic.span_err(it.span(),
+                                "allow internal unstable expects feature names")
+                        }
+                        name
+                    })
                     .collect::<Vec<Symbol>>().into()
                 )
                 .unwrap_or_else(|| {
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 279e208..9beaabb 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -1042,7 +1042,7 @@
                                              "rustc_attrs",
                                              "internal rustc attributes will never be stable",
                                              cfg_fn!(rustc_attrs))),
-    ("rustc_item_path", Whitelisted, template!(Word), Gated(Stability::Unstable,
+    ("rustc_def_path", Whitelisted, template!(Word), Gated(Stability::Unstable,
                                            "rustc_attrs",
                                            "internal rustc attributes will never be stable",
                                            cfg_fn!(rustc_attrs))),
@@ -1289,9 +1289,8 @@
 
 impl GatedCfg {
     pub fn gate(cfg: &ast::MetaItem) -> Option<GatedCfg> {
-        let name = cfg.name().as_str();
         GATED_CFGS.iter()
-                  .position(|info| info.0 == name)
+                  .position(|info| cfg.check_name(info.0))
                   .map(|idx| {
                       GatedCfg {
                           span: cfg.span,
@@ -1342,16 +1341,16 @@
 impl<'a> Context<'a> {
     fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
         debug!("check_attribute(attr = {:?})", attr);
-        let name = attr.name().as_str();
+        let name = attr.ident_str();
         for &(n, ty, _template, ref gateage) in BUILTIN_ATTRIBUTES {
-            if name == n {
+            if name == Some(n) {
                 if let Gated(_, name, desc, ref has_feature) = *gateage {
                     if !attr.span.allows_unstable(name) {
                         gate_feature_fn!(
                             self, has_feature, attr.span, name, desc, GateStrength::Hard
                         );
                     }
-                } else if name == "doc" {
+                } else if n == "doc" {
                     if let Some(content) = attr.meta_item_list() {
                         if content.iter().any(|c| c.check_name("include")) {
                             gate_feature!(self, external_doc, attr.span,
@@ -1374,7 +1373,7 @@
             }
         }
         if !attr::is_known(attr) {
-            if name.starts_with("rustc_") {
+            if name.map_or(false, |name| name.starts_with("rustc_")) {
                 let msg = "unless otherwise specified, attributes with the prefix `rustc_` \
                            are reserved for internal compiler diagnostics";
                 gate_feature!(self, rustc_attrs, attr.span, msg);
@@ -2008,7 +2007,7 @@
 }
 
 pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
-                    crate_edition: Edition) -> Features {
+                    crate_edition: Edition, allow_features: &Option<Vec<String>>) -> Features {
     fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) {
         let mut err = struct_span_err!(span_handler, span, E0557, "feature has been removed");
         if let Some(reason) = reason {
@@ -2055,15 +2054,14 @@
         };
 
         for mi in list {
-            let name = if let Some(word) = mi.word() {
-                word.name()
-            } else {
-                continue
+            let name = match mi.ident_str() {
+                Some(name) if mi.is_word() => name,
+                _ => continue,
             };
 
-            if incomplete_features.iter().any(|f| *f == name.as_str()) {
+            if incomplete_features.iter().any(|f| *f == name) {
                 span_handler.struct_span_warn(
-                    mi.span,
+                    mi.span(),
                     &format!(
                         "the feature `{}` is incomplete and may cause the compiler to crash",
                         name
@@ -2101,18 +2099,19 @@
         };
 
         for mi in list {
-            let name = if let Some(word) = mi.word() {
-                word.name()
-            } else {
-                span_err!(span_handler, mi.span, E0556,
-                          "malformed feature, expected just one word");
-                continue
+            let name = match mi.ident() {
+                Some(ident) if mi.is_word() => ident.name,
+                _ => {
+                    span_err!(span_handler, mi.span(), E0556,
+                            "malformed feature, expected just one word");
+                    continue
+                }
             };
 
             if let Some(edition) = edition_enabled_features.get(&name) {
                 struct_span_warn!(
                     span_handler,
-                    mi.span,
+                    mi.span(),
                     E0705,
                     "the feature `{}` is included in the Rust {} edition",
                     name,
@@ -2127,25 +2126,34 @@
             }
 
             if let Some((.., set)) = ACTIVE_FEATURES.iter().find(|f| name == f.0) {
-                set(&mut features, mi.span);
-                features.declared_lang_features.push((name, mi.span, None));
+                if let Some(allowed) = allow_features.as_ref() {
+                    if allowed.iter().find(|f| *f == name.as_str()).is_none() {
+                        span_err!(span_handler, mi.span(), E0725,
+                                  "the feature `{}` is not in the list of allowed features",
+                                  name);
+                        continue;
+                    }
+                }
+
+                set(&mut features, mi.span());
+                features.declared_lang_features.push((name, mi.span(), None));
                 continue
             }
 
             let removed = REMOVED_FEATURES.iter().find(|f| name == f.0);
             let stable_removed = STABLE_REMOVED_FEATURES.iter().find(|f| name == f.0);
             if let Some((.., reason)) = removed.or(stable_removed) {
-                feature_removed(span_handler, mi.span, *reason);
+                feature_removed(span_handler, mi.span(), *reason);
                 continue
             }
 
             if let Some((_, since, ..)) = ACCEPTED_FEATURES.iter().find(|f| name == f.0) {
                 let since = Some(Symbol::intern(since));
-                features.declared_lang_features.push((name, mi.span, since));
+                features.declared_lang_features.push((name, mi.span(), since));
                 continue
             }
 
-            features.declared_lib_features.push((name, mi.span));
+            features.declared_lib_features.push((name, mi.span()));
         }
     }
 
diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs
index 802b780..462346d 100644
--- a/src/libsyntax/mut_visit.rs
+++ b/src/libsyntax/mut_visit.rs
@@ -539,16 +539,14 @@
 }
 
 pub fn noop_visit_meta_list_item<T: MutVisitor>(li: &mut NestedMetaItem, vis: &mut T) {
-    let Spanned { node, span } = li;
-    match node {
-        NestedMetaItemKind::MetaItem(mi) => vis.visit_meta_item(mi),
-        NestedMetaItemKind::Literal(_lit) => {}
+    match li {
+        NestedMetaItem::MetaItem(mi) => vis.visit_meta_item(mi),
+        NestedMetaItem::Literal(_lit) => {}
     }
-    vis.visit_span(span);
 }
 
 pub fn noop_visit_meta_item<T: MutVisitor>(mi: &mut MetaItem, vis: &mut T) {
-    let MetaItem { ident: _, node, span } = mi;
+    let MetaItem { path: _, node, span } = mi;
     match node {
         MetaItemKind::Word => {}
         MetaItemKind::List(mis) => visit_vec(mis, |mi| vis.visit_meta_list_item(mi)),
@@ -1340,4 +1338,3 @@
         })
     }
 }
-
diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs
index e93e15f..4211268 100644
--- a/src/libsyntax/parse/attr.rs
+++ b/src/libsyntax/parse/attr.rs
@@ -1,6 +1,5 @@
 use crate::attr;
 use crate::ast;
-use crate::source_map::respan;
 use crate::parse::{SeqSep, PResult};
 use crate::parse::token::{self, Nonterminal, DelimToken};
 use crate::parse::parser::{Parser, TokenType, PathStyle};
@@ -149,7 +148,7 @@
         };
         Ok(if let Some(meta) = meta {
             self.bump();
-            (meta.ident, meta.node.tokens(meta.span))
+            (meta.path, meta.node.tokens(meta.span))
         } else {
             let path = self.parse_path(PathStyle::Mod)?;
             let tokens = if self.check(&token::OpenDelim(DelimToken::Paren)) ||
@@ -250,10 +249,10 @@
         }
 
         let lo = self.span;
-        let ident = self.parse_path(PathStyle::Mod)?;
+        let path = self.parse_path(PathStyle::Mod)?;
         let node = self.parse_meta_item_kind()?;
         let span = lo.to(self.prev_span);
-        Ok(ast::MetaItem { ident, node, span })
+        Ok(ast::MetaItem { path, node, span })
     }
 
     crate fn parse_meta_item_kind(&mut self) -> PResult<'a, ast::MetaItemKind> {
@@ -268,18 +267,16 @@
 
     /// matches meta_item_inner : (meta_item | UNSUFFIXED_LIT) ;
     fn parse_meta_item_inner(&mut self) -> PResult<'a, ast::NestedMetaItem> {
-        let lo = self.span;
-
         match self.parse_unsuffixed_lit() {
             Ok(lit) => {
-                return Ok(respan(lo.to(self.prev_span), ast::NestedMetaItemKind::Literal(lit)))
+                return Ok(ast::NestedMetaItem::Literal(lit))
             }
             Err(ref mut err) => self.diagnostic().cancel(err)
         }
 
         match self.parse_meta_item() {
             Ok(mi) => {
-                return Ok(respan(lo.to(self.prev_span), ast::NestedMetaItemKind::MetaItem(mi)))
+                return Ok(ast::NestedMetaItem::MetaItem(mi))
             }
             Err(ref mut err) => self.diagnostic().cancel(err)
         }
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs
index 01e3b29..bcd53db 100644
--- a/src/libsyntax/parse/lexer/mod.rs
+++ b/src/libsyntax/parse/lexer/mod.rs
@@ -1,7 +1,7 @@
 use crate::ast::{self, Ident};
 use crate::source_map::{SourceMap, FilePathMapping};
 use crate::parse::{token, ParseSess};
-use crate::symbol::{Symbol, keywords};
+use crate::symbol::Symbol;
 
 use errors::{Applicability, FatalError, Diagnostic, DiagnosticBuilder};
 use syntax_pos::{BytePos, CharPos, Pos, Span, NO_EXPANSION};
@@ -1249,15 +1249,11 @@
                     // FIXME: perform NFKC normalization here. (Issue #2253)
                     let ident = self.mk_ident(string);
 
-                    if is_raw_ident && (ident.is_path_segment_keyword() ||
-                                        ident.name == keywords::Underscore.name()) {
-                        self.fatal_span_(raw_start, self.pos,
-                            &format!("`r#{}` is not currently supported.", ident.name)
-                        ).raise();
-                    }
-
                     if is_raw_ident {
                         let span = self.mk_sp(raw_start, self.pos);
+                        if !ident.can_be_raw() {
+                            self.err_span(span, &format!("`{}` cannot be a raw identifier", ident));
+                        }
                         self.sess.raw_identifier_spans.borrow_mut().push(span);
                     }
 
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index fe31311..7a4a687 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -895,9 +895,7 @@
                                            &format!("expected identifier, found {}",
                                                     self.this_token_descr()));
         if let token::Ident(ident, false) = &self.token {
-            if ident.is_reserved() && !ident.is_path_segment_keyword() &&
-                ident.name != keywords::Underscore.name()
-            {
+            if ident.is_raw_guess() {
                 err.span_suggestion(
                     self.span,
                     "you can escape reserved keywords to use them as identifiers",
@@ -1526,7 +1524,7 @@
                          at_end: &mut bool,
                          mut attrs: Vec<Attribute>) -> PResult<'a, TraitItem> {
         let lo = self.span;
-
+        self.eat_bad_pub();
         let (name, node, generics) = if self.eat_keyword(keywords::Type) {
             self.parse_trait_item_assoc_ty()?
         } else if self.is_const_item() {
@@ -2335,7 +2333,7 @@
         let meta_ident = match self.token {
             token::Interpolated(ref nt) => match **nt {
                 token::NtMeta(ref meta) => match meta.node {
-                    ast::MetaItemKind::Word => Some(meta.ident.clone()),
+                    ast::MetaItemKind::Word => Some(meta.path.clone()),
                     _ => None,
                 },
                 _ => None,
@@ -5116,12 +5114,8 @@
 
                 let ident = self.parse_ident()?;
                 let (delim, tokens) = self.expect_delimited_token_tree()?;
-                if delim != MacDelimiter::Brace {
-                    if !self.eat(&token::Semi) {
-                        let msg = "macros that expand to items must either \
-                                   be surrounded with braces or followed by a semicolon";
-                        self.span_err(self.prev_span, msg);
-                    }
+                if delim != MacDelimiter::Brace && !self.eat(&token::Semi) {
+                    self.report_invalid_macro_expansion_item();
                 }
 
                 (ident, ast::MacroDef { tokens: tokens, legacy: true })
@@ -5264,13 +5258,8 @@
                 // if it has a special ident, it's definitely an item
                 //
                 // Require a semicolon or braces.
-                if style != MacStmtStyle::Braces {
-                    if !self.eat(&token::Semi) {
-                        self.span_err(self.prev_span,
-                                      "macros that expand to items must \
-                                       either be surrounded with braces or \
-                                       followed by a semicolon");
-                    }
+                if style != MacStmtStyle::Braces && !self.eat(&token::Semi) {
+                    self.report_invalid_macro_expansion_item();
                 }
                 let span = lo.to(hi);
                 Stmt {
@@ -6743,7 +6732,15 @@
         };
 
         // Parse both types and traits as a type, then reinterpret if necessary.
-        let ty_first = self.parse_ty()?;
+        let err_path = |span| ast::Path::from_ident(Ident::new(keywords::Invalid.name(), span));
+        let ty_first = if self.token.is_keyword(keywords::For) &&
+                          self.look_ahead(1, |t| t != &token::Lt) {
+            let span = self.prev_span.between(self.span);
+            self.struct_span_err(span, "missing trait in a trait impl").emit();
+            P(Ty { node: TyKind::Path(None, err_path(span)), span, id: ast::DUMMY_NODE_ID })
+        } else {
+            self.parse_ty()?
+        };
 
         // If `for` is missing we try to recover.
         let has_for = self.eat_keyword(keywords::For);
@@ -6752,7 +6749,7 @@
         let ty_second = if self.token == token::DotDot {
             // We need to report this error after `cfg` expansion for compatibility reasons
             self.bump(); // `..`, do not add it to expected tokens
-            Some(P(Ty { node: TyKind::Err, span: self.prev_span, id: ast::DUMMY_NODE_ID }))
+            Some(DummyResult::raw_ty(self.prev_span, true))
         } else if has_for || self.token.can_begin_type() {
             Some(self.parse_ty()?)
         } else {
@@ -6782,7 +6779,7 @@
                     TyKind::Path(None, path) => path,
                     _ => {
                         self.span_err(ty_first.span, "expected a trait, found type");
-                        ast::Path::from_ident(Ident::new(keywords::Invalid.name(), ty_first.span))
+                        err_path(ty_first.span)
                     }
                 };
                 let trait_ref = TraitRef { path, ref_id: ty_first.id };
@@ -7691,6 +7688,7 @@
 
             let struct_def;
             let mut disr_expr = None;
+            self.eat_bad_pub();
             let ident = self.parse_ident()?;
             if self.check(&token::OpenDelim(token::Brace)) {
                 // Parse a struct variant.
@@ -7722,11 +7720,25 @@
             };
             variants.push(respan(vlo.to(self.prev_span), vr));
 
-            if !self.eat(&token::Comma) { break; }
+            if !self.eat(&token::Comma) {
+                if self.token.is_ident() && !self.token.is_reserved_ident() {
+                    let sp = self.sess.source_map().next_point(self.prev_span);
+                    let mut err = self.struct_span_err(sp, "missing comma");
+                    err.span_suggestion_short(
+                        sp,
+                        "missing comma",
+                        ",".to_owned(),
+                        Applicability::MaybeIncorrect,
+                    );
+                    err.emit();
+                } else {
+                    break;
+                }
+            }
         }
         self.expect(&token::CloseDelim(token::Brace))?;
         if !any_disr.is_empty() && !all_nullary {
-            let mut err =self.struct_span_err(
+            let mut err = self.struct_span_err(
                 any_disr.clone(),
                 "discriminator values can only be used with a field-less enum",
             );
@@ -8360,13 +8372,8 @@
             };
             // eat a matched-delimiter token tree:
             let (delim, tts) = self.expect_delimited_token_tree()?;
-            if delim != MacDelimiter::Brace {
-                if !self.eat(&token::Semi) {
-                    self.span_err(self.prev_span,
-                                  "macros that expand to items must either \
-                                   be surrounded with braces or followed by \
-                                   a semicolon");
-                }
+            if delim != MacDelimiter::Brace && !self.eat(&token::Semi) {
+                self.report_invalid_macro_expansion_item();
             }
 
             let hi = self.prev_span;
@@ -8597,6 +8604,40 @@
             }
         }
     }
+
+    fn report_invalid_macro_expansion_item(&self) {
+        self.struct_span_err(
+            self.prev_span,
+            "macros that expand to items must be delimited with braces or followed by a semicolon",
+        ).multipart_suggestion(
+            "change the delimiters to curly braces",
+            vec![
+                (self.prev_span.with_hi(self.prev_span.lo() + BytePos(1)), String::from(" {")),
+                (self.prev_span.with_lo(self.prev_span.hi() - BytePos(1)), '}'.to_string()),
+            ],
+            Applicability::MaybeIncorrect,
+        ).span_suggestion(
+            self.sess.source_map.next_point(self.prev_span),
+            "add a semicolon",
+            ';'.to_string(),
+            Applicability::MaybeIncorrect,
+        ).emit();
+    }
+
+    /// Recover from `pub` keyword in places where it seems _reasonable_ but isn't valid.
+    fn eat_bad_pub(&mut self) {
+        if self.token.is_keyword(keywords::Pub) {
+            match self.parse_visibility(false) {
+                Ok(vis) => {
+                    let mut err = self.diagnostic()
+                        .struct_span_err(vis.span, "unnecessary visibility qualifier");
+                    err.span_label(vis.span, "`pub` not permitted here");
+                    err.emit();
+                }
+                Err(mut err) => err.emit(),
+            }
+        }
+    }
 }
 
 pub fn emit_unclosed_delims(unclosed_delims: &mut Vec<UnmatchedBrace>, handler: &errors::Handler) {
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 49e3fad..07df14d 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -768,11 +768,11 @@
     }
 
     fn print_meta_list_item(&mut self, item: &ast::NestedMetaItem) -> io::Result<()> {
-        match item.node {
-            ast::NestedMetaItemKind::MetaItem(ref mi) => {
+        match item {
+            ast::NestedMetaItem::MetaItem(ref mi) => {
                 self.print_meta_item(mi)
             },
-            ast::NestedMetaItemKind::Literal(ref lit) => {
+            ast::NestedMetaItem::Literal(ref lit) => {
                 self.print_literal(lit)
             }
         }
@@ -781,15 +781,15 @@
     fn print_meta_item(&mut self, item: &ast::MetaItem) -> io::Result<()> {
         self.ibox(INDENT_UNIT)?;
         match item.node {
-            ast::MetaItemKind::Word => self.print_attribute_path(&item.ident)?,
+            ast::MetaItemKind::Word => self.print_attribute_path(&item.path)?,
             ast::MetaItemKind::NameValue(ref value) => {
-                self.print_attribute_path(&item.ident)?;
+                self.print_attribute_path(&item.path)?;
                 self.writer().space()?;
                 self.word_space("=")?;
                 self.print_literal(value)?;
             }
             ast::MetaItemKind::List(ref items) => {
-                self.print_attribute_path(&item.ident)?;
+                self.print_attribute_path(&item.path)?;
                 self.popen()?;
                 self.commasep(Consistent,
                               &items[..],
@@ -1263,13 +1263,13 @@
                 self.s.word(";")?;
                 self.end()?; // end the outer cbox
             }
-            ast::ItemKind::Fn(ref decl, header, ref typarams, ref body) => {
+            ast::ItemKind::Fn(ref decl, header, ref param_names, ref body) => {
                 self.head("")?;
                 self.print_fn(
                     decl,
                     header,
                     Some(item.ident),
-                    typarams,
+                    param_names,
                     &item.vis
                 )?;
                 self.s.word(" ")?;
diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs
index 56290fa..6f03c58 100644
--- a/src/libsyntax/test.rs
+++ b/src/libsyntax/test.rs
@@ -435,9 +435,12 @@
     let test_attr = attr::find_by_name(&krate.attrs, "test_runner")?;
     test_attr.meta_item_list().map(|meta_list| {
         if meta_list.len() != 1 {
-            sd.span_fatal(test_attr.span(),
+            sd.span_fatal(test_attr.span,
                 "#![test_runner(..)] accepts exactly 1 argument").raise()
         }
-        meta_list[0].word().as_ref().unwrap().ident.clone()
+        match meta_list[0].meta_item() {
+            Some(meta_item) if meta_item.is_word() => meta_item.path.clone(),
+            _ => sd.span_fatal(test_attr.span, "`test_runner` argument must be a path").raise()
+        }
     })
 }
diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs
index 4ce308d..80a7bde 100644
--- a/src/libsyntax/tokenstream.rs
+++ b/src/libsyntax/tokenstream.rs
@@ -178,9 +178,11 @@
             while let Some((pos, ts)) = iter.next() {
                 if let Some((_, next)) = iter.peek() {
                     let sp = match (&ts, &next) {
-                        ((TokenTree::Token(_, token::Token::Comma), NonJoint), _) |
-                        (_, (TokenTree::Token(_, token::Token::Comma), NonJoint)) => continue,
-                        ((TokenTree::Token(sp, _), NonJoint), _) => *sp,
+                        (_, (TokenTree::Token(_, token::Token::Comma), _)) => continue,
+                        ((TokenTree::Token(sp, token_left), NonJoint),
+                         (TokenTree::Token(_, token_right), _))
+                        if (token_left.is_ident() || token_left.is_lit()) &&
+                            (token_right.is_ident() || token_right.is_lit()) => *sp,
                         ((TokenTree::Delimited(sp, ..), NonJoint), _) => sp.entire(),
                         _ => continue,
                     };
diff --git a/src/libsyntax_ext/deriving/custom.rs b/src/libsyntax_ext/deriving/custom.rs
index cfc3c93..e731107 100644
--- a/src/libsyntax_ext/deriving/custom.rs
+++ b/src/libsyntax_ext/deriving/custom.rs
@@ -17,9 +17,11 @@
 
 impl<'a> Visitor<'a> for MarkAttrs<'a> {
     fn visit_attribute(&mut self, attr: &Attribute) {
-        if self.0.contains(&attr.name()) {
-            mark_used(attr);
-            mark_known(attr);
+        if let Some(ident) = attr.ident() {
+            if self.0.contains(&ident.name) {
+                mark_used(attr);
+                mark_known(attr);
+            }
         }
     }
 
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index b8f96c5..2bb98c1 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -463,12 +463,9 @@
                 let mut attrs = newitem.attrs.clone();
                 attrs.extend(item.attrs
                     .iter()
-                    .filter(|a| {
-                        match &*a.name().as_str() {
-                            "allow" | "warn" | "deny" | "forbid" | "stable" | "unstable" => true,
-                            _ => false,
-                        }
-                    })
+                    .filter(|a| a.ident_str().map_or(false, |name| {
+                        ["allow", "warn", "deny", "forbid", "stable", "unstable"].contains(&name)
+                    }))
                     .cloned());
                 push(Annotatable::Item(P(ast::Item { attrs: attrs, ..(*newitem).clone() })))
             }
diff --git a/src/libsyntax_ext/proc_macro_decls.rs b/src/libsyntax_ext/proc_macro_decls.rs
index d8f8dec..d5f37af 100644
--- a/src/libsyntax_ext/proc_macro_decls.rs
+++ b/src/libsyntax_ext/proc_macro_decls.rs
@@ -109,52 +109,67 @@
             None => return,
         };
         if list.len() != 1 && list.len() != 2 {
-            self.handler.span_err(attr.span(),
+            self.handler.span_err(attr.span,
                                   "attribute must have either one or two arguments");
             return
         }
-        let trait_attr = &list[0];
-        let attributes_attr = list.get(1);
-        let trait_name = match trait_attr.name() {
-            Some(name) => name,
+        let trait_attr = match list[0].meta_item() {
+            Some(meta_item) => meta_item,
             _ => {
-                self.handler.span_err(trait_attr.span(), "not a meta item");
+                self.handler.span_err(list[0].span(), "not a meta item");
                 return
             }
         };
-        if !trait_attr.is_word() {
-            self.handler.span_err(trait_attr.span(), "must only be one word");
+        let trait_ident = match trait_attr.ident() {
+            Some(trait_ident) if trait_attr.is_word() => trait_ident,
+            _ => {
+                self.handler.span_err(trait_attr.span, "must only be one word");
+                return
+            }
+        };
+
+        if !trait_ident.can_be_raw() {
+            self.handler.span_err(trait_attr.span,
+                                  &format!("`{}` cannot be a name of derive macro", trait_ident));
+        }
+        if deriving::is_builtin_trait(trait_ident.name) {
+            self.handler.span_err(trait_attr.span,
+                                  "cannot override a built-in derive macro");
         }
 
-        if deriving::is_builtin_trait(trait_name) {
-            self.handler.span_err(trait_attr.span(),
-                                  "cannot override a built-in #[derive] mode");
-        }
-
+        let attributes_attr = list.get(1);
         let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr {
             if !attr.check_name("attributes") {
                 self.handler.span_err(attr.span(), "second argument must be `attributes`")
             }
             attr.meta_item_list().unwrap_or_else(|| {
                 self.handler.span_err(attr.span(),
-                                      "attribute must be of form: \
-                                       `attributes(foo, bar)`");
+                                      "attribute must be of form: `attributes(foo, bar)`");
                 &[]
             }).into_iter().filter_map(|attr| {
-                let name = match attr.name() {
-                    Some(name) => name,
+                let attr = match attr.meta_item() {
+                    Some(meta_item) => meta_item,
                     _ => {
                         self.handler.span_err(attr.span(), "not a meta item");
                         return None;
-                    },
+                    }
                 };
 
-                if !attr.is_word() {
-                    self.handler.span_err(attr.span(), "must only be one word");
-                    return None;
+                let ident = match attr.ident() {
+                    Some(ident) if attr.is_word() => ident,
+                    _ => {
+                        self.handler.span_err(attr.span, "must only be one word");
+                        return None;
+                    }
+                };
+                if !ident.can_be_raw() {
+                    self.handler.span_err(
+                        attr.span,
+                        &format!("`{}` cannot be a name of derive helper attribute", ident),
+                    );
                 }
 
-                Some(name)
+                Some(ident.name)
             }).collect()
         } else {
             Vec::new()
@@ -163,7 +178,7 @@
         if self.in_root && item.vis.node.is_pub() {
             self.derives.push(ProcMacroDerive {
                 span: item.span,
-                trait_name,
+                trait_name: trait_ident.name,
                 function_name: item.ident,
                 attrs: proc_attrs,
             });
@@ -247,8 +262,8 @@
                                 to the same function", attr.path, prev_attr.path)
                     };
 
-                    self.handler.struct_span_err(attr.span(), &msg)
-                        .span_note(prev_attr.span(), "Previous attribute here")
+                    self.handler.struct_span_err(attr.span, &msg)
+                        .span_note(prev_attr.span, "Previous attribute here")
                         .emit();
 
                     return;
@@ -273,7 +288,7 @@
             let msg = format!("the `#[{}]` attribute may only be used on bare functions",
                               attr.path);
 
-            self.handler.span_err(attr.span(), &msg);
+            self.handler.span_err(attr.span, &msg);
             return;
         }
 
@@ -285,7 +300,7 @@
             let msg = format!("the `#[{}]` attribute is only usable with crates of the \
                               `proc-macro` crate type", attr.path);
 
-            self.handler.span_err(attr.span(), &msg);
+            self.handler.span_err(attr.span, &msg);
             return;
         }
 
diff --git a/src/libsyntax_ext/proc_macro_server.rs b/src/libsyntax_ext/proc_macro_server.rs
index a7ac95b..c0a9dfe 100644
--- a/src/libsyntax_ext/proc_macro_server.rs
+++ b/src/libsyntax_ext/proc_macro_server.rs
@@ -340,12 +340,8 @@
         if !Self::is_valid(string) {
             panic!("`{:?}` is not a valid identifier", string)
         }
-        if is_raw {
-            let normalized_sym = Symbol::intern(string);
-            if normalized_sym == keywords::Underscore.name() ||
-               ast::Ident::with_empty_ctxt(normalized_sym).is_path_segment_keyword() {
-                panic!("`{:?}` is not a valid raw identifier", string)
-            }
+        if is_raw && !ast::Ident::from_str(string).can_be_raw() {
+            panic!("`{}` cannot be a raw identifier", string);
         }
         Ident { sym, is_raw, span }
     }
diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs
index f4b625f..0dbcb7c 100644
--- a/src/libsyntax_ext/test.rs
+++ b/src/libsyntax_ext/test.rs
@@ -227,7 +227,7 @@
                         .and_then(|mi| mi.value_str());
                     if list.len() != 1 || msg.is_none() {
                         sd.struct_span_warn(
-                            attr.span(),
+                            attr.span,
                             "argument must be of the form: \
                              `expected = \"error message\"`"
                         ).note("Errors in this attribute were erroneously \
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index c5301f9..e8d215a 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -484,11 +484,16 @@
         self.name == keywords::DollarCrate.name()
     }
 
-    // We see this identifier in a normal identifier position, like variable name or a type.
-    // How was it written originally? Did it use the raw form? Let's try to guess.
-    pub fn is_raw_guess(self) -> bool {
+    /// This identifier can be a raw identifier.
+    pub fn can_be_raw(self) -> bool {
         self.name != keywords::Invalid.name() && self.name != keywords::Underscore.name() &&
-        self.is_reserved() && !self.is_path_segment_keyword()
+        !self.is_path_segment_keyword()
+    }
+
+    /// We see this identifier in a normal identifier position, like variable name or a type.
+    /// How was it written originally? Did it use the raw form? Let's try to guess.
+    pub fn is_raw_guess(self) -> bool {
+        self.can_be_raw() && self.is_reserved()
     }
 }
 
diff --git a/src/libterm/Cargo.toml b/src/libterm/Cargo.toml
deleted file mode 100644
index 4eba9a9..0000000
--- a/src/libterm/Cargo.toml
+++ /dev/null
@@ -1,10 +0,0 @@
-[package]
-authors = ["The Rust Project Developers"]
-name = "term"
-version = "0.0.0"
-edition = "2018"
-
-[lib]
-name = "term"
-path = "lib.rs"
-crate-type = ["dylib", "rlib"]
diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs
deleted file mode 100644
index 711716d..0000000
--- a/src/libterm/lib.rs
+++ /dev/null
@@ -1,201 +0,0 @@
-//! Terminal formatting library.
-//!
-//! This crate provides the `Terminal` trait, which abstracts over an [ANSI
-//! Terminal][ansi] to provide color printing, among other things. There are two
-//! implementations, the `TerminfoTerminal`, which uses control characters from
-//! a [terminfo][ti] database, and `WinConsole`, which uses the [Win32 Console
-//! API][win].
-//!
-//! # Examples
-//!
-//! ```no_run
-//! # #![feature(rustc_private)]
-//! extern crate term;
-//! use std::io::prelude::*;
-//!
-//! fn main() {
-//!     let mut t = term::stdout().unwrap();
-//!
-//!     t.fg(term::color::GREEN).unwrap();
-//!     write!(t, "hello, ").unwrap();
-//!
-//!     t.fg(term::color::RED).unwrap();
-//!     writeln!(t, "world!").unwrap();
-//!
-//!     assert!(t.reset().unwrap());
-//! }
-//! ```
-//!
-//! [ansi]: https://en.wikipedia.org/wiki/ANSI_escape_code
-//! [win]: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682010%28v=vs.85%29.aspx
-//! [ti]: https://en.wikipedia.org/wiki/Terminfo
-
-#![doc(html_root_url = "https://doc.rust-lang.org/nightly/",
-       html_playground_url = "https://play.rust-lang.org/",
-       test(attr(deny(warnings))))]
-#![deny(missing_docs)]
-
-#![deny(rust_2018_idioms)]
-
-#![cfg_attr(windows, feature(libc))]
-// Handle rustfmt skips
-#![feature(custom_attribute)]
-#![allow(unused_attributes)]
-
-use std::io::prelude::*;
-use std::io::{self, Stdout, Stderr};
-
-pub use terminfo::TerminfoTerminal;
-#[cfg(windows)]
-pub use win::WinConsole;
-
-pub mod terminfo;
-
-#[cfg(windows)]
-mod win;
-
-/// Alias for stdout terminals.
-pub type StdoutTerminal = dyn Terminal<Output = Stdout> + Send;
-/// Alias for stderr terminals.
-pub type StderrTerminal = dyn Terminal<Output = Stderr> + Send;
-
-#[cfg(not(windows))]
-/// Returns a Terminal wrapping stdout, or None if a terminal couldn't be
-/// opened.
-pub fn stdout() -> Option<Box<StdoutTerminal>> {
-    TerminfoTerminal::new(io::stdout()).map(|t| Box::new(t) as Box<StdoutTerminal>)
-}
-
-#[cfg(windows)]
-/// Returns a Terminal wrapping stdout, or None if a terminal couldn't be
-/// opened.
-pub fn stdout() -> Option<Box<StdoutTerminal>> {
-    TerminfoTerminal::new(io::stdout())
-        .map(|t| Box::new(t) as Box<StdoutTerminal>)
-        .or_else(|| WinConsole::new(io::stdout()).ok().map(|t| Box::new(t) as Box<StdoutTerminal>))
-}
-
-#[cfg(not(windows))]
-/// Returns a Terminal wrapping stderr, or None if a terminal couldn't be
-/// opened.
-pub fn stderr() -> Option<Box<StderrTerminal>> {
-    TerminfoTerminal::new(io::stderr()).map(|t| Box::new(t) as Box<StderrTerminal>)
-}
-
-#[cfg(windows)]
-/// Returns a Terminal wrapping stderr, or None if a terminal couldn't be
-/// opened.
-pub fn stderr() -> Option<Box<StderrTerminal>> {
-    TerminfoTerminal::new(io::stderr())
-        .map(|t| Box::new(t) as Box<StderrTerminal>)
-        .or_else(|| WinConsole::new(io::stderr()).ok().map(|t| Box::new(t) as Box<StderrTerminal>))
-}
-
-
-/// Terminal color definitions
-#[allow(missing_docs)]
-pub mod color {
-    /// Number for a terminal color
-    pub type Color = u16;
-
-    pub const BLACK: Color = 0;
-    pub const RED: Color = 1;
-    pub const GREEN: Color = 2;
-    pub const YELLOW: Color = 3;
-    pub const BLUE: Color = 4;
-    pub const MAGENTA: Color = 5;
-    pub const CYAN: Color = 6;
-    pub const WHITE: Color = 7;
-
-    pub const BRIGHT_BLACK: Color = 8;
-    pub const BRIGHT_RED: Color = 9;
-    pub const BRIGHT_GREEN: Color = 10;
-    pub const BRIGHT_YELLOW: Color = 11;
-    pub const BRIGHT_BLUE: Color = 12;
-    pub const BRIGHT_MAGENTA: Color = 13;
-    pub const BRIGHT_CYAN: Color = 14;
-    pub const BRIGHT_WHITE: Color = 15;
-}
-
-/// Terminal attributes for use with term.attr().
-///
-/// Most attributes can only be turned on and must be turned off with term.reset().
-/// The ones that can be turned off explicitly take a boolean value.
-/// Color is also represented as an attribute for convenience.
-#[derive(Debug, PartialEq, Eq, Copy, Clone)]
-pub enum Attr {
-    /// Bold (or possibly bright) mode
-    Bold,
-    /// Dim mode, also called faint or half-bright. Often not supported
-    Dim,
-    /// Italics mode. Often not supported
-    Italic(bool),
-    /// Underline mode
-    Underline(bool),
-    /// Blink mode
-    Blink,
-    /// Standout mode. Often implemented as Reverse, sometimes coupled with Bold
-    Standout(bool),
-    /// Reverse mode, inverts the foreground and background colors
-    Reverse,
-    /// Secure mode, also called invis mode. Hides the printed text
-    Secure,
-    /// Convenience attribute to set the foreground color
-    ForegroundColor(color::Color),
-    /// Convenience attribute to set the background color
-    BackgroundColor(color::Color),
-}
-
-/// A terminal with similar capabilities to an ANSI Terminal
-/// (foreground/background colors etc).
-pub trait Terminal: Write {
-    /// The terminal's output writer type.
-    type Output: Write;
-
-    /// Sets the foreground color to the given color.
-    ///
-    /// If the color is a bright color, but the terminal only supports 8 colors,
-    /// the corresponding normal color will be used instead.
-    ///
-    /// Returns `Ok(true)` if the color was set, `Ok(false)` otherwise, and `Err(e)`
-    /// if there was an I/O error.
-    fn fg(&mut self, color: color::Color) -> io::Result<bool>;
-
-    /// Sets the background color to the given color.
-    ///
-    /// If the color is a bright color, but the terminal only supports 8 colors,
-    /// the corresponding normal color will be used instead.
-    ///
-    /// Returns `Ok(true)` if the color was set, `Ok(false)` otherwise, and `Err(e)`
-    /// if there was an I/O error.
-    fn bg(&mut self, color: color::Color) -> io::Result<bool>;
-
-    /// Sets the given terminal attribute, if supported. Returns `Ok(true)`
-    /// if the attribute was supported, `Ok(false)` otherwise, and `Err(e)` if
-    /// there was an I/O error.
-    fn attr(&mut self, attr: Attr) -> io::Result<bool>;
-
-    /// Returns `true` if the given terminal attribute is supported.
-    fn supports_attr(&self, attr: Attr) -> bool;
-
-    /// Resets all terminal attributes and colors to their defaults.
-    ///
-    /// Returns `Ok(true)` if the terminal was reset, `Ok(false)` otherwise, and `Err(e)` if there
-    /// was an I/O error.
-    ///
-    /// *Note: This does not flush.*
-    ///
-    /// That means the reset command may get buffered so, if you aren't planning on doing anything
-    /// else that might flush stdout's buffer (e.g., writing a line of text), you should flush after
-    /// calling reset.
-    fn reset(&mut self) -> io::Result<bool>;
-
-    /// Gets an immutable reference to the stream inside
-    fn get_ref(&self) -> &Self::Output;
-
-    /// Gets a mutable reference to the stream inside
-    fn get_mut(&mut self) -> &mut Self::Output;
-
-    /// Returns the contained stream, destroying the `Terminal`
-    fn into_inner(self) -> Self::Output where Self: Sized;
-}
diff --git a/src/libterm/terminfo/mod.rs b/src/libterm/terminfo/mod.rs
deleted file mode 100644
index be90195..0000000
--- a/src/libterm/terminfo/mod.rs
+++ /dev/null
@@ -1,265 +0,0 @@
-//! Terminfo database interface.
-
-use std::collections::HashMap;
-use std::env;
-use std::error;
-use std::fmt;
-use std::fs::File;
-use std::io::{self, prelude::*, BufReader};
-use std::path::Path;
-
-use crate::Attr;
-use crate::color;
-use crate::Terminal;
-
-use searcher::get_dbpath_for_term;
-use parser::compiled::{parse, msys_terminfo};
-use parm::{expand, Variables, Param};
-
-/// A parsed terminfo database entry.
-#[derive(Debug)]
-pub struct TermInfo {
-    /// Names for the terminal
-    pub names: Vec<String>,
-    /// Map of capability name to boolean value
-    pub bools: HashMap<String, bool>,
-    /// Map of capability name to numeric value
-    pub numbers: HashMap<String, u16>,
-    /// Map of capability name to raw (unexpanded) string
-    pub strings: HashMap<String, Vec<u8>>,
-}
-
-/// A terminfo creation error.
-#[derive(Debug)]
-pub enum Error {
-    /// TermUnset Indicates that the environment doesn't include enough information to find
-    /// the terminfo entry.
-    TermUnset,
-    /// MalformedTerminfo indicates that parsing the terminfo entry failed.
-    MalformedTerminfo(String),
-    /// io::Error forwards any io::Errors encountered when finding or reading the terminfo entry.
-    IoError(io::Error),
-}
-
-impl error::Error for Error {
-    fn description(&self) -> &str {
-        "failed to create TermInfo"
-    }
-
-    fn cause(&self) -> Option<&dyn error::Error> {
-        use Error::*;
-        match *self {
-            IoError(ref e) => Some(e),
-            _ => None,
-        }
-    }
-}
-
-impl fmt::Display for Error {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use Error::*;
-        match *self {
-            TermUnset => Ok(()),
-            MalformedTerminfo(ref e) => e.fmt(f),
-            IoError(ref e) => e.fmt(f),
-        }
-    }
-}
-
-impl TermInfo {
-    /// Creates a TermInfo based on current environment.
-    pub fn from_env() -> Result<TermInfo, Error> {
-        let term = match env::var("TERM") {
-            Ok(name) => TermInfo::from_name(&name),
-            Err(..) => return Err(Error::TermUnset),
-        };
-
-        if term.is_err() && env::var("MSYSCON").ok().map_or(false, |s| "mintty.exe" == s) {
-            // msys terminal
-            Ok(msys_terminfo())
-        } else {
-            term
-        }
-    }
-
-    /// Creates a TermInfo for the named terminal.
-    pub fn from_name(name: &str) -> Result<TermInfo, Error> {
-        get_dbpath_for_term(name)
-            .ok_or_else(|| {
-                Error::IoError(io::Error::new(io::ErrorKind::NotFound, "terminfo file not found"))
-            })
-            .and_then(|p| TermInfo::from_path(&(*p)))
-    }
-
-    /// Parse the given TermInfo.
-    pub fn from_path<P: AsRef<Path>>(path: P) -> Result<TermInfo, Error> {
-        Self::_from_path(path.as_ref())
-    }
-    // Keep the metadata small
-    fn _from_path(path: &Path) -> Result<TermInfo, Error> {
-        let file = File::open(path).map_err(Error::IoError)?;
-        let mut reader = BufReader::new(file);
-        parse(&mut reader, false).map_err(Error::MalformedTerminfo)
-    }
-}
-
-pub mod searcher;
-
-/// TermInfo format parsing.
-pub mod parser {
-    //! ncurses-compatible compiled terminfo format parsing (term(5))
-    pub mod compiled;
-}
-pub mod parm;
-
-
-fn cap_for_attr(attr: Attr) -> &'static str {
-    match attr {
-        Attr::Bold => "bold",
-        Attr::Dim => "dim",
-        Attr::Italic(true) => "sitm",
-        Attr::Italic(false) => "ritm",
-        Attr::Underline(true) => "smul",
-        Attr::Underline(false) => "rmul",
-        Attr::Blink => "blink",
-        Attr::Standout(true) => "smso",
-        Attr::Standout(false) => "rmso",
-        Attr::Reverse => "rev",
-        Attr::Secure => "invis",
-        Attr::ForegroundColor(_) => "setaf",
-        Attr::BackgroundColor(_) => "setab",
-    }
-}
-
-/// A Terminal that knows how many colors it supports, with a reference to its
-/// parsed Terminfo database record.
-pub struct TerminfoTerminal<T> {
-    num_colors: u16,
-    out: T,
-    ti: TermInfo,
-}
-
-impl<T: Write + Send> Terminal for TerminfoTerminal<T> {
-    type Output = T;
-    fn fg(&mut self, color: color::Color) -> io::Result<bool> {
-        let color = self.dim_if_necessary(color);
-        if self.num_colors > color {
-            return self.apply_cap("setaf", &[Param::Number(color as i32)]);
-        }
-        Ok(false)
-    }
-
-    fn bg(&mut self, color: color::Color) -> io::Result<bool> {
-        let color = self.dim_if_necessary(color);
-        if self.num_colors > color {
-            return self.apply_cap("setab", &[Param::Number(color as i32)]);
-        }
-        Ok(false)
-    }
-
-    fn attr(&mut self, attr: Attr) -> io::Result<bool> {
-        match attr {
-            Attr::ForegroundColor(c) => self.fg(c),
-            Attr::BackgroundColor(c) => self.bg(c),
-            _ => self.apply_cap(cap_for_attr(attr), &[]),
-        }
-    }
-
-    fn supports_attr(&self, attr: Attr) -> bool {
-        match attr {
-            Attr::ForegroundColor(_) | Attr::BackgroundColor(_) => self.num_colors > 0,
-            _ => {
-                let cap = cap_for_attr(attr);
-                self.ti.strings.get(cap).is_some()
-            }
-        }
-    }
-
-    fn reset(&mut self) -> io::Result<bool> {
-        // are there any terminals that have color/attrs and not sgr0?
-        // Try falling back to sgr, then op
-        let cmd = match ["sgr0", "sgr", "op"]
-                            .iter()
-                            .filter_map(|cap| self.ti.strings.get(*cap))
-                            .next() {
-            Some(op) => {
-                match expand(&op, &[], &mut Variables::new()) {
-                    Ok(cmd) => cmd,
-                    Err(e) => return Err(io::Error::new(io::ErrorKind::InvalidData, e)),
-                }
-            }
-            None => return Ok(false),
-        };
-        self.out.write_all(&cmd).and(Ok(true))
-    }
-
-    fn get_ref(&self) -> &T {
-        &self.out
-    }
-
-    fn get_mut(&mut self) -> &mut T {
-        &mut self.out
-    }
-
-    fn into_inner(self) -> T
-        where Self: Sized
-    {
-        self.out
-    }
-}
-
-impl<T: Write + Send> TerminfoTerminal<T> {
-    /// Creates a new TerminfoTerminal with the given TermInfo and Write.
-    pub fn new_with_terminfo(out: T, terminfo: TermInfo) -> TerminfoTerminal<T> {
-        let nc = if terminfo.strings.contains_key("setaf") &&
-                    terminfo.strings.contains_key("setab") {
-            terminfo.numbers.get("colors").map_or(0, |&n| n)
-        } else {
-            0
-        };
-
-        TerminfoTerminal {
-            out,
-            ti: terminfo,
-            num_colors: nc,
-        }
-    }
-
-    /// Creates a new TerminfoTerminal for the current environment with the given Write.
-    ///
-    /// Returns `None` when the terminfo cannot be found or parsed.
-    pub fn new(out: T) -> Option<TerminfoTerminal<T>> {
-        TermInfo::from_env().map(move |ti| TerminfoTerminal::new_with_terminfo(out, ti)).ok()
-    }
-
-    fn dim_if_necessary(&self, color: color::Color) -> color::Color {
-        if color >= self.num_colors && color >= 8 && color < 16 {
-            color - 8
-        } else {
-            color
-        }
-    }
-
-    fn apply_cap(&mut self, cmd: &str, params: &[Param]) -> io::Result<bool> {
-        match self.ti.strings.get(cmd) {
-            Some(cmd) => {
-                match expand(&cmd, params, &mut Variables::new()) {
-                    Ok(s) => self.out.write_all(&s).and(Ok(true)),
-                    Err(e) => Err(io::Error::new(io::ErrorKind::InvalidData, e)),
-                }
-            }
-            None => Ok(false),
-        }
-    }
-}
-
-
-impl<T: Write> Write for TerminfoTerminal<T> {
-    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        self.out.write(buf)
-    }
-
-    fn flush(&mut self) -> io::Result<()> {
-        self.out.flush()
-    }
-}
diff --git a/src/libterm/terminfo/parm.rs b/src/libterm/terminfo/parm.rs
deleted file mode 100644
index 28229bd..0000000
--- a/src/libterm/terminfo/parm.rs
+++ /dev/null
@@ -1,669 +0,0 @@
-//! Parameterized string expansion
-
-use self::Param::*;
-use self::States::*;
-
-use std::iter::repeat;
-
-#[derive(Clone, Copy, PartialEq)]
-enum States {
-    Nothing,
-    Percent,
-    SetVar,
-    GetVar,
-    PushParam,
-    CharConstant,
-    CharClose,
-    IntConstant(i32),
-    FormatPattern(Flags, FormatState),
-    SeekIfElse(usize),
-    SeekIfElsePercent(usize),
-    SeekIfEnd(usize),
-    SeekIfEndPercent(usize),
-}
-
-#[derive(Copy, PartialEq, Clone)]
-enum FormatState {
-    Flags,
-    Width,
-    Precision,
-}
-
-/// Types of parameters a capability can use
-#[allow(missing_docs)]
-#[derive(Clone)]
-pub enum Param {
-    Words(String),
-    Number(i32),
-}
-
-/// Container for static and dynamic variable arrays
-pub struct Variables {
-    /// Static variables A-Z
-    sta_va: [Param; 26],
-    /// Dynamic variables a-z
-    dyn_va: [Param; 26],
-}
-
-impl Variables {
-    /// Returns a new zero-initialized Variables
-    pub fn new() -> Variables {
-        Variables {
-            sta_va: [
-                Number(0), Number(0), Number(0), Number(0), Number(0), Number(0), Number(0),
-                Number(0), Number(0), Number(0), Number(0), Number(0), Number(0), Number(0),
-                Number(0), Number(0), Number(0), Number(0), Number(0), Number(0), Number(0),
-                Number(0), Number(0), Number(0), Number(0), Number(0)
-            ],
-            dyn_va: [
-                Number(0), Number(0), Number(0), Number(0), Number(0), Number(0), Number(0),
-                Number(0), Number(0), Number(0), Number(0), Number(0), Number(0), Number(0),
-                Number(0), Number(0), Number(0), Number(0), Number(0), Number(0), Number(0),
-                Number(0), Number(0), Number(0), Number(0), Number(0)
-            ],
-        }
-    }
-}
-
-/// Expand a parameterized capability
-///
-/// # Arguments
-/// * `cap`    - string to expand
-/// * `params` - vector of params for %p1 etc
-/// * `vars`   - Variables struct for %Pa etc
-///
-/// To be compatible with ncurses, `vars` should be the same between calls to `expand` for
-/// multiple capabilities for the same terminal.
-pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables) -> Result<Vec<u8>, String> {
-    let mut state = Nothing;
-
-    // expanded cap will only rarely be larger than the cap itself
-    let mut output = Vec::with_capacity(cap.len());
-
-    let mut stack: Vec<Param> = Vec::new();
-
-    // Copy parameters into a local vector for mutability
-    let mut mparams = [Number(0), Number(0), Number(0), Number(0), Number(0), Number(0),
-                       Number(0), Number(0), Number(0)];
-    for (dst, src) in mparams.iter_mut().zip(params.iter()) {
-        *dst = (*src).clone();
-    }
-
-    for &c in cap.iter() {
-        let cur = c as char;
-        let mut old_state = state;
-        match state {
-            Nothing => {
-                if cur == '%' {
-                    state = Percent;
-                } else {
-                    output.push(c);
-                }
-            }
-            Percent => {
-                match cur {
-                    '%' => {
-                        output.push(c);
-                        state = Nothing
-                    }
-                    'c' => {
-                        match stack.pop() {
-                            // if c is 0, use 0200 (128) for ncurses compatibility
-                            Some(Number(0)) => output.push(128u8),
-                            // Don't check bounds. ncurses just casts and truncates.
-                            Some(Number(c)) => output.push(c as u8),
-                            Some(_) => return Err("a non-char was used with %c".to_string()),
-                            None => return Err("stack is empty".to_string()),
-                        }
-                    }
-                    'p' => state = PushParam,
-                    'P' => state = SetVar,
-                    'g' => state = GetVar,
-                    '\'' => state = CharConstant,
-                    '{' => state = IntConstant(0),
-                    'l' => {
-                        match stack.pop() {
-                            Some(Words(s)) => stack.push(Number(s.len() as i32)),
-                            Some(_) => return Err("a non-str was used with %l".to_string()),
-                            None => return Err("stack is empty".to_string()),
-                        }
-                    }
-                    '+' | '-' | '/' | '*' | '^' | '&' | '|' | 'm' => {
-                        match (stack.pop(), stack.pop()) {
-                            (Some(Number(y)), Some(Number(x))) => {
-                                stack.push(Number(match cur {
-                                    '+' => x + y,
-                                    '-' => x - y,
-                                    '*' => x * y,
-                                    '/' => x / y,
-                                    '|' => x | y,
-                                    '&' => x & y,
-                                    '^' => x ^ y,
-                                    'm' => x % y,
-                                    _ => unreachable!("All cases handled"),
-                                }))
-                            }
-                            (Some(_), Some(_)) => {
-                                return Err(format!("non-numbers on stack with {}", cur))
-                            }
-                            _ => return Err("stack is empty".to_string()),
-                        }
-                    }
-                    '=' | '>' | '<' | 'A' | 'O' => {
-                        match (stack.pop(), stack.pop()) {
-                            (Some(Number(y)), Some(Number(x))) => {
-                                stack.push(Number(if match cur {
-                                    '=' => x == y,
-                                    '<' => x < y,
-                                    '>' => x > y,
-                                    'A' => x > 0 && y > 0,
-                                    'O' => x > 0 || y > 0,
-                                    _ => unreachable!(),
-                                } {
-                                    1
-                                } else {
-                                    0
-                                }))
-                            }
-                            (Some(_), Some(_)) => {
-                                return Err(format!("non-numbers on stack with {}", cur))
-                            }
-                            _ => return Err("stack is empty".to_string()),
-                        }
-                    }
-                    '!' | '~' => {
-                        match stack.pop() {
-                            Some(Number(x)) => {
-                                stack.push(Number(match cur {
-                                    '!' if x > 0 => 0,
-                                    '!' => 1,
-                                    '~' => !x,
-                                    _ => unreachable!(),
-                                }))
-                            }
-                            Some(_) => return Err(format!("non-numbers on stack with {}", cur)),
-                            None => return Err("stack is empty".to_string()),
-                        }
-                    }
-                    'i' => {
-                        match (&mparams[0], &mparams[1]) {
-                            (&Number(x), &Number(y)) => {
-                                mparams[0] = Number(x + 1);
-                                mparams[1] = Number(y + 1);
-                            }
-                            _ => {
-                                return Err("first two params not numbers with %i".to_string())
-                            }
-                        }
-                    }
-
-                    // printf-style support for %doxXs
-                    'd' | 'o' | 'x' | 'X' | 's' => {
-                        if let Some(arg) = stack.pop() {
-                            let flags = Flags::new();
-                            let res = format(arg, FormatOp::from_char(cur), flags)?;
-                            output.extend(res.iter().cloned());
-                        } else {
-                            return Err("stack is empty".to_string());
-                        }
-                    }
-                    ':' | '#' | ' ' | '.' | '0'..='9' => {
-                        let mut flags = Flags::new();
-                        let mut fstate = FormatState::Flags;
-                        match cur {
-                            ':' => (),
-                            '#' => flags.alternate = true,
-                            ' ' => flags.space = true,
-                            '.' => fstate = FormatState::Precision,
-                            '0'..='9' => {
-                                flags.width = cur as usize - '0' as usize;
-                                fstate = FormatState::Width;
-                            }
-                            _ => unreachable!(),
-                        }
-                        state = FormatPattern(flags, fstate);
-                    }
-
-                    // conditionals
-                    '?' => (),
-                    't' => {
-                        match stack.pop() {
-                            Some(Number(0)) => state = SeekIfElse(0),
-                            Some(Number(_)) => (),
-                            Some(_) => {
-                                return Err("non-number on stack with conditional".to_string())
-                            }
-                            None => return Err("stack is empty".to_string()),
-                        }
-                    }
-                    'e' => state = SeekIfEnd(0),
-                    ';' => (),
-                    _ => return Err(format!("unrecognized format option {}", cur)),
-                }
-            }
-            PushParam => {
-                // params are 1-indexed
-                stack.push(mparams[match cur.to_digit(10) {
-                               Some(d) => d as usize - 1,
-                               None => return Err("bad param number".to_string()),
-                           }]
-                           .clone());
-            }
-            SetVar => {
-                if cur >= 'A' && cur <= 'Z' {
-                    if let Some(arg) = stack.pop() {
-                        let idx = (cur as u8) - b'A';
-                        vars.sta_va[idx as usize] = arg;
-                    } else {
-                        return Err("stack is empty".to_string());
-                    }
-                } else if cur >= 'a' && cur <= 'z' {
-                    if let Some(arg) = stack.pop() {
-                        let idx = (cur as u8) - b'a';
-                        vars.dyn_va[idx as usize] = arg;
-                    } else {
-                        return Err("stack is empty".to_string());
-                    }
-                } else {
-                    return Err("bad variable name in %P".to_string());
-                }
-            }
-            GetVar => {
-                if cur >= 'A' && cur <= 'Z' {
-                    let idx = (cur as u8) - b'A';
-                    stack.push(vars.sta_va[idx as usize].clone());
-                } else if cur >= 'a' && cur <= 'z' {
-                    let idx = (cur as u8) - b'a';
-                    stack.push(vars.dyn_va[idx as usize].clone());
-                } else {
-                    return Err("bad variable name in %g".to_string());
-                }
-            }
-            CharConstant => {
-                stack.push(Number(c as i32));
-                state = CharClose;
-            }
-            CharClose => {
-                if cur != '\'' {
-                    return Err("malformed character constant".to_string());
-                }
-            }
-            IntConstant(i) => {
-                if cur == '}' {
-                    stack.push(Number(i));
-                    state = Nothing;
-                } else if let Some(digit) = cur.to_digit(10) {
-                    match i.checked_mul(10).and_then(|i_ten| i_ten.checked_add(digit as i32)) {
-                        Some(i) => {
-                            state = IntConstant(i);
-                            old_state = Nothing;
-                        }
-                        None => return Err("int constant too large".to_string()),
-                    }
-                } else {
-                    return Err("bad int constant".to_string());
-                }
-            }
-            FormatPattern(ref mut flags, ref mut fstate) => {
-                old_state = Nothing;
-                match (*fstate, cur) {
-                    (_, 'd') | (_, 'o') | (_, 'x') | (_, 'X') | (_, 's') => {
-                        if let Some(arg) = stack.pop() {
-                            let res = format(arg, FormatOp::from_char(cur), *flags)?;
-                            output.extend(res.iter().cloned());
-                            // will cause state to go to Nothing
-                            old_state = FormatPattern(*flags, *fstate);
-                        } else {
-                            return Err("stack is empty".to_string());
-                        }
-                    }
-                    (FormatState::Flags, '#') => {
-                        flags.alternate = true;
-                    }
-                    (FormatState::Flags, '-') => {
-                        flags.left = true;
-                    }
-                    (FormatState::Flags, '+') => {
-                        flags.sign = true;
-                    }
-                    (FormatState::Flags, ' ') => {
-                        flags.space = true;
-                    }
-                    (FormatState::Flags, '0'..='9') => {
-                        flags.width = cur as usize - '0' as usize;
-                        *fstate = FormatState::Width;
-                    }
-                    (FormatState::Flags, '.') => {
-                        *fstate = FormatState::Precision;
-                    }
-                    (FormatState::Width, '0'..='9') => {
-                        let old = flags.width;
-                        flags.width = flags.width * 10 + (cur as usize - '0' as usize);
-                        if flags.width < old {
-                            return Err("format width overflow".to_string());
-                        }
-                    }
-                    (FormatState::Width, '.') => {
-                        *fstate = FormatState::Precision;
-                    }
-                    (FormatState::Precision, '0'..='9') => {
-                        let old = flags.precision;
-                        flags.precision = flags.precision * 10 + (cur as usize - '0' as usize);
-                        if flags.precision < old {
-                            return Err("format precision overflow".to_string());
-                        }
-                    }
-                    _ => return Err("invalid format specifier".to_string()),
-                }
-            }
-            SeekIfElse(level) => {
-                if cur == '%' {
-                    state = SeekIfElsePercent(level);
-                }
-                old_state = Nothing;
-            }
-            SeekIfElsePercent(level) => {
-                if cur == ';' {
-                    if level == 0 {
-                        state = Nothing;
-                    } else {
-                        state = SeekIfElse(level - 1);
-                    }
-                } else if cur == 'e' && level == 0 {
-                    state = Nothing;
-                } else if cur == '?' {
-                    state = SeekIfElse(level + 1);
-                } else {
-                    state = SeekIfElse(level);
-                }
-            }
-            SeekIfEnd(level) => {
-                if cur == '%' {
-                    state = SeekIfEndPercent(level);
-                }
-                old_state = Nothing;
-            }
-            SeekIfEndPercent(level) => {
-                if cur == ';' {
-                    if level == 0 {
-                        state = Nothing;
-                    } else {
-                        state = SeekIfEnd(level - 1);
-                    }
-                } else if cur == '?' {
-                    state = SeekIfEnd(level + 1);
-                } else {
-                    state = SeekIfEnd(level);
-                }
-            }
-        }
-        if state == old_state {
-            state = Nothing;
-        }
-    }
-    Ok(output)
-}
-
-#[derive(Copy, PartialEq, Clone)]
-struct Flags {
-    width: usize,
-    precision: usize,
-    alternate: bool,
-    left: bool,
-    sign: bool,
-    space: bool,
-}
-
-impl Flags {
-    fn new() -> Flags {
-        Flags {
-            width: 0,
-            precision: 0,
-            alternate: false,
-            left: false,
-            sign: false,
-            space: false,
-        }
-    }
-}
-
-#[derive(Copy, Clone)]
-enum FormatOp {
-    Digit,
-    Octal,
-    LowerHex,
-    UpperHex,
-    String,
-}
-
-impl FormatOp {
-    fn from_char(c: char) -> FormatOp {
-        match c {
-            'd' => FormatOp::Digit,
-            'o' => FormatOp::Octal,
-            'x' => FormatOp::LowerHex,
-            'X' => FormatOp::UpperHex,
-            's' => FormatOp::String,
-            _ => panic!("bad FormatOp char"),
-        }
-    }
-    fn to_char(self) -> char {
-        match self {
-            FormatOp::Digit => 'd',
-            FormatOp::Octal => 'o',
-            FormatOp::LowerHex => 'x',
-            FormatOp::UpperHex => 'X',
-            FormatOp::String => 's',
-        }
-    }
-}
-
-fn format(val: Param, op: FormatOp, flags: Flags) -> Result<Vec<u8>, String> {
-    let mut s = match val {
-        Number(d) => {
-            match op {
-                FormatOp::Digit => {
-                    if flags.sign {
-                        format!("{:+01$}", d, flags.precision)
-                    } else if d < 0 {
-                        // C doesn't take sign into account in precision calculation.
-                        format!("{:01$}", d, flags.precision + 1)
-                    } else if flags.space {
-                        format!(" {:01$}", d, flags.precision)
-                    } else {
-                        format!("{:01$}", d, flags.precision)
-                    }
-                }
-                FormatOp::Octal => {
-                    if flags.alternate {
-                        // Leading octal zero counts against precision.
-                        format!("0{:01$o}", d, flags.precision.saturating_sub(1))
-                    } else {
-                        format!("{:01$o}", d, flags.precision)
-                    }
-                }
-                FormatOp::LowerHex => {
-                    if flags.alternate && d != 0 {
-                        format!("0x{:01$x}", d, flags.precision)
-                    } else {
-                        format!("{:01$x}", d, flags.precision)
-                    }
-                }
-                FormatOp::UpperHex => {
-                    if flags.alternate && d != 0 {
-                        format!("0X{:01$X}", d, flags.precision)
-                    } else {
-                        format!("{:01$X}", d, flags.precision)
-                    }
-                }
-                FormatOp::String => return Err("non-number on stack with %s".to_string()),
-            }
-            .into_bytes()
-        }
-        Words(s) => {
-            match op {
-                FormatOp::String => {
-                    let mut s = s.into_bytes();
-                    if flags.precision > 0 && flags.precision < s.len() {
-                        s.truncate(flags.precision);
-                    }
-                    s
-                }
-                _ => return Err(format!("non-string on stack with %{}", op.to_char())),
-            }
-        }
-    };
-    if flags.width > s.len() {
-        let n = flags.width - s.len();
-        if flags.left {
-            s.extend(repeat(b' ').take(n));
-        } else {
-            let mut s_ = Vec::with_capacity(flags.width);
-            s_.extend(repeat(b' ').take(n));
-            s_.extend(s.into_iter());
-            s = s_;
-        }
-    }
-    Ok(s)
-}
-
-#[cfg(test)]
-mod test {
-    use super::{expand, Variables};
-    use super::Param::{self, Words, Number};
-    use std::result::Result::Ok;
-
-    #[test]
-    fn test_basic_setabf() {
-        let s = b"\\E[48;5;%p1%dm";
-        assert_eq!(expand(s, &[Number(1)], &mut Variables::new()).unwrap(),
-                   "\\E[48;5;1m".bytes().collect::<Vec<_>>());
-    }
-
-    #[test]
-    fn test_multiple_int_constants() {
-        assert_eq!(expand(b"%{1}%{2}%d%d", &[], &mut Variables::new()).unwrap(),
-                   "21".bytes().collect::<Vec<_>>());
-    }
-
-    #[test]
-    fn test_op_i() {
-        let mut vars = Variables::new();
-        assert_eq!(expand(b"%p1%d%p2%d%p3%d%i%p1%d%p2%d%p3%d",
-                          &[Number(1), Number(2), Number(3)],
-                          &mut vars),
-                   Ok("123233".bytes().collect::<Vec<_>>()));
-        assert_eq!(expand(b"%p1%d%p2%d%i%p1%d%p2%d", &[], &mut vars),
-                   Ok("0011".bytes().collect::<Vec<_>>()));
-    }
-
-    #[test]
-    fn test_param_stack_failure_conditions() {
-        let mut varstruct = Variables::new();
-        let vars = &mut varstruct;
-        fn get_res(fmt: &str,
-                   cap: &str,
-                   params: &[Param],
-                   vars: &mut Variables)
-                   -> Result<Vec<u8>, String> {
-            let mut u8v: Vec<_> = fmt.bytes().collect();
-            u8v.extend(cap.as_bytes().iter().map(|&b| b));
-            expand(&u8v, params, vars)
-        }
-
-        let caps = ["%d", "%c", "%s", "%Pa", "%l", "%!", "%~"];
-        for &cap in caps.iter() {
-            let res = get_res("", cap, &[], vars);
-            assert!(res.is_err(),
-                    "Op {} succeeded incorrectly with 0 stack entries",
-                    cap);
-            let p = if cap == "%s" || cap == "%l" {
-                Words("foo".to_string())
-            } else {
-                Number(97)
-            };
-            let res = get_res("%p1", cap, &[p], vars);
-            assert!(res.is_ok(),
-                    "Op {} failed with 1 stack entry: {}",
-                    cap,
-                    res.unwrap_err());
-        }
-        let caps = ["%+", "%-", "%*", "%/", "%m", "%&", "%|", "%A", "%O"];
-        for &cap in caps.iter() {
-            let res = expand(cap.as_bytes(), &[], vars);
-            assert!(res.is_err(),
-                    "Binop {} succeeded incorrectly with 0 stack entries",
-                    cap);
-            let res = get_res("%{1}", cap, &[], vars);
-            assert!(res.is_err(),
-                    "Binop {} succeeded incorrectly with 1 stack entry",
-                    cap);
-            let res = get_res("%{1}%{2}", cap, &[], vars);
-            assert!(res.is_ok(),
-                    "Binop {} failed with 2 stack entries: {}",
-                    cap,
-                    res.unwrap_err());
-        }
-    }
-
-    #[test]
-    fn test_push_bad_param() {
-        assert!(expand(b"%pa", &[], &mut Variables::new()).is_err());
-    }
-
-    #[test]
-    fn test_comparison_ops() {
-        let v = [('<', [1u8, 0u8, 0u8]), ('=', [0u8, 1u8, 0u8]), ('>', [0u8, 0u8, 1u8])];
-        for &(op, bs) in v.iter() {
-            let s = format!("%{{1}}%{{2}}%{}%d", op);
-            let res = expand(s.as_bytes(), &[], &mut Variables::new());
-            assert!(res.is_ok(), res.unwrap_err());
-            assert_eq!(res.unwrap(), vec![b'0' + bs[0]]);
-            let s = format!("%{{1}}%{{1}}%{}%d", op);
-            let res = expand(s.as_bytes(), &[], &mut Variables::new());
-            assert!(res.is_ok(), res.unwrap_err());
-            assert_eq!(res.unwrap(), vec![b'0' + bs[1]]);
-            let s = format!("%{{2}}%{{1}}%{}%d", op);
-            let res = expand(s.as_bytes(), &[], &mut Variables::new());
-            assert!(res.is_ok(), res.unwrap_err());
-            assert_eq!(res.unwrap(), vec![b'0' + bs[2]]);
-        }
-    }
-
-    #[test]
-    fn test_conditionals() {
-        let mut vars = Variables::new();
-        let s = b"\\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m";
-        let res = expand(s, &[Number(1)], &mut vars);
-        assert!(res.is_ok(), res.unwrap_err());
-        assert_eq!(res.unwrap(), "\\E[31m".bytes().collect::<Vec<_>>());
-        let res = expand(s, &[Number(8)], &mut vars);
-        assert!(res.is_ok(), res.unwrap_err());
-        assert_eq!(res.unwrap(), "\\E[90m".bytes().collect::<Vec<_>>());
-        let res = expand(s, &[Number(42)], &mut vars);
-        assert!(res.is_ok(), res.unwrap_err());
-        assert_eq!(res.unwrap(), "\\E[38;5;42m".bytes().collect::<Vec<_>>());
-    }
-
-    #[test]
-    fn test_format() {
-        let mut varstruct = Variables::new();
-        let vars = &mut varstruct;
-        assert_eq!(expand(b"%p1%s%p2%2s%p3%2s%p4%.2s",
-                          &[Words("foo".to_string()),
-                            Words("foo".to_string()),
-                            Words("f".to_string()),
-                            Words("foo".to_string())],
-                          vars),
-                   Ok("foofoo ffo".bytes().collect::<Vec<_>>()));
-        assert_eq!(expand(b"%p1%:-4.2s", &[Words("foo".to_string())], vars),
-                   Ok("fo  ".bytes().collect::<Vec<_>>()));
-
-        assert_eq!(expand(b"%p1%d%p1%.3d%p1%5d%p1%:+d", &[Number(1)], vars),
-                   Ok("1001    1+1".bytes().collect::<Vec<_>>()));
-        assert_eq!(expand(b"%p1%o%p1%#o%p2%6.4x%p2%#6.4X",
-                          &[Number(15), Number(27)],
-                          vars),
-                   Ok("17017  001b0X001B".bytes().collect::<Vec<_>>()));
-    }
-}
diff --git a/src/libterm/terminfo/parser/compiled.rs b/src/libterm/terminfo/parser/compiled.rs
deleted file mode 100644
index 05a8c94..0000000
--- a/src/libterm/terminfo/parser/compiled.rs
+++ /dev/null
@@ -1,346 +0,0 @@
-#![allow(non_upper_case_globals, missing_docs)]
-
-//! ncurses-compatible compiled terminfo format parsing (term(5))
-
-use std::collections::HashMap;
-use std::io;
-use std::io::prelude::*;
-use super::super::TermInfo;
-
-// These are the orders ncurses uses in its compiled format (as of 5.9). Not sure if portable.
-
-#[rustfmt::skip]
-pub static boolfnames: &[&str] = &["auto_left_margin", "auto_right_margin",
-    "no_esc_ctlc", "ceol_standout_glitch", "eat_newline_glitch", "erase_overstrike", "generic_type",
-    "hard_copy", "has_meta_key", "has_status_line", "insert_null_glitch", "memory_above",
-    "memory_below", "move_insert_mode", "move_standout_mode", "over_strike", "status_line_esc_ok",
-    "dest_tabs_magic_smso", "tilde_glitch", "transparent_underline", "xon_xoff", "needs_xon_xoff",
-    "prtr_silent", "hard_cursor", "non_rev_rmcup", "no_pad_char", "non_dest_scroll_region",
-    "can_change", "back_color_erase", "hue_lightness_saturation", "col_addr_glitch",
-    "cr_cancels_micro_mode", "has_print_wheel", "row_addr_glitch", "semi_auto_right_margin",
-    "cpi_changes_res", "lpi_changes_res", "backspaces_with_bs", "crt_no_scrolling",
-    "no_correctly_working_cr", "gnu_has_meta_key", "linefeed_is_newline", "has_hardware_tabs",
-    "return_does_clr_eol"];
-
-#[rustfmt::skip]
-pub static boolnames: &[&str] = &["bw", "am", "xsb", "xhp", "xenl", "eo",
-    "gn", "hc", "km", "hs", "in", "db", "da", "mir", "msgr", "os", "eslok", "xt", "hz", "ul", "xon",
-    "nxon", "mc5i", "chts", "nrrmc", "npc", "ndscr", "ccc", "bce", "hls", "xhpa", "crxm", "daisy",
-    "xvpa", "sam", "cpix", "lpix", "OTbs", "OTns", "OTnc", "OTMT", "OTNL", "OTpt", "OTxr"];
-
-#[rustfmt::skip]
-pub static numfnames: &[&str] = &[ "columns", "init_tabs", "lines",
-    "lines_of_memory", "magic_cookie_glitch", "padding_baud_rate", "virtual_terminal",
-    "width_status_line", "num_labels", "label_height", "label_width", "max_attributes",
-    "maximum_windows", "max_colors", "max_pairs", "no_color_video", "buffer_capacity",
-    "dot_vert_spacing", "dot_horz_spacing", "max_micro_address", "max_micro_jump", "micro_col_size",
-    "micro_line_size", "number_of_pins", "output_res_char", "output_res_line",
-    "output_res_horz_inch", "output_res_vert_inch", "print_rate", "wide_char_size", "buttons",
-    "bit_image_entwining", "bit_image_type", "magic_cookie_glitch_ul", "carriage_return_delay",
-    "new_line_delay", "backspace_delay", "horizontal_tab_delay", "number_of_function_keys"];
-
-#[rustfmt::skip]
-pub static numnames: &[&str] = &[ "cols", "it", "lines", "lm", "xmc", "pb",
-    "vt", "wsl", "nlab", "lh", "lw", "ma", "wnum", "colors", "pairs", "ncv", "bufsz", "spinv",
-    "spinh", "maddr", "mjump", "mcs", "mls", "npins", "orc", "orl", "orhi", "orvi", "cps", "widcs",
-    "btns", "bitwin", "bitype", "UTug", "OTdC", "OTdN", "OTdB", "OTdT", "OTkn"];
-
-#[rustfmt::skip]
-pub static stringfnames: &[&str] = &[ "back_tab", "bell", "carriage_return",
-    "change_scroll_region", "clear_all_tabs", "clear_screen", "clr_eol", "clr_eos",
-    "column_address", "command_character", "cursor_address", "cursor_down", "cursor_home",
-    "cursor_invisible", "cursor_left", "cursor_mem_address", "cursor_normal", "cursor_right",
-    "cursor_to_ll", "cursor_up", "cursor_visible", "delete_character", "delete_line",
-    "dis_status_line", "down_half_line", "enter_alt_charset_mode", "enter_blink_mode",
-    "enter_bold_mode", "enter_ca_mode", "enter_delete_mode", "enter_dim_mode", "enter_insert_mode",
-    "enter_secure_mode", "enter_protected_mode", "enter_reverse_mode", "enter_standout_mode",
-    "enter_underline_mode", "erase_chars", "exit_alt_charset_mode", "exit_attribute_mode",
-    "exit_ca_mode", "exit_delete_mode", "exit_insert_mode", "exit_standout_mode",
-    "exit_underline_mode", "flash_screen", "form_feed", "from_status_line", "init_1string",
-    "init_2string", "init_3string", "init_file", "insert_character", "insert_line",
-    "insert_padding", "key_backspace", "key_catab", "key_clear", "key_ctab", "key_dc", "key_dl",
-    "key_down", "key_eic", "key_eol", "key_eos", "key_f0", "key_f1", "key_f10", "key_f2", "key_f3",
-    "key_f4", "key_f5", "key_f6", "key_f7", "key_f8", "key_f9", "key_home", "key_ic", "key_il",
-    "key_left", "key_ll", "key_npage", "key_ppage", "key_right", "key_sf", "key_sr", "key_stab",
-    "key_up", "keypad_local", "keypad_xmit", "lab_f0", "lab_f1", "lab_f10", "lab_f2", "lab_f3",
-    "lab_f4", "lab_f5", "lab_f6", "lab_f7", "lab_f8", "lab_f9", "meta_off", "meta_on", "newline",
-    "pad_char", "parm_dch", "parm_delete_line", "parm_down_cursor", "parm_ich", "parm_index",
-    "parm_insert_line", "parm_left_cursor", "parm_right_cursor", "parm_rindex", "parm_up_cursor",
-    "pkey_key", "pkey_local", "pkey_xmit", "print_screen", "prtr_off", "prtr_on", "repeat_char",
-    "reset_1string", "reset_2string", "reset_3string", "reset_file", "restore_cursor",
-    "row_address", "save_cursor", "scroll_forward", "scroll_reverse", "set_attributes", "set_tab",
-    "set_window", "tab", "to_status_line", "underline_char", "up_half_line", "init_prog", "key_a1",
-    "key_a3", "key_b2", "key_c1", "key_c3", "prtr_non", "char_padding", "acs_chars", "plab_norm",
-    "key_btab", "enter_xon_mode", "exit_xon_mode", "enter_am_mode", "exit_am_mode", "xon_character",
-    "xoff_character", "ena_acs", "label_on", "label_off", "key_beg", "key_cancel", "key_close",
-    "key_command", "key_copy", "key_create", "key_end", "key_enter", "key_exit", "key_find",
-    "key_help", "key_mark", "key_message", "key_move", "key_next", "key_open", "key_options",
-    "key_previous", "key_print", "key_redo", "key_reference", "key_refresh", "key_replace",
-    "key_restart", "key_resume", "key_save", "key_suspend", "key_undo", "key_sbeg", "key_scancel",
-    "key_scommand", "key_scopy", "key_screate", "key_sdc", "key_sdl", "key_select", "key_send",
-    "key_seol", "key_sexit", "key_sfind", "key_shelp", "key_shome", "key_sic", "key_sleft",
-    "key_smessage", "key_smove", "key_snext", "key_soptions", "key_sprevious", "key_sprint",
-    "key_sredo", "key_sreplace", "key_sright", "key_srsume", "key_ssave", "key_ssuspend",
-    "key_sundo", "req_for_input", "key_f11", "key_f12", "key_f13", "key_f14", "key_f15", "key_f16",
-    "key_f17", "key_f18", "key_f19", "key_f20", "key_f21", "key_f22", "key_f23", "key_f24",
-    "key_f25", "key_f26", "key_f27", "key_f28", "key_f29", "key_f30", "key_f31", "key_f32",
-    "key_f33", "key_f34", "key_f35", "key_f36", "key_f37", "key_f38", "key_f39", "key_f40",
-    "key_f41", "key_f42", "key_f43", "key_f44", "key_f45", "key_f46", "key_f47", "key_f48",
-    "key_f49", "key_f50", "key_f51", "key_f52", "key_f53", "key_f54", "key_f55", "key_f56",
-    "key_f57", "key_f58", "key_f59", "key_f60", "key_f61", "key_f62", "key_f63", "clr_bol",
-    "clear_margins", "set_left_margin", "set_right_margin", "label_format", "set_clock",
-    "display_clock", "remove_clock", "create_window", "goto_window", "hangup", "dial_phone",
-    "quick_dial", "tone", "pulse", "flash_hook", "fixed_pause", "wait_tone", "user0", "user1",
-    "user2", "user3", "user4", "user5", "user6", "user7", "user8", "user9", "orig_pair",
-    "orig_colors", "initialize_color", "initialize_pair", "set_color_pair", "set_foreground",
-    "set_background", "change_char_pitch", "change_line_pitch", "change_res_horz",
-    "change_res_vert", "define_char", "enter_doublewide_mode", "enter_draft_quality",
-    "enter_italics_mode", "enter_leftward_mode", "enter_micro_mode", "enter_near_letter_quality",
-    "enter_normal_quality", "enter_shadow_mode", "enter_subscript_mode", "enter_superscript_mode",
-    "enter_upward_mode", "exit_doublewide_mode", "exit_italics_mode", "exit_leftward_mode",
-    "exit_micro_mode", "exit_shadow_mode", "exit_subscript_mode", "exit_superscript_mode",
-    "exit_upward_mode", "micro_column_address", "micro_down", "micro_left", "micro_right",
-    "micro_row_address", "micro_up", "order_of_pins", "parm_down_micro", "parm_left_micro",
-    "parm_right_micro", "parm_up_micro", "select_char_set", "set_bottom_margin",
-    "set_bottom_margin_parm", "set_left_margin_parm", "set_right_margin_parm", "set_top_margin",
-    "set_top_margin_parm", "start_bit_image", "start_char_set_def", "stop_bit_image",
-    "stop_char_set_def", "subscript_characters", "superscript_characters", "these_cause_cr",
-    "zero_motion", "char_set_names", "key_mouse", "mouse_info", "req_mouse_pos", "get_mouse",
-    "set_a_foreground", "set_a_background", "pkey_plab", "device_type", "code_set_init",
-    "set0_des_seq", "set1_des_seq", "set2_des_seq", "set3_des_seq", "set_lr_margin",
-    "set_tb_margin", "bit_image_repeat", "bit_image_newline", "bit_image_carriage_return",
-    "color_names", "define_bit_image_region", "end_bit_image_region", "set_color_band",
-    "set_page_length", "display_pc_char", "enter_pc_charset_mode", "exit_pc_charset_mode",
-    "enter_scancode_mode", "exit_scancode_mode", "pc_term_options", "scancode_escape",
-    "alt_scancode_esc", "enter_horizontal_hl_mode", "enter_left_hl_mode", "enter_low_hl_mode",
-    "enter_right_hl_mode", "enter_top_hl_mode", "enter_vertical_hl_mode", "set_a_attributes",
-    "set_pglen_inch", "termcap_init2", "termcap_reset", "linefeed_if_not_lf", "backspace_if_not_bs",
-    "other_non_function_keys", "arrow_key_map", "acs_ulcorner", "acs_llcorner", "acs_urcorner",
-    "acs_lrcorner", "acs_ltee", "acs_rtee", "acs_btee", "acs_ttee", "acs_hline", "acs_vline",
-    "acs_plus", "memory_lock", "memory_unlock", "box_chars_1"];
-
-#[rustfmt::skip]
-pub static stringnames: &[&str] = &[ "cbt", "_", "cr", "csr", "tbc", "clear",
-    "_", "_", "hpa", "cmdch", "cup", "cud1", "home", "civis", "cub1", "mrcup", "cnorm", "cuf1",
-    "ll", "cuu1", "cvvis", "dch1", "dl1", "dsl", "hd", "smacs", "blink", "bold", "smcup", "smdc",
-    "dim", "smir", "invis", "prot", "rev", "smso", "smul", "ech", "rmacs", "sgr0", "rmcup", "rmdc",
-    "rmir", "rmso", "rmul", "flash", "ff", "fsl", "is1", "is2", "is3", "if", "ich1", "il1", "ip",
-    "kbs", "ktbc", "kclr", "kctab", "_", "_", "kcud1", "_", "_", "_", "_", "_", "_", "_", "_", "_",
-    "_", "_", "_", "_", "_", "khome", "_", "_", "kcub1", "_", "knp", "kpp", "kcuf1", "_", "_",
-    "khts", "_", "rmkx", "smkx", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "rmm", "_",
-    "_", "pad", "dch", "dl", "cud", "ich", "indn", "il", "cub", "cuf", "rin", "cuu", "pfkey",
-    "pfloc", "pfx", "mc0", "mc4", "_", "rep", "rs1", "rs2", "rs3", "rf", "rc", "vpa", "sc", "ind",
-    "ri", "sgr", "_", "wind", "_", "tsl", "uc", "hu", "iprog", "_", "_", "_", "_", "_", "mc5p",
-    "rmp", "acsc", "pln", "kcbt", "smxon", "rmxon", "smam", "rmam", "xonc", "xoffc", "_", "smln",
-    "rmln", "_", "kcan", "kclo", "kcmd", "kcpy", "kcrt", "_", "kent", "kext", "kfnd", "khlp",
-    "kmrk", "kmsg", "kmov", "knxt", "kopn", "kopt", "kprv", "kprt", "krdo", "kref", "krfr", "krpl",
-    "krst", "kres", "ksav", "kspd", "kund", "kBEG", "kCAN", "kCMD", "kCPY", "kCRT", "_", "_",
-    "kslt", "kEND", "kEOL", "kEXT", "kFND", "kHLP", "kHOM", "_", "kLFT", "kMSG", "kMOV", "kNXT",
-    "kOPT", "kPRV", "kPRT", "kRDO", "kRPL", "kRIT", "kRES", "kSAV", "kSPD", "kUND", "rfi", "_", "_",
-    "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_",
-    "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_",
-    "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_",
-    "dclk", "rmclk", "cwin", "wingo", "_", "dial", "qdial", "_", "_", "hook", "pause", "wait", "_",
-    "_", "_", "_", "_", "_", "_", "_", "_", "_", "op", "oc", "initc", "initp", "scp", "setf",
-    "setb", "cpi", "lpi", "chr", "cvr", "defc", "swidm", "sdrfq", "sitm", "slm", "smicm", "snlq",
-    "snrmq", "sshm", "ssubm", "ssupm", "sum", "rwidm", "ritm", "rlm", "rmicm", "rshm", "rsubm",
-    "rsupm", "rum", "mhpa", "mcud1", "mcub1", "mcuf1", "mvpa", "mcuu1", "porder", "mcud", "mcub",
-    "mcuf", "mcuu", "scs", "smgb", "smgbp", "smglp", "smgrp", "smgt", "smgtp", "sbim", "scsd",
-    "rbim", "rcsd", "subcs", "supcs", "docr", "zerom", "csnm", "kmous", "minfo", "reqmp", "getm",
-    "setaf", "setab", "pfxl", "devt", "csin", "s0ds", "s1ds", "s2ds", "s3ds", "smglr", "smgtb",
-    "birep", "binel", "bicr", "colornm", "defbi", "endbi", "setcolor", "slines", "dispc", "smpch",
-    "rmpch", "smsc", "rmsc", "pctrm", "scesc", "scesa", "ehhlm", "elhlm", "elohlm", "erhlm",
-    "ethlm", "evhlm", "sgr1", "slength", "OTi2", "OTrs", "OTnl", "OTbs", "OTko", "OTma", "OTG2",
-    "OTG3", "OTG1", "OTG4", "OTGR", "OTGL", "OTGU", "OTGD", "OTGH", "OTGV", "OTGC", "meml", "memu",
-    "box1"];
-
-fn read_le_u16(r: &mut dyn io::Read) -> io::Result<u16> {
-    let mut b = [0; 2];
-    let mut amt = 0;
-    while amt < b.len() {
-        match r.read(&mut b[amt..])? {
-            0 => return Err(io::Error::new(io::ErrorKind::Other, "end of file")),
-            n => amt += n,
-        }
-    }
-    Ok((b[0] as u16) | ((b[1] as u16) << 8))
-}
-
-fn read_byte(r: &mut dyn io::Read) -> io::Result<u8> {
-    match r.bytes().next() {
-        Some(s) => s,
-        None => Err(io::Error::new(io::ErrorKind::Other, "end of file")),
-    }
-}
-
-/// Parse a compiled terminfo entry, using long capability names if `longnames`
-/// is true
-pub fn parse(file: &mut dyn io::Read, longnames: bool) -> Result<TermInfo, String> {
-    macro_rules! t( ($e:expr) => (
-        match $e {
-            Ok(e) => e,
-            Err(e) => return Err(e.to_string())
-        }
-    ) );
-
-    let (bnames, snames, nnames) = if longnames {
-        (boolfnames, stringfnames, numfnames)
-    } else {
-        (boolnames, stringnames, numnames)
-    };
-
-    // Check magic number
-    let magic = t!(read_le_u16(file));
-    if magic != 0x011A {
-        return Err(format!("invalid magic number: expected {:x}, found {:x}",
-                           0x011A,
-                           magic));
-    }
-
-    // According to the spec, these fields must be >= -1 where -1 means that the feature is not
-    // supported. Using 0 instead of -1 works because we skip sections with length 0.
-    macro_rules! read_nonneg {
-        () => {{
-            match t!(read_le_u16(file)) as i16 {
-                n if n >= 0 => n as usize,
-                -1 => 0,
-                _ => return Err("incompatible file: length fields must be  >= -1".to_string()),
-            }
-        }}
-    }
-
-    let names_bytes = read_nonneg!();
-    let bools_bytes = read_nonneg!();
-    let numbers_count = read_nonneg!();
-    let string_offsets_count = read_nonneg!();
-    let string_table_bytes = read_nonneg!();
-
-    if names_bytes == 0 {
-        return Err("incompatible file: names field must be at least 1 byte wide".to_string());
-    }
-
-    if bools_bytes > boolnames.len() {
-        return Err("incompatible file: more booleans than expected".to_string());
-    }
-
-    if numbers_count > numnames.len() {
-        return Err("incompatible file: more numbers than expected".to_string());
-    }
-
-    if string_offsets_count > stringnames.len() {
-        return Err("incompatible file: more string offsets than expected".to_string());
-    }
-
-    // don't read NUL
-    let mut bytes = Vec::new();
-    t!(file.take((names_bytes - 1) as u64).read_to_end(&mut bytes));
-    let names_str = match String::from_utf8(bytes) {
-        Ok(s) => s,
-        Err(_) => return Err("input not utf-8".to_string()),
-    };
-
-    let term_names: Vec<String> = names_str.split('|')
-                                           .map(|s| s.to_string())
-                                           .collect();
-    // consume NUL
-    if t!(read_byte(file)) != b'\0' {
-        return Err("incompatible file: missing null terminator for names section".to_string());
-    }
-
-    let bools_map: HashMap<String, bool> = t! {
-        (0..bools_bytes).filter_map(|i| match read_byte(file) {
-            Err(e) => Some(Err(e)),
-            Ok(1) => Some(Ok((bnames[i].to_string(), true))),
-            Ok(_) => None
-        }).collect()
-    };
-
-    if (bools_bytes + names_bytes) % 2 == 1 {
-        t!(read_byte(file)); // compensate for padding
-    }
-
-    let numbers_map: HashMap<String, u16> = t! {
-        (0..numbers_count).filter_map(|i| match read_le_u16(file) {
-            Ok(0xFFFF) => None,
-            Ok(n) => Some(Ok((nnames[i].to_string(), n))),
-            Err(e) => Some(Err(e))
-        }).collect()
-    };
-
-    let string_map: HashMap<String, Vec<u8>> = if string_offsets_count > 0 {
-        let string_offsets: Vec<u16> = t!((0..string_offsets_count)
-                                                .map(|_| read_le_u16(file))
-                                                .collect());
-
-        let mut string_table = Vec::new();
-        t!(file.take(string_table_bytes as u64).read_to_end(&mut string_table));
-
-        t!(string_offsets.into_iter().enumerate().filter(|&(_, offset)| {
-            // non-entry
-            offset != 0xFFFF
-        }).map(|(i, offset)| {
-            let offset = offset as usize;
-
-            let name = if snames[i] == "_" {
-                stringfnames[i]
-            } else {
-                snames[i]
-            };
-
-            if offset == 0xFFFE {
-                // undocumented: FFFE indicates cap@, which means the capability is not present
-                // unsure if the handling for this is correct
-                return Ok((name.to_string(), Vec::new()));
-            }
-
-            // Find the offset of the NUL we want to go to
-            let nulpos = string_table[offset..string_table_bytes].iter().position(|&b| b == 0);
-            match nulpos {
-                Some(len) => Ok((name.to_string(), string_table[offset..offset + len].to_vec())),
-                None => Err("invalid file: missing NUL in string_table".to_string()),
-            }
-        }).collect())
-    } else {
-        HashMap::new()
-    };
-
-    // And that's all there is to it
-    Ok(TermInfo {
-        names: term_names,
-        bools: bools_map,
-        numbers: numbers_map,
-        strings: string_map,
-    })
-}
-
-/// Creates a dummy TermInfo struct for msys terminals
-pub fn msys_terminfo() -> TermInfo {
-    let mut strings = HashMap::new();
-    strings.insert("sgr0".to_string(), b"\x1B[0m".to_vec());
-    strings.insert("bold".to_string(), b"\x1B[1m".to_vec());
-    strings.insert("setaf".to_string(), b"\x1B[3%p1%dm".to_vec());
-    strings.insert("setab".to_string(), b"\x1B[4%p1%dm".to_vec());
-
-    let mut numbers = HashMap::new();
-    numbers.insert("colors".to_string(), 8u16);
-
-    TermInfo {
-        names: vec!["cygwin".to_string()], // msys is a fork of an older cygwin version
-        bools: HashMap::new(),
-        numbers,
-        strings,
-    }
-}
-
-#[cfg(test)]
-mod test {
-
-    use super::{boolnames, boolfnames, numnames, numfnames, stringnames, stringfnames};
-
-    #[test]
-    fn test_veclens() {
-        assert_eq!(boolfnames.len(), boolnames.len());
-        assert_eq!(numfnames.len(), numnames.len());
-        assert_eq!(stringfnames.len(), stringnames.len());
-    }
-}
diff --git a/src/libterm/terminfo/searcher.rs b/src/libterm/terminfo/searcher.rs
deleted file mode 100644
index 0b17ed3..0000000
--- a/src/libterm/terminfo/searcher.rs
+++ /dev/null
@@ -1,84 +0,0 @@
-//! ncurses-compatible database discovery.
-//!
-//! Does not support hashed database, only filesystem!
-
-use std::env;
-use std::fs;
-use std::path::PathBuf;
-
-/// Return path to database entry for `term`
-#[allow(deprecated)]
-pub fn get_dbpath_for_term(term: &str) -> Option<PathBuf> {
-    let mut dirs_to_search = Vec::new();
-    let first_char = term.chars().next()?;
-
-    // Find search directory
-    if let Some(dir) = env::var_os("TERMINFO") {
-        dirs_to_search.push(PathBuf::from(dir));
-    }
-
-    if let Ok(dirs) = env::var("TERMINFO_DIRS") {
-        for i in dirs.split(':') {
-            if i == "" {
-                dirs_to_search.push(PathBuf::from("/usr/share/terminfo"));
-            } else {
-                dirs_to_search.push(PathBuf::from(i));
-            }
-        }
-    } else {
-        // Found nothing in TERMINFO_DIRS, use the default paths:
-        // According to  /etc/terminfo/README, after looking at
-        // ~/.terminfo, ncurses will search /etc/terminfo, then
-        // /lib/terminfo, and eventually /usr/share/terminfo.
-        // On Haiku the database can be found at /boot/system/data/terminfo
-        if let Some(mut homedir) = env::home_dir() {
-            homedir.push(".terminfo");
-            dirs_to_search.push(homedir)
-        }
-
-        dirs_to_search.push(PathBuf::from("/etc/terminfo"));
-        dirs_to_search.push(PathBuf::from("/lib/terminfo"));
-        dirs_to_search.push(PathBuf::from("/usr/share/terminfo"));
-        dirs_to_search.push(PathBuf::from("/boot/system/data/terminfo"));
-    }
-
-    // Look for the terminal in all of the search directories
-    for mut p in dirs_to_search {
-        if fs::metadata(&p).is_ok() {
-            p.push(&first_char.to_string());
-            p.push(&term);
-            if fs::metadata(&p).is_ok() {
-                return Some(p);
-            }
-            p.pop();
-            p.pop();
-
-            // on some installations the dir is named after the hex of the char
-            // (e.g., macOS)
-            p.push(&format!("{:x}", first_char as usize));
-            p.push(term);
-            if fs::metadata(&p).is_ok() {
-                return Some(p);
-            }
-        }
-    }
-    None
-}
-
-#[test]
-#[ignore = "buildbots don't have ncurses installed and I can't mock everything I need"]
-fn test_get_dbpath_for_term() {
-    // woefully inadequate test coverage
-    // note: current tests won't work with non-standard terminfo hierarchies (e.g., macOS's)
-    use std::env;
-    // FIXME (#9639): This needs to handle non-utf8 paths
-    fn x(t: &str) -> String {
-        let p = get_dbpath_for_term(t).expect("no terminfo entry found");
-        p.to_str().unwrap().to_string()
-    }
-    assert!(x("screen") == "/usr/share/terminfo/s/screen");
-    assert!(get_dbpath_for_term("") == None);
-    env::set_var("TERMINFO_DIRS", ":");
-    assert!(x("screen") == "/usr/share/terminfo/s/screen");
-    env::remove_var("TERMINFO_DIRS");
-}
diff --git a/src/libterm/win.rs b/src/libterm/win.rs
deleted file mode 100644
index 6d42b01..0000000
--- a/src/libterm/win.rs
+++ /dev/null
@@ -1,203 +0,0 @@
-//! Windows console handling
-
-// FIXME (#13400): this is only a tiny fraction of the Windows console api
-
-extern crate libc;
-
-use std::io;
-use std::io::prelude::*;
-
-use crate::Attr;
-use crate::color;
-use crate::Terminal;
-
-/// A Terminal implementation that uses the Win32 Console API.
-pub struct WinConsole<T> {
-    buf: T,
-    def_foreground: color::Color,
-    def_background: color::Color,
-    foreground: color::Color,
-    background: color::Color,
-}
-
-type WORD = u16;
-type DWORD = u32;
-type BOOL = i32;
-type HANDLE = *mut u8;
-
-#[allow(non_snake_case)]
-#[repr(C)]
-struct CONSOLE_SCREEN_BUFFER_INFO {
-    dwSize: [libc::c_short; 2],
-    dwCursorPosition: [libc::c_short; 2],
-    wAttributes: WORD,
-    srWindow: [libc::c_short; 4],
-    dwMaximumWindowSize: [libc::c_short; 2],
-}
-
-#[allow(non_snake_case)]
-#[link(name = "kernel32")]
-extern "system" {
-    fn SetConsoleTextAttribute(handle: HANDLE, attr: WORD) -> BOOL;
-    fn GetStdHandle(which: DWORD) -> HANDLE;
-    fn GetConsoleScreenBufferInfo(handle: HANDLE, info: *mut CONSOLE_SCREEN_BUFFER_INFO) -> BOOL;
-}
-
-fn color_to_bits(color: color::Color) -> u16 {
-    // magic numbers from mingw-w64's wincon.h
-
-    let bits = match color % 8 {
-        color::BLACK => 0,
-        color::BLUE => 0x1,
-        color::GREEN => 0x2,
-        color::RED => 0x4,
-        color::YELLOW => 0x2 | 0x4,
-        color::MAGENTA => 0x1 | 0x4,
-        color::CYAN => 0x1 | 0x2,
-        color::WHITE => 0x1 | 0x2 | 0x4,
-        _ => unreachable!(),
-    };
-
-    if color >= 8 {
-        bits | 0x8
-    } else {
-        bits
-    }
-}
-
-fn bits_to_color(bits: u16) -> color::Color {
-    let color = match bits & 0x7 {
-        0 => color::BLACK,
-        0x1 => color::BLUE,
-        0x2 => color::GREEN,
-        0x4 => color::RED,
-        0x6 => color::YELLOW,
-        0x5 => color::MAGENTA,
-        0x3 => color::CYAN,
-        0x7 => color::WHITE,
-        _ => unreachable!(),
-    };
-
-    color | (bits & 0x8) // copy the hi-intensity bit
-}
-
-impl<T: Write + Send + 'static> WinConsole<T> {
-    fn apply(&mut self) {
-        let _unused = self.buf.flush();
-        let mut accum: WORD = 0;
-        accum |= color_to_bits(self.foreground);
-        accum |= color_to_bits(self.background) << 4;
-
-        unsafe {
-            // Magic -11 means stdout, from
-            // http://msdn.microsoft.com/en-us/library/windows/desktop/ms683231%28v=vs.85%29.aspx
-            //
-            // You may be wondering, "but what about stderr?", and the answer
-            // to that is that setting terminal attributes on the stdout
-            // handle also sets them for stderr, since they go to the same
-            // terminal! Admittedly, this is fragile, since stderr could be
-            // redirected to a different console. This is good enough for
-            // rustc though. See #13400.
-            let out = GetStdHandle(-11i32 as DWORD);
-            SetConsoleTextAttribute(out, accum);
-        }
-    }
-
-    /// Returns `None` whenever the terminal cannot be created for some reason.
-    pub fn new(out: T) -> io::Result<WinConsole<T>> {
-        let fg;
-        let bg;
-        unsafe {
-            let mut buffer_info = ::std::mem::uninitialized();
-            if GetConsoleScreenBufferInfo(GetStdHandle(-11i32 as DWORD), &mut buffer_info) != 0 {
-                fg = bits_to_color(buffer_info.wAttributes);
-                bg = bits_to_color(buffer_info.wAttributes >> 4);
-            } else {
-                fg = color::WHITE;
-                bg = color::BLACK;
-            }
-        }
-        Ok(WinConsole {
-            buf: out,
-            def_foreground: fg,
-            def_background: bg,
-            foreground: fg,
-            background: bg,
-        })
-    }
-}
-
-impl<T: Write> Write for WinConsole<T> {
-    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        self.buf.write(buf)
-    }
-
-    fn flush(&mut self) -> io::Result<()> {
-        self.buf.flush()
-    }
-}
-
-impl<T: Write + Send + 'static> Terminal for WinConsole<T> {
-    type Output = T;
-
-    fn fg(&mut self, color: color::Color) -> io::Result<bool> {
-        self.foreground = color;
-        self.apply();
-
-        Ok(true)
-    }
-
-    fn bg(&mut self, color: color::Color) -> io::Result<bool> {
-        self.background = color;
-        self.apply();
-
-        Ok(true)
-    }
-
-    fn attr(&mut self, attr: Attr) -> io::Result<bool> {
-        match attr {
-            Attr::ForegroundColor(f) => {
-                self.foreground = f;
-                self.apply();
-                Ok(true)
-            }
-            Attr::BackgroundColor(b) => {
-                self.background = b;
-                self.apply();
-                Ok(true)
-            }
-            _ => Ok(false),
-        }
-    }
-
-    fn supports_attr(&self, attr: Attr) -> bool {
-        // it claims support for underscore and reverse video, but I can't get
-        // it to do anything -cmr
-        match attr {
-            Attr::ForegroundColor(_) | Attr::BackgroundColor(_) => true,
-            _ => false,
-        }
-    }
-
-    fn reset(&mut self) -> io::Result<bool> {
-        self.foreground = self.def_foreground;
-        self.background = self.def_background;
-        self.apply();
-
-        Ok(true)
-    }
-
-    fn get_ref(&self) -> &T {
-        &self.buf
-    }
-
-    fn get_mut(&mut self) -> &mut T {
-        &mut self.buf
-    }
-
-    fn into_inner(self) -> T
-        where Self: Sized
-    {
-        self.buf
-    }
-}
diff --git a/src/libtest/Cargo.toml b/src/libtest/Cargo.toml
index 10bdd6e..26ac788 100644
--- a/src/libtest/Cargo.toml
+++ b/src/libtest/Cargo.toml
@@ -10,8 +10,7 @@
 crate-type = ["dylib", "rlib"]
 
 [dependencies]
-getopts = "0.2"
-term = { path = "../libterm" }
+libtest = { version = "0.0.1" }
 
 # not actually used but needed to always have proc_macro in the sysroot
 proc_macro = { path = "../libproc_macro" }
diff --git a/src/libtest/README.md b/src/libtest/README.md
new file mode 100644
index 0000000..6d9fe30
--- /dev/null
+++ b/src/libtest/README.md
@@ -0,0 +1,13 @@
+WIP - stable libtest
+===
+
+The migration of libtest to stable Rust is currently in progress.
+
+You can find libtest at: https://github.com/rust-lang/libtest . If you need to
+make a change:
+
+* perform the change there, 
+* do a new crates.io release, and
+* send a PR to rust-lang/rust bumping the libtest version.
+
+The roadmap of the migration is being tracked here: https://github.com/rust-lang/libtest/issues/2
diff --git a/src/libtest/formatters/json.rs b/src/libtest/formatters/json.rs
deleted file mode 100644
index a06497f..0000000
--- a/src/libtest/formatters/json.rs
+++ /dev/null
@@ -1,208 +0,0 @@
-use super::*;
-
-pub(crate) struct JsonFormatter<T> {
-    out: OutputLocation<T>,
-}
-
-impl<T: Write> JsonFormatter<T> {
-    pub fn new(out: OutputLocation<T>) -> Self {
-        Self { out }
-    }
-
-    fn write_message(&mut self, s: &str) -> io::Result<()> {
-        assert!(!s.contains('\n'));
-
-        self.out.write_all(s.as_ref())?;
-        self.out.write_all(b"\n")
-    }
-
-    fn write_event(
-        &mut self,
-        ty: &str,
-        name: &str,
-        evt: &str,
-        extra: Option<String>,
-    ) -> io::Result<()> {
-        if let Some(extras) = extra {
-            self.write_message(&*format!(
-                r#"{{ "type": "{}", "name": "{}", "event": "{}", {} }}"#,
-                ty, name, evt, extras
-            ))
-        } else {
-            self.write_message(&*format!(
-                r#"{{ "type": "{}", "name": "{}", "event": "{}" }}"#,
-                ty, name, evt
-            ))
-        }
-    }
-}
-
-impl<T: Write> OutputFormatter for JsonFormatter<T> {
-    fn write_run_start(&mut self, test_count: usize) -> io::Result<()> {
-        self.write_message(&*format!(
-            r#"{{ "type": "suite", "event": "started", "test_count": {} }}"#,
-            test_count
-        ))
-    }
-
-    fn write_test_start(&mut self, desc: &TestDesc) -> io::Result<()> {
-        self.write_message(&*format!(
-            r#"{{ "type": "test", "event": "started", "name": "{}" }}"#,
-            desc.name
-        ))
-    }
-
-    fn write_result(
-        &mut self,
-        desc: &TestDesc,
-        result: &TestResult,
-        stdout: &[u8],
-    ) -> io::Result<()> {
-        match *result {
-            TrOk => self.write_event("test", desc.name.as_slice(), "ok", None),
-
-            TrFailed => {
-                let extra_data = if stdout.len() > 0 {
-                    Some(format!(
-                        r#""stdout": "{}""#,
-                        EscapedString(String::from_utf8_lossy(stdout))
-                    ))
-                } else {
-                    None
-                };
-
-                self.write_event("test", desc.name.as_slice(), "failed", extra_data)
-            }
-
-            TrFailedMsg(ref m) => self.write_event(
-                "test",
-                desc.name.as_slice(),
-                "failed",
-                Some(format!(r#""message": "{}""#, EscapedString(m))),
-            ),
-
-            TrIgnored => self.write_event("test", desc.name.as_slice(), "ignored", None),
-
-            TrAllowedFail => {
-                self.write_event("test", desc.name.as_slice(), "allowed_failure", None)
-            }
-
-            TrBench(ref bs) => {
-                let median = bs.ns_iter_summ.median as usize;
-                let deviation = (bs.ns_iter_summ.max - bs.ns_iter_summ.min) as usize;
-
-                let mbps = if bs.mb_s == 0 {
-                    String::new()
-                } else {
-                    format!(r#", "mib_per_second": {}"#, bs.mb_s)
-                };
-
-                let line = format!(
-                    "{{ \"type\": \"bench\", \
-                     \"name\": \"{}\", \
-                     \"median\": {}, \
-                     \"deviation\": {}{} }}",
-                    desc.name, median, deviation, mbps
-                );
-
-                self.write_message(&*line)
-            }
-        }
-    }
-
-    fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()> {
-        self.write_message(&*format!(
-            r#"{{ "type": "test", "event": "timeout", "name": "{}" }}"#,
-            desc.name
-        ))
-    }
-
-    fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result<bool> {
-        self.write_message(&*format!(
-            "{{ \"type\": \"suite\", \
-             \"event\": \"{}\", \
-             \"passed\": {}, \
-             \"failed\": {}, \
-             \"allowed_fail\": {}, \
-             \"ignored\": {}, \
-             \"measured\": {}, \
-             \"filtered_out\": {} }}",
-            if state.failed == 0 { "ok" } else { "failed" },
-            state.passed,
-            state.failed + state.allowed_fail,
-            state.allowed_fail,
-            state.ignored,
-            state.measured,
-            state.filtered_out
-        ))?;
-
-        Ok(state.failed == 0)
-    }
-}
-
-/// A formatting utility used to print strings with characters in need of escaping.
-/// Base code taken form `libserialize::json::escape_str`
-struct EscapedString<S: AsRef<str>>(S);
-
-impl<S: AsRef<str>> ::std::fmt::Display for EscapedString<S> {
-    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
-        let mut start = 0;
-
-        for (i, byte) in self.0.as_ref().bytes().enumerate() {
-            let escaped = match byte {
-                b'"' => "\\\"",
-                b'\\' => "\\\\",
-                b'\x00' => "\\u0000",
-                b'\x01' => "\\u0001",
-                b'\x02' => "\\u0002",
-                b'\x03' => "\\u0003",
-                b'\x04' => "\\u0004",
-                b'\x05' => "\\u0005",
-                b'\x06' => "\\u0006",
-                b'\x07' => "\\u0007",
-                b'\x08' => "\\b",
-                b'\t' => "\\t",
-                b'\n' => "\\n",
-                b'\x0b' => "\\u000b",
-                b'\x0c' => "\\f",
-                b'\r' => "\\r",
-                b'\x0e' => "\\u000e",
-                b'\x0f' => "\\u000f",
-                b'\x10' => "\\u0010",
-                b'\x11' => "\\u0011",
-                b'\x12' => "\\u0012",
-                b'\x13' => "\\u0013",
-                b'\x14' => "\\u0014",
-                b'\x15' => "\\u0015",
-                b'\x16' => "\\u0016",
-                b'\x17' => "\\u0017",
-                b'\x18' => "\\u0018",
-                b'\x19' => "\\u0019",
-                b'\x1a' => "\\u001a",
-                b'\x1b' => "\\u001b",
-                b'\x1c' => "\\u001c",
-                b'\x1d' => "\\u001d",
-                b'\x1e' => "\\u001e",
-                b'\x1f' => "\\u001f",
-                b'\x7f' => "\\u007f",
-                _ => {
-                    continue;
-                }
-            };
-
-            if start < i {
-                f.write_str(&self.0.as_ref()[start..i])?;
-            }
-
-            f.write_str(escaped)?;
-
-            start = i + 1;
-        }
-
-        if start != self.0.as_ref().len() {
-            f.write_str(&self.0.as_ref()[start..])?;
-        }
-
-        Ok(())
-    }
-}
diff --git a/src/libtest/formatters/mod.rs b/src/libtest/formatters/mod.rs
deleted file mode 100644
index be5f6a6..0000000
--- a/src/libtest/formatters/mod.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-use super::*;
-
-mod pretty;
-mod json;
-mod terse;
-
-pub(crate) use self::pretty::PrettyFormatter;
-pub(crate) use self::json::JsonFormatter;
-pub(crate) use self::terse::TerseFormatter;
-
-pub(crate) trait OutputFormatter {
-    fn write_run_start(&mut self, test_count: usize) -> io::Result<()>;
-    fn write_test_start(&mut self, desc: &TestDesc) -> io::Result<()>;
-    fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()>;
-    fn write_result(
-        &mut self,
-        desc: &TestDesc,
-        result: &TestResult,
-        stdout: &[u8],
-    ) -> io::Result<()>;
-    fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result<bool>;
-}
diff --git a/src/libtest/formatters/pretty.rs b/src/libtest/formatters/pretty.rs
deleted file mode 100644
index 4af0042..0000000
--- a/src/libtest/formatters/pretty.rs
+++ /dev/null
@@ -1,232 +0,0 @@
-use super::*;
-
-pub(crate) struct PrettyFormatter<T> {
-    out: OutputLocation<T>,
-    use_color: bool,
-
-    /// Number of columns to fill when aligning names
-    max_name_len: usize,
-
-    is_multithreaded: bool,
-}
-
-impl<T: Write> PrettyFormatter<T> {
-    pub fn new(
-        out: OutputLocation<T>,
-        use_color: bool,
-        max_name_len: usize,
-        is_multithreaded: bool,
-    ) -> Self {
-        PrettyFormatter {
-            out,
-            use_color,
-            max_name_len,
-            is_multithreaded,
-        }
-    }
-
-    #[cfg(test)]
-    pub fn output_location(&self) -> &OutputLocation<T> {
-        &self.out
-    }
-
-    pub fn write_ok(&mut self) -> io::Result<()> {
-        self.write_short_result("ok", term::color::GREEN)
-    }
-
-    pub fn write_failed(&mut self) -> io::Result<()> {
-        self.write_short_result("FAILED", term::color::RED)
-    }
-
-    pub fn write_ignored(&mut self) -> io::Result<()> {
-        self.write_short_result("ignored", term::color::YELLOW)
-    }
-
-    pub fn write_allowed_fail(&mut self) -> io::Result<()> {
-        self.write_short_result("FAILED (allowed)", term::color::YELLOW)
-    }
-
-    pub fn write_bench(&mut self) -> io::Result<()> {
-        self.write_pretty("bench", term::color::CYAN)
-    }
-
-    pub fn write_short_result(
-        &mut self,
-        result: &str,
-        color: term::color::Color,
-    ) -> io::Result<()> {
-        self.write_pretty(result, color)?;
-        self.write_plain("\n")
-    }
-
-    pub fn write_pretty(&mut self, word: &str, color: term::color::Color) -> io::Result<()> {
-        match self.out {
-            Pretty(ref mut term) => {
-                if self.use_color {
-                    term.fg(color)?;
-                }
-                term.write_all(word.as_bytes())?;
-                if self.use_color {
-                    term.reset()?;
-                }
-                term.flush()
-            }
-            Raw(ref mut stdout) => {
-                stdout.write_all(word.as_bytes())?;
-                stdout.flush()
-            }
-        }
-    }
-
-    pub fn write_plain<S: AsRef<str>>(&mut self, s: S) -> io::Result<()> {
-        let s = s.as_ref();
-        self.out.write_all(s.as_bytes())?;
-        self.out.flush()
-    }
-
-    pub fn write_successes(&mut self, state: &ConsoleTestState) -> io::Result<()> {
-        self.write_plain("\nsuccesses:\n")?;
-        let mut successes = Vec::new();
-        let mut stdouts = String::new();
-        for &(ref f, ref stdout) in &state.not_failures {
-            successes.push(f.name.to_string());
-            if !stdout.is_empty() {
-                stdouts.push_str(&format!("---- {} stdout ----\n", f.name));
-                let output = String::from_utf8_lossy(stdout);
-                stdouts.push_str(&output);
-                stdouts.push_str("\n");
-            }
-        }
-        if !stdouts.is_empty() {
-            self.write_plain("\n")?;
-            self.write_plain(&stdouts)?;
-        }
-
-        self.write_plain("\nsuccesses:\n")?;
-        successes.sort();
-        for name in &successes {
-            self.write_plain(&format!("    {}\n", name))?;
-        }
-        Ok(())
-    }
-
-    pub fn write_failures(&mut self, state: &ConsoleTestState) -> io::Result<()> {
-        self.write_plain("\nfailures:\n")?;
-        let mut failures = Vec::new();
-        let mut fail_out = String::new();
-        for &(ref f, ref stdout) in &state.failures {
-            failures.push(f.name.to_string());
-            if !stdout.is_empty() {
-                fail_out.push_str(&format!("---- {} stdout ----\n", f.name));
-                let output = String::from_utf8_lossy(stdout);
-                fail_out.push_str(&output);
-                fail_out.push_str("\n");
-            }
-        }
-        if !fail_out.is_empty() {
-            self.write_plain("\n")?;
-            self.write_plain(&fail_out)?;
-        }
-
-        self.write_plain("\nfailures:\n")?;
-        failures.sort();
-        for name in &failures {
-            self.write_plain(&format!("    {}\n", name))?;
-        }
-        Ok(())
-    }
-
-    fn write_test_name(&mut self, desc: &TestDesc) -> io::Result<()> {
-        let name = desc.padded_name(self.max_name_len, desc.name.padding());
-        self.write_plain(&format!("test {} ... ", name))?;
-
-        Ok(())
-    }
-}
-
-impl<T: Write> OutputFormatter for PrettyFormatter<T> {
-    fn write_run_start(&mut self, test_count: usize) -> io::Result<()> {
-        let noun = if test_count != 1 { "tests" } else { "test" };
-        self.write_plain(&format!("\nrunning {} {}\n", test_count, noun))
-    }
-
-    fn write_test_start(&mut self, desc: &TestDesc) -> io::Result<()> {
-        // When running tests concurrently, we should not print
-        // the test's name as the result will be mis-aligned.
-        // When running the tests serially, we print the name here so
-        // that the user can see which test hangs.
-        if !self.is_multithreaded {
-            self.write_test_name(desc)?;
-        }
-
-        Ok(())
-    }
-
-    fn write_result(&mut self, desc: &TestDesc, result: &TestResult, _: &[u8]) -> io::Result<()> {
-        if self.is_multithreaded {
-            self.write_test_name(desc)?;
-        }
-
-        match *result {
-            TrOk => self.write_ok(),
-            TrFailed | TrFailedMsg(_) => self.write_failed(),
-            TrIgnored => self.write_ignored(),
-            TrAllowedFail => self.write_allowed_fail(),
-            TrBench(ref bs) => {
-                self.write_bench()?;
-                self.write_plain(&format!(": {}\n", fmt_bench_samples(bs)))
-            }
-        }
-    }
-
-    fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()> {
-        if self.is_multithreaded {
-            self.write_test_name(desc)?;
-        }
-
-        self.write_plain(&format!(
-            "test {} has been running for over {} seconds\n",
-            desc.name, TEST_WARN_TIMEOUT_S
-        ))
-    }
-
-    fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result<bool> {
-        if state.options.display_output {
-            self.write_successes(state)?;
-        }
-        let success = state.failed == 0;
-        if !success {
-            self.write_failures(state)?;
-        }
-
-        self.write_plain("\ntest result: ")?;
-
-        if success {
-            // There's no parallelism at this point so it's safe to use color
-            self.write_pretty("ok", term::color::GREEN)?;
-        } else {
-            self.write_pretty("FAILED", term::color::RED)?;
-        }
-
-        let s = if state.allowed_fail > 0 {
-            format!(
-                ". {} passed; {} failed ({} allowed); {} ignored; {} measured; {} filtered out\n\n",
-                state.passed,
-                state.failed + state.allowed_fail,
-                state.allowed_fail,
-                state.ignored,
-                state.measured,
-                state.filtered_out
-            )
-        } else {
-            format!(
-                ". {} passed; {} failed; {} ignored; {} measured; {} filtered out\n\n",
-                state.passed, state.failed, state.ignored, state.measured, state.filtered_out
-            )
-        };
-
-        self.write_plain(&s)?;
-
-        Ok(success)
-    }
-}
diff --git a/src/libtest/formatters/terse.rs b/src/libtest/formatters/terse.rs
deleted file mode 100644
index 1400fba..0000000
--- a/src/libtest/formatters/terse.rs
+++ /dev/null
@@ -1,235 +0,0 @@
-use super::*;
-
-pub(crate) struct TerseFormatter<T> {
-    out: OutputLocation<T>,
-    use_color: bool,
-    is_multithreaded: bool,
-    /// Number of columns to fill when aligning names
-    max_name_len: usize,
-
-    test_count: usize,
-    total_test_count: usize,
-}
-
-impl<T: Write> TerseFormatter<T> {
-    pub fn new(
-        out: OutputLocation<T>,
-        use_color: bool,
-        max_name_len: usize,
-        is_multithreaded: bool,
-    ) -> Self {
-        TerseFormatter {
-            out,
-            use_color,
-            max_name_len,
-            is_multithreaded,
-            test_count: 0,
-            total_test_count: 0, // initialized later, when write_run_start is called
-        }
-    }
-
-    pub fn write_ok(&mut self) -> io::Result<()> {
-        self.write_short_result(".", term::color::GREEN)
-    }
-
-    pub fn write_failed(&mut self) -> io::Result<()> {
-        self.write_short_result("F", term::color::RED)
-    }
-
-    pub fn write_ignored(&mut self) -> io::Result<()> {
-        self.write_short_result("i", term::color::YELLOW)
-    }
-
-    pub fn write_allowed_fail(&mut self) -> io::Result<()> {
-        self.write_short_result("a", term::color::YELLOW)
-    }
-
-    pub fn write_bench(&mut self) -> io::Result<()> {
-        self.write_pretty("bench", term::color::CYAN)
-    }
-
-    pub fn write_short_result(
-        &mut self,
-        result: &str,
-        color: term::color::Color,
-    ) -> io::Result<()> {
-        self.write_pretty(result, color)?;
-        if self.test_count % QUIET_MODE_MAX_COLUMN == QUIET_MODE_MAX_COLUMN - 1 {
-            // we insert a new line every 100 dots in order to flush the
-            // screen when dealing with line-buffered output (e.g., piping to
-            // `stamp` in the rust CI).
-            let out = format!(" {}/{}\n", self.test_count+1, self.total_test_count);
-            self.write_plain(&out)?;
-        }
-
-        self.test_count += 1;
-        Ok(())
-    }
-
-    pub fn write_pretty(&mut self, word: &str, color: term::color::Color) -> io::Result<()> {
-        match self.out {
-            Pretty(ref mut term) => {
-                if self.use_color {
-                    term.fg(color)?;
-                }
-                term.write_all(word.as_bytes())?;
-                if self.use_color {
-                    term.reset()?;
-                }
-                term.flush()
-            }
-            Raw(ref mut stdout) => {
-                stdout.write_all(word.as_bytes())?;
-                stdout.flush()
-            }
-        }
-    }
-
-    pub fn write_plain<S: AsRef<str>>(&mut self, s: S) -> io::Result<()> {
-        let s = s.as_ref();
-        self.out.write_all(s.as_bytes())?;
-        self.out.flush()
-    }
-
-    pub fn write_outputs(&mut self, state: &ConsoleTestState) -> io::Result<()> {
-        self.write_plain("\nsuccesses:\n")?;
-        let mut successes = Vec::new();
-        let mut stdouts = String::new();
-        for &(ref f, ref stdout) in &state.not_failures {
-            successes.push(f.name.to_string());
-            if !stdout.is_empty() {
-                stdouts.push_str(&format!("---- {} stdout ----\n", f.name));
-                let output = String::from_utf8_lossy(stdout);
-                stdouts.push_str(&output);
-                stdouts.push_str("\n");
-            }
-        }
-        if !stdouts.is_empty() {
-            self.write_plain("\n")?;
-            self.write_plain(&stdouts)?;
-        }
-
-        self.write_plain("\nsuccesses:\n")?;
-        successes.sort();
-        for name in &successes {
-            self.write_plain(&format!("    {}\n", name))?;
-        }
-        Ok(())
-    }
-
-    pub fn write_failures(&mut self, state: &ConsoleTestState) -> io::Result<()> {
-        self.write_plain("\nfailures:\n")?;
-        let mut failures = Vec::new();
-        let mut fail_out = String::new();
-        for &(ref f, ref stdout) in &state.failures {
-            failures.push(f.name.to_string());
-            if !stdout.is_empty() {
-                fail_out.push_str(&format!("---- {} stdout ----\n", f.name));
-                let output = String::from_utf8_lossy(stdout);
-                fail_out.push_str(&output);
-                fail_out.push_str("\n");
-            }
-        }
-        if !fail_out.is_empty() {
-            self.write_plain("\n")?;
-            self.write_plain(&fail_out)?;
-        }
-
-        self.write_plain("\nfailures:\n")?;
-        failures.sort();
-        for name in &failures {
-            self.write_plain(&format!("    {}\n", name))?;
-        }
-        Ok(())
-    }
-
-    fn write_test_name(&mut self, desc: &TestDesc) -> io::Result<()> {
-        let name = desc.padded_name(self.max_name_len, desc.name.padding());
-        self.write_plain(&format!("test {} ... ", name))?;
-
-        Ok(())
-    }
-}
-
-impl<T: Write> OutputFormatter for TerseFormatter<T> {
-    fn write_run_start(&mut self, test_count: usize) -> io::Result<()> {
-        self.total_test_count = test_count;
-        let noun = if test_count != 1 { "tests" } else { "test" };
-        self.write_plain(&format!("\nrunning {} {}\n", test_count, noun))
-    }
-
-    fn write_test_start(&mut self, desc: &TestDesc) -> io::Result<()> {
-        // Remnants from old libtest code that used the padding value
-        // in order to indicate benchmarks.
-        // When running benchmarks, terse-mode should still print their name as if
-        // it is the Pretty formatter.
-        if !self.is_multithreaded && desc.name.padding() == PadOnRight {
-            self.write_test_name(desc)?;
-        }
-
-        Ok(())
-    }
-
-    fn write_result(&mut self, desc: &TestDesc, result: &TestResult, _: &[u8]) -> io::Result<()> {
-        match *result {
-            TrOk => self.write_ok(),
-            TrFailed | TrFailedMsg(_) => self.write_failed(),
-            TrIgnored => self.write_ignored(),
-            TrAllowedFail => self.write_allowed_fail(),
-            TrBench(ref bs) => {
-                if self.is_multithreaded {
-                    self.write_test_name(desc)?;
-                }
-                self.write_bench()?;
-                self.write_plain(&format!(": {}\n", fmt_bench_samples(bs)))
-            }
-        }
-    }
-
-    fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()> {
-        self.write_plain(&format!(
-            "test {} has been running for over {} seconds\n",
-            desc.name, TEST_WARN_TIMEOUT_S
-        ))
-    }
-
-    fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result<bool> {
-        if state.options.display_output {
-            self.write_outputs(state)?;
-        }
-        let success = state.failed == 0;
-        if !success {
-            self.write_failures(state)?;
-        }
-
-        self.write_plain("\ntest result: ")?;
-
-        if success {
-            // There's no parallelism at this point so it's safe to use color
-            self.write_pretty("ok", term::color::GREEN)?;
-        } else {
-            self.write_pretty("FAILED", term::color::RED)?;
-        }
-
-        let s = if state.allowed_fail > 0 {
-            format!(
-                ". {} passed; {} failed ({} allowed); {} ignored; {} measured; {} filtered out\n\n",
-                state.passed,
-                state.failed + state.allowed_fail,
-                state.allowed_fail,
-                state.ignored,
-                state.measured,
-                state.filtered_out
-            )
-        } else {
-            format!(
-                ". {} passed; {} failed; {} ignored; {} measured; {} filtered out\n\n",
-                state.passed, state.failed, state.ignored, state.measured, state.filtered_out
-            )
-        };
-
-        self.write_plain(&s)?;
-
-        Ok(success)
-    }
-}
diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs
index ea821a1..3fcba0f 100644
--- a/src/libtest/lib.rs
+++ b/src/libtest/lib.rs
@@ -8,1582 +8,24 @@
 //!
 //! See the [Testing Chapter](../book/ch11-00-testing.html) of the book for more details.
 
-// Currently, not much of this is meant for users. It is intended to
-// support the simplest interface possible for representing and
-// running tests while providing a base that other test frameworks may
-// build off of.
-
-// N.B., this is also specified in this crate's Cargo.toml, but libsyntax contains logic specific to
-// this crate, which relies on this attribute (rather than the value of `--crate-name` passed by
-// cargo) to detect this crate.
-
-#![deny(rust_2018_idioms)]
 #![crate_name = "test"]
 #![unstable(feature = "test", issue = "27812")]
-#![doc(html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))]
+#![doc(html_root_url = "https://doc.rust-lang.org/nightly/",
+       test(attr(deny(warnings))))]
 #![feature(asm)]
-#![feature(fnbox)]
-#![cfg_attr(any(unix, target_os = "cloudabi"), feature(libc, rustc_private))]
-#![feature(nll)]
-#![feature(set_stdio)]
-#![feature(panic_unwind)]
 #![feature(staged_api)]
-#![feature(termination_trait_lib)]
 #![feature(test)]
 
-use getopts;
-#[cfg(any(unix, target_os = "cloudabi"))]
-extern crate libc;
-use term;
+extern crate libtest;
 
-// FIXME(#54291): rustc and/or LLVM don't yet support building with panic-unwind
-//                on aarch64-pc-windows-msvc, so we don't link libtest against
-//                libunwind (for the time being), even though it means that
-//                libtest won't be fully functional on this platform.
-//
-// See also: https://github.com/rust-lang/rust/issues/54190#issuecomment-422904437
-#[cfg(not(all(windows, target_arch = "aarch64")))]
-extern crate panic_unwind;
-
-pub use self::ColorConfig::*;
-use self::NamePadding::*;
-use self::OutputLocation::*;
-use self::TestEvent::*;
-pub use self::TestFn::*;
-pub use self::TestName::*;
-pub use self::TestResult::*;
-
-use std::any::Any;
-use std::borrow::Cow;
-use std::boxed::FnBox;
-use std::cmp;
-use std::collections::BTreeMap;
-use std::env;
-use std::fmt;
-use std::fs::File;
-use std::io;
-use std::io::prelude::*;
-use std::panic::{catch_unwind, AssertUnwindSafe};
-use std::path::PathBuf;
-use std::process;
-use std::process::Termination;
-use std::sync::mpsc::{channel, Sender};
-use std::sync::{Arc, Mutex};
-use std::thread;
-use std::time::{Duration, Instant};
-
-const TEST_WARN_TIMEOUT_S: u64 = 60;
-const QUIET_MODE_MAX_COLUMN: usize = 100; // insert a '\n' after 100 tests in quiet mode
-
-// to be used by rustc to compile tests in libtest
-pub mod test {
-    pub use crate::{
-        assert_test_result, filter_tests, parse_opts, run_test, test_main, test_main_static,
-        Bencher, DynTestFn, DynTestName, Metric, MetricMap, Options, RunIgnored, ShouldPanic,
-        StaticBenchFn, StaticTestFn, StaticTestName, TestDesc, TestDescAndFn, TestName, TestOpts,
-        TestResult, TrFailed, TrFailedMsg, TrIgnored, TrOk,
-    };
-}
-
-mod formatters;
-pub mod stats;
-
-use crate::formatters::{JsonFormatter, OutputFormatter, PrettyFormatter, TerseFormatter};
-
-/// Whether to execute tests concurrently or not
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub enum Concurrent {
-    Yes,
-    No,
-}
-
-// The name of a test. By convention this follows the rules for rust
-// paths; i.e., it should be a series of identifiers separated by double
-// colons. This way if some test runner wants to arrange the tests
-// hierarchically it may.
-
-#[derive(Clone, PartialEq, Eq, Hash, Debug)]
-pub enum TestName {
-    StaticTestName(&'static str),
-    DynTestName(String),
-    AlignedTestName(Cow<'static, str>, NamePadding),
-}
-impl TestName {
-    fn as_slice(&self) -> &str {
-        match *self {
-            StaticTestName(s) => s,
-            DynTestName(ref s) => s,
-            AlignedTestName(ref s, _) => &*s,
-        }
-    }
-
-    fn padding(&self) -> NamePadding {
-        match self {
-            &AlignedTestName(_, p) => p,
-            _ => PadNone,
-        }
-    }
-
-    fn with_padding(&self, padding: NamePadding) -> TestName {
-        let name = match self {
-            &TestName::StaticTestName(name) => Cow::Borrowed(name),
-            &TestName::DynTestName(ref name) => Cow::Owned(name.clone()),
-            &TestName::AlignedTestName(ref name, _) => name.clone(),
-        };
-
-        TestName::AlignedTestName(name, padding)
-    }
-}
-impl fmt::Display for TestName {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Display::fmt(self.as_slice(), f)
-    }
-}
-
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
-pub enum NamePadding {
-    PadNone,
-    PadOnRight,
-}
-
-impl TestDesc {
-    fn padded_name(&self, column_count: usize, align: NamePadding) -> String {
-        let mut name = String::from(self.name.as_slice());
-        let fill = column_count.saturating_sub(name.len());
-        let pad = " ".repeat(fill);
-        match align {
-            PadNone => name,
-            PadOnRight => {
-                name.push_str(&pad);
-                name
-            }
-        }
-    }
-}
-
-/// Represents a benchmark function.
-pub trait TDynBenchFn: Send {
-    fn run(&self, harness: &mut Bencher);
-}
-
-// A function that runs a test. If the function returns successfully,
-// the test succeeds; if the function panics then the test fails. We
-// may need to come up with a more clever definition of test in order
-// to support isolation of tests into threads.
-pub enum TestFn {
-    StaticTestFn(fn()),
-    StaticBenchFn(fn(&mut Bencher)),
-    DynTestFn(Box<dyn FnBox() + Send>),
-    DynBenchFn(Box<dyn TDynBenchFn + 'static>),
-}
-
-impl TestFn {
-    fn padding(&self) -> NamePadding {
-        match *self {
-            StaticTestFn(..) => PadNone,
-            StaticBenchFn(..) => PadOnRight,
-            DynTestFn(..) => PadNone,
-            DynBenchFn(..) => PadOnRight,
-        }
-    }
-}
-
-impl fmt::Debug for TestFn {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.write_str(match *self {
-            StaticTestFn(..) => "StaticTestFn(..)",
-            StaticBenchFn(..) => "StaticBenchFn(..)",
-            DynTestFn(..) => "DynTestFn(..)",
-            DynBenchFn(..) => "DynBenchFn(..)",
-        })
-    }
-}
-
-/// Manager of the benchmarking runs.
-///
-/// This is fed into functions marked with `#[bench]` to allow for
-/// set-up & tear-down before running a piece of code repeatedly via a
-/// call to `iter`.
-#[derive(Clone)]
-pub struct Bencher {
-    mode: BenchMode,
-    summary: Option<stats::Summary>,
-    pub bytes: u64,
-}
-
-#[derive(Clone, PartialEq, Eq)]
-pub enum BenchMode {
-    Auto,
-    Single,
-}
-
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
-pub enum ShouldPanic {
-    No,
-    Yes,
-    YesWithMessage(&'static str),
-}
-
-// The definition of a single test. A test runner will run a list of
-// these.
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
-pub struct TestDesc {
-    pub name: TestName,
-    pub ignore: bool,
-    pub should_panic: ShouldPanic,
-    pub allow_fail: bool,
-}
-
-#[derive(Debug)]
-pub struct TestDescAndFn {
-    pub desc: TestDesc,
-    pub testfn: TestFn,
-}
-
-#[derive(Clone, PartialEq, Debug, Copy)]
-pub struct Metric {
-    value: f64,
-    noise: f64,
-}
-
-impl Metric {
-    pub fn new(value: f64, noise: f64) -> Metric {
-        Metric { value, noise }
-    }
-}
-
-/// In case we want to add other options as well, just add them in this struct.
-#[derive(Copy, Clone, Debug)]
-pub struct Options {
-    display_output: bool,
-}
-
-impl Options {
-    pub fn new() -> Options {
-        Options {
-            display_output: false,
-        }
-    }
-
-    pub fn display_output(mut self, display_output: bool) -> Options {
-        self.display_output = display_output;
-        self
-    }
-}
-
-// The default console test runner. It accepts the command line
-// arguments and a vector of test_descs.
-pub fn test_main(args: &[String], tests: Vec<TestDescAndFn>, options: Options) {
-    let mut opts = match parse_opts(args) {
-        Some(Ok(o)) => o,
-        Some(Err(msg)) => {
-            eprintln!("error: {}", msg);
-            process::exit(101);
-        }
-        None => return,
-    };
-
-    opts.options = options;
-    if opts.list {
-        if let Err(e) = list_tests_console(&opts, tests) {
-            eprintln!("error: io error when listing tests: {:?}", e);
-            process::exit(101);
-        }
-    } else {
-        match run_tests_console(&opts, tests) {
-            Ok(true) => {}
-            Ok(false) => process::exit(101),
-            Err(e) => {
-                eprintln!("error: io error when listing tests: {:?}", e);
-                process::exit(101);
-            }
-        }
-    }
-}
-
-// A variant optimized for invocation with a static test vector.
-// This will panic (intentionally) when fed any dynamic tests, because
-// it is copying the static values out into a dynamic vector and cannot
-// copy dynamic values. It is doing this because from this point on
-// a Vec<TestDescAndFn> is used in order to effect ownership-transfer
-// semantics into parallel test runners, which in turn requires a Vec<>
-// rather than a &[].
-pub fn test_main_static(tests: &[&TestDescAndFn]) {
-    let args = env::args().collect::<Vec<_>>();
-    let owned_tests = tests
-        .iter()
-        .map(|t| match t.testfn {
-            StaticTestFn(f) => TestDescAndFn {
-                testfn: StaticTestFn(f),
-                desc: t.desc.clone(),
-            },
-            StaticBenchFn(f) => TestDescAndFn {
-                testfn: StaticBenchFn(f),
-                desc: t.desc.clone(),
-            },
-            _ => panic!("non-static tests passed to test::test_main_static"),
-        })
-        .collect();
-    test_main(&args, owned_tests, Options::new())
-}
-
-/// Invoked when unit tests terminate. Should panic if the unit
-/// Tests is considered a failure. By default, invokes `report()`
-/// and checks for a `0` result.
-pub fn assert_test_result<T: Termination>(result: T) {
-    let code = result.report();
-    assert_eq!(
-        code, 0,
-        "the test returned a termination value with a non-zero status code ({}) \
-         which indicates a failure",
-        code
-    );
-}
-
-#[derive(Copy, Clone, Debug)]
-pub enum ColorConfig {
-    AutoColor,
-    AlwaysColor,
-    NeverColor,
-}
-
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub enum OutputFormat {
-    Pretty,
-    Terse,
-    Json,
-}
-
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub enum RunIgnored {
-    Yes,
-    No,
-    Only,
-}
-
-#[derive(Debug)]
-pub struct TestOpts {
-    pub list: bool,
-    pub filter: Option<String>,
-    pub filter_exact: bool,
-    pub exclude_should_panic: bool,
-    pub run_ignored: RunIgnored,
-    pub run_tests: bool,
-    pub bench_benchmarks: bool,
-    pub logfile: Option<PathBuf>,
-    pub nocapture: bool,
-    pub color: ColorConfig,
-    pub format: OutputFormat,
-    pub test_threads: Option<usize>,
-    pub skip: Vec<String>,
-    pub options: Options,
-}
-
-impl TestOpts {
-    #[cfg(test)]
-    fn new() -> TestOpts {
-        TestOpts {
-            list: false,
-            filter: None,
-            filter_exact: false,
-            exclude_should_panic: false,
-            run_ignored: RunIgnored::No,
-            run_tests: false,
-            bench_benchmarks: false,
-            logfile: None,
-            nocapture: false,
-            color: AutoColor,
-            format: OutputFormat::Pretty,
-            test_threads: None,
-            skip: vec![],
-            options: Options::new(),
-        }
-    }
-}
-
-/// Result of parsing the options.
-pub type OptRes = Result<TestOpts, String>;
-
-fn optgroups() -> getopts::Options {
-    let mut opts = getopts::Options::new();
-    opts.optflag("", "include-ignored", "Run ignored and not ignored tests")
-        .optflag("", "ignored", "Run only ignored tests")
-        .optflag("", "exclude-should-panic", "Excludes tests marked as should_panic")
-        .optflag("", "test", "Run tests and not benchmarks")
-        .optflag("", "bench", "Run benchmarks instead of tests")
-        .optflag("", "list", "List all tests and benchmarks")
-        .optflag("h", "help", "Display this message (longer with --help)")
-        .optopt(
-            "",
-            "logfile",
-            "Write logs to the specified file instead \
-             of stdout",
-            "PATH",
-        )
-        .optflag(
-            "",
-            "nocapture",
-            "don't capture stdout/stderr of each \
-             task, allow printing directly",
-        )
-        .optopt(
-            "",
-            "test-threads",
-            "Number of threads used for running tests \
-             in parallel",
-            "n_threads",
-        )
-        .optmulti(
-            "",
-            "skip",
-            "Skip tests whose names contain FILTER (this flag can \
-             be used multiple times)",
-            "FILTER",
-        )
-        .optflag(
-            "q",
-            "quiet",
-            "Display one character per test instead of one line. \
-             Alias to --format=terse",
-        )
-        .optflag(
-            "",
-            "exact",
-            "Exactly match filters rather than by substring",
-        )
-        .optopt(
-            "",
-            "color",
-            "Configure coloring of output:
-            auto   = colorize if stdout is a tty and tests are run on serially (default);
-            always = always colorize output;
-            never  = never colorize output;",
-            "auto|always|never",
-        )
-        .optopt(
-            "",
-            "format",
-            "Configure formatting of output:
-            pretty = Print verbose output;
-            terse  = Display one character per test;
-            json   = Output a json document",
-            "pretty|terse|json",
-        )
-        .optopt(
-            "Z",
-            "",
-            "Enable nightly-only flags:
-            unstable-options = Allow use of experimental features",
-            "unstable-options",
-        );
-    return opts;
-}
-
-fn usage(binary: &str, options: &getopts::Options) {
-    let message = format!("Usage: {} [OPTIONS] [FILTER]", binary);
-    println!(
-        r#"{usage}
-
-The FILTER string is tested against the name of all tests, and only those
-tests whose names contain the filter are run.
-
-By default, all tests are run in parallel. This can be altered with the
---test-threads flag or the RUST_TEST_THREADS environment variable when running
-tests (set it to 1).
-
-All tests have their standard output and standard error captured by default.
-This can be overridden with the --nocapture flag or setting RUST_TEST_NOCAPTURE
-environment variable to a value other than "0". Logging is not captured by default.
-
-Test Attributes:
-
-    #[test]        - Indicates a function is a test to be run. This function
-                     takes no arguments.
-    #[bench]       - Indicates a function is a benchmark to be run. This
-                     function takes one argument (test::Bencher).
-    #[should_panic] - This function (also labeled with #[test]) will only pass if
-                     the code causes a panic (an assertion failure or panic!)
-                     A message may be provided, which the failure string must
-                     contain: #[should_panic(expected = "foo")].
-    #[ignore]      - When applied to a function which is already attributed as a
-                     test, then the test runner will ignore these tests during
-                     normal test runs. Running with --ignored or --include-ignored will run
-                     these tests."#,
-        usage = options.usage(&message)
-    );
-}
-
-// FIXME: Copied from libsyntax until linkage errors are resolved. Issue #47566
-fn is_nightly() -> bool {
-    // Whether this is a feature-staged build, i.e., on the beta or stable channel
-    let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
-    // Whether we should enable unstable features for bootstrapping
-    let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok();
-
-    bootstrap || !disable_unstable_features
-}
-
-// Parses command line arguments into test options
-pub fn parse_opts(args: &[String]) -> Option<OptRes> {
-    let mut allow_unstable = false;
-    let opts = optgroups();
-    let args = args.get(1..).unwrap_or(args);
-    let matches = match opts.parse(args) {
-        Ok(m) => m,
-        Err(f) => return Some(Err(f.to_string())),
-    };
-
-    if let Some(opt) = matches.opt_str("Z") {
-        if !is_nightly() {
-            return Some(Err(
-                "the option `Z` is only accepted on the nightly compiler".into(),
-            ));
-        }
-
-        match &*opt {
-            "unstable-options" => {
-                allow_unstable = true;
-            }
-            _ => {
-                return Some(Err("Unrecognized option to `Z`".into()));
-            }
-        }
-    };
-
-    if matches.opt_present("h") {
-        usage(&args[0], &opts);
-        return None;
-    }
-
-    let filter = if !matches.free.is_empty() {
-        Some(matches.free[0].clone())
-    } else {
-        None
-    };
-
-    let exclude_should_panic = matches.opt_present("exclude-should-panic");
-    if !allow_unstable && exclude_should_panic {
-        return Some(Err(
-            "The \"exclude-should-panic\" flag is only accepted on the nightly compiler".into(),
-        ));
-    }
-
-    let include_ignored = matches.opt_present("include-ignored");
-    if !allow_unstable && include_ignored {
-        return Some(Err(
-            "The \"include-ignored\" flag is only accepted on the nightly compiler".into(),
-        ));
-    }
-
-    let run_ignored = match (include_ignored, matches.opt_present("ignored")) {
-        (true, true) => {
-            return Some(Err(
-                "the options --include-ignored and --ignored are mutually exclusive".into(),
-            ));
-        }
-        (true, false) => RunIgnored::Yes,
-        (false, true) => RunIgnored::Only,
-        (false, false) => RunIgnored::No,
-    };
-    let quiet = matches.opt_present("quiet");
-    let exact = matches.opt_present("exact");
-    let list = matches.opt_present("list");
-
-    let logfile = matches.opt_str("logfile");
-    let logfile = logfile.map(|s| PathBuf::from(&s));
-
-    let bench_benchmarks = matches.opt_present("bench");
-    let run_tests = !bench_benchmarks || matches.opt_present("test");
-
-    let mut nocapture = matches.opt_present("nocapture");
-    if !nocapture {
-        nocapture = match env::var("RUST_TEST_NOCAPTURE") {
-            Ok(val) => &val != "0",
-            Err(_) => false,
-        };
-    }
-
-    let test_threads = match matches.opt_str("test-threads") {
-        Some(n_str) => match n_str.parse::<usize>() {
-            Ok(0) => return Some(Err("argument for --test-threads must not be 0".to_string())),
-            Ok(n) => Some(n),
-            Err(e) => {
-                return Some(Err(format!(
-                    "argument for --test-threads must be a number > 0 \
-                     (error: {})",
-                    e
-                )));
-            }
-        },
-        None => None,
-    };
-
-    let color = match matches.opt_str("color").as_ref().map(|s| &**s) {
-        Some("auto") | None => AutoColor,
-        Some("always") => AlwaysColor,
-        Some("never") => NeverColor,
-
-        Some(v) => {
-            return Some(Err(format!(
-                "argument for --color must be auto, always, or never (was \
-                 {})",
-                v
-            )));
-        }
-    };
-
-    let format = match matches.opt_str("format").as_ref().map(|s| &**s) {
-        None if quiet => OutputFormat::Terse,
-        Some("pretty") | None => OutputFormat::Pretty,
-        Some("terse") => OutputFormat::Terse,
-        Some("json") => {
-            if !allow_unstable {
-                return Some(Err(
-                    "The \"json\" format is only accepted on the nightly compiler".into(),
-                ));
-            }
-            OutputFormat::Json
-        }
-
-        Some(v) => {
-            return Some(Err(format!(
-                "argument for --format must be pretty, terse, or json (was \
-                 {})",
-                v
-            )));
-        }
-    };
-
-    let test_opts = TestOpts {
-        list,
-        filter,
-        filter_exact: exact,
-        exclude_should_panic,
-        run_ignored,
-        run_tests,
-        bench_benchmarks,
-        logfile,
-        nocapture,
-        color,
-        format,
-        test_threads,
-        skip: matches.opt_strs("skip"),
-        options: Options::new(),
-    };
-
-    Some(Ok(test_opts))
-}
-
-#[derive(Clone, PartialEq)]
-pub struct BenchSamples {
-    ns_iter_summ: stats::Summary,
-    mb_s: usize,
-}
-
-#[derive(Clone, PartialEq)]
-pub enum TestResult {
-    TrOk,
-    TrFailed,
-    TrFailedMsg(String),
-    TrIgnored,
-    TrAllowedFail,
-    TrBench(BenchSamples),
-}
-
-unsafe impl Send for TestResult {}
-
-enum OutputLocation<T> {
-    Pretty(Box<term::StdoutTerminal>),
-    Raw(T),
-}
-
-impl<T: Write> Write for OutputLocation<T> {
-    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        match *self {
-            Pretty(ref mut term) => term.write(buf),
-            Raw(ref mut stdout) => stdout.write(buf),
-        }
-    }
-
-    fn flush(&mut self) -> io::Result<()> {
-        match *self {
-            Pretty(ref mut term) => term.flush(),
-            Raw(ref mut stdout) => stdout.flush(),
-        }
-    }
-}
-
-struct ConsoleTestState {
-    log_out: Option<File>,
-    total: usize,
-    passed: usize,
-    failed: usize,
-    ignored: usize,
-    allowed_fail: usize,
-    filtered_out: usize,
-    measured: usize,
-    metrics: MetricMap,
-    failures: Vec<(TestDesc, Vec<u8>)>,
-    not_failures: Vec<(TestDesc, Vec<u8>)>,
-    options: Options,
-}
-
-impl ConsoleTestState {
-    pub fn new(opts: &TestOpts) -> io::Result<ConsoleTestState> {
-        let log_out = match opts.logfile {
-            Some(ref path) => Some(File::create(path)?),
-            None => None,
-        };
-
-        Ok(ConsoleTestState {
-            log_out,
-            total: 0,
-            passed: 0,
-            failed: 0,
-            ignored: 0,
-            allowed_fail: 0,
-            filtered_out: 0,
-            measured: 0,
-            metrics: MetricMap::new(),
-            failures: Vec::new(),
-            not_failures: Vec::new(),
-            options: opts.options,
-        })
-    }
-
-    pub fn write_log<S: AsRef<str>>(&mut self, msg: S) -> io::Result<()> {
-        let msg = msg.as_ref();
-        match self.log_out {
-            None => Ok(()),
-            Some(ref mut o) => o.write_all(msg.as_bytes()),
-        }
-    }
-
-    pub fn write_log_result(&mut self, test: &TestDesc, result: &TestResult) -> io::Result<()> {
-        self.write_log(format!(
-            "{} {}\n",
-            match *result {
-                TrOk => "ok".to_owned(),
-                TrFailed => "failed".to_owned(),
-                TrFailedMsg(ref msg) => format!("failed: {}", msg),
-                TrIgnored => "ignored".to_owned(),
-                TrAllowedFail => "failed (allowed)".to_owned(),
-                TrBench(ref bs) => fmt_bench_samples(bs),
-            },
-            test.name
-        ))
-    }
-
-    fn current_test_count(&self) -> usize {
-        self.passed + self.failed + self.ignored + self.measured + self.allowed_fail
-    }
-}
-
-// Format a number with thousands separators
-fn fmt_thousands_sep(mut n: usize, sep: char) -> String {
-    use std::fmt::Write;
-    let mut output = String::new();
-    let mut trailing = false;
-    for &pow in &[9, 6, 3, 0] {
-        let base = 10_usize.pow(pow);
-        if pow == 0 || trailing || n / base != 0 {
-            if !trailing {
-                output.write_fmt(format_args!("{}", n / base)).unwrap();
-            } else {
-                output.write_fmt(format_args!("{:03}", n / base)).unwrap();
-            }
-            if pow != 0 {
-                output.push(sep);
-            }
-            trailing = true;
-        }
-        n %= base;
-    }
-
-    output
-}
-
-pub fn fmt_bench_samples(bs: &BenchSamples) -> String {
-    use std::fmt::Write;
-    let mut output = String::new();
-
-    let median = bs.ns_iter_summ.median as usize;
-    let deviation = (bs.ns_iter_summ.max - bs.ns_iter_summ.min) as usize;
-
-    output
-        .write_fmt(format_args!(
-            "{:>11} ns/iter (+/- {})",
-            fmt_thousands_sep(median, ','),
-            fmt_thousands_sep(deviation, ',')
-        ))
-        .unwrap();
-    if bs.mb_s != 0 {
-        output
-            .write_fmt(format_args!(" = {} MB/s", bs.mb_s))
-            .unwrap();
-    }
-    output
-}
-
-// List the tests to console, and optionally to logfile. Filters are honored.
-pub fn list_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Result<()> {
-    let mut output = match term::stdout() {
-        None => Raw(io::stdout()),
-        Some(t) => Pretty(t),
-    };
-
-    let quiet = opts.format == OutputFormat::Terse;
-    let mut st = ConsoleTestState::new(opts)?;
-
-    let mut ntest = 0;
-    let mut nbench = 0;
-
-    for test in filter_tests(&opts, tests) {
-        use crate::TestFn::*;
-
-        let TestDescAndFn {
-            desc: TestDesc { name, .. },
-            testfn,
-        } = test;
-
-        let fntype = match testfn {
-            StaticTestFn(..) | DynTestFn(..) => {
-                ntest += 1;
-                "test"
-            }
-            StaticBenchFn(..) | DynBenchFn(..) => {
-                nbench += 1;
-                "benchmark"
-            }
-        };
-
-        writeln!(output, "{}: {}", name, fntype)?;
-        st.write_log(format!("{} {}\n", fntype, name))?;
-    }
-
-    fn plural(count: u32, s: &str) -> String {
-        match count {
-            1 => format!("{} {}", 1, s),
-            n => format!("{} {}s", n, s),
-        }
-    }
-
-    if !quiet {
-        if ntest != 0 || nbench != 0 {
-            writeln!(output, "")?;
-        }
-
-        writeln!(
-            output,
-            "{}, {}",
-            plural(ntest, "test"),
-            plural(nbench, "benchmark")
-        )?;
-    }
-
-    Ok(())
-}
-
-// A simple console test runner
-pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Result<bool> {
-    fn callback(
-        event: &TestEvent,
-        st: &mut ConsoleTestState,
-        out: &mut dyn OutputFormatter,
-    ) -> io::Result<()> {
-        match (*event).clone() {
-            TeFiltered(ref filtered_tests) => {
-                st.total = filtered_tests.len();
-                out.write_run_start(filtered_tests.len())
-            }
-            TeFilteredOut(filtered_out) => Ok(st.filtered_out = filtered_out),
-            TeWait(ref test) => out.write_test_start(test),
-            TeTimeout(ref test) => out.write_timeout(test),
-            TeResult(test, result, stdout) => {
-                st.write_log_result(&test, &result)?;
-                out.write_result(&test, &result, &*stdout)?;
-                match result {
-                    TrOk => {
-                        st.passed += 1;
-                        st.not_failures.push((test, stdout));
-                    }
-                    TrIgnored => st.ignored += 1,
-                    TrAllowedFail => st.allowed_fail += 1,
-                    TrBench(bs) => {
-                        st.metrics.insert_metric(
-                            test.name.as_slice(),
-                            bs.ns_iter_summ.median,
-                            bs.ns_iter_summ.max - bs.ns_iter_summ.min,
-                        );
-                        st.measured += 1
-                    }
-                    TrFailed => {
-                        st.failed += 1;
-                        st.failures.push((test, stdout));
-                    }
-                    TrFailedMsg(msg) => {
-                        st.failed += 1;
-                        let mut stdout = stdout;
-                        stdout.extend_from_slice(format!("note: {}", msg).as_bytes());
-                        st.failures.push((test, stdout));
-                    }
-                }
-                Ok(())
-            }
-        }
-    }
-
-    let output = match term::stdout() {
-        None => Raw(io::stdout()),
-        Some(t) => Pretty(t),
-    };
-
-    let max_name_len = tests
-        .iter()
-        .max_by_key(|t| len_if_padded(*t))
-        .map(|t| t.desc.name.as_slice().len())
-        .unwrap_or(0);
-
-    let is_multithreaded = opts.test_threads.unwrap_or_else(get_concurrency) > 1;
-
-    let mut out: Box<dyn OutputFormatter> = match opts.format {
-        OutputFormat::Pretty => Box::new(PrettyFormatter::new(
-            output,
-            use_color(opts),
-            max_name_len,
-            is_multithreaded,
-        )),
-        OutputFormat::Terse => Box::new(TerseFormatter::new(
-            output,
-            use_color(opts),
-            max_name_len,
-            is_multithreaded,
-        )),
-        OutputFormat::Json => Box::new(JsonFormatter::new(output)),
-    };
-    let mut st = ConsoleTestState::new(opts)?;
-    fn len_if_padded(t: &TestDescAndFn) -> usize {
-        match t.testfn.padding() {
-            PadNone => 0,
-            PadOnRight => t.desc.name.as_slice().len(),
-        }
-    }
-
-    run_tests(opts, tests, |x| callback(&x, &mut st, &mut *out))?;
-
-    assert!(st.current_test_count() == st.total);
-
-    return out.write_run_finish(&st);
-}
-
-#[test]
-fn should_sort_failures_before_printing_them() {
-    let test_a = TestDesc {
-        name: StaticTestName("a"),
-        ignore: false,
-        should_panic: ShouldPanic::No,
-        allow_fail: false,
-    };
-
-    let test_b = TestDesc {
-        name: StaticTestName("b"),
-        ignore: false,
-        should_panic: ShouldPanic::No,
-        allow_fail: false,
-    };
-
-    let mut out = PrettyFormatter::new(Raw(Vec::new()), false, 10, false);
-
-    let st = ConsoleTestState {
-        log_out: None,
-        total: 0,
-        passed: 0,
-        failed: 0,
-        ignored: 0,
-        allowed_fail: 0,
-        filtered_out: 0,
-        measured: 0,
-        metrics: MetricMap::new(),
-        failures: vec![(test_b, Vec::new()), (test_a, Vec::new())],
-        options: Options::new(),
-        not_failures: Vec::new(),
-    };
-
-    out.write_failures(&st).unwrap();
-    let s = match out.output_location() {
-        &Raw(ref m) => String::from_utf8_lossy(&m[..]),
-        &Pretty(_) => unreachable!(),
-    };
-
-    let apos = s.find("a").unwrap();
-    let bpos = s.find("b").unwrap();
-    assert!(apos < bpos);
-}
-
-fn use_color(opts: &TestOpts) -> bool {
-    match opts.color {
-        AutoColor => !opts.nocapture && stdout_isatty(),
-        AlwaysColor => true,
-        NeverColor => false,
-    }
-}
-
-#[cfg(any(
-    target_os = "cloudabi",
-    target_os = "redox",
-    all(target_arch = "wasm32", not(target_os = "emscripten")),
-    all(target_vendor = "fortanix", target_env = "sgx")
-))]
-fn stdout_isatty() -> bool {
-    // FIXME: Implement isatty on Redox and SGX
-    false
-}
-#[cfg(unix)]
-fn stdout_isatty() -> bool {
-    unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 }
-}
-#[cfg(windows)]
-fn stdout_isatty() -> bool {
-    type DWORD = u32;
-    type BOOL = i32;
-    type HANDLE = *mut u8;
-    type LPDWORD = *mut u32;
-    const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD;
-    extern "system" {
-        fn GetStdHandle(which: DWORD) -> HANDLE;
-        fn GetConsoleMode(hConsoleHandle: HANDLE, lpMode: LPDWORD) -> BOOL;
-    }
-    unsafe {
-        let handle = GetStdHandle(STD_OUTPUT_HANDLE);
-        let mut out = 0;
-        GetConsoleMode(handle, &mut out) != 0
-    }
-}
-
-#[derive(Clone)]
-pub enum TestEvent {
-    TeFiltered(Vec<TestDesc>),
-    TeWait(TestDesc),
-    TeResult(TestDesc, TestResult, Vec<u8>),
-    TeTimeout(TestDesc),
-    TeFilteredOut(usize),
-}
-
-pub type MonitorMsg = (TestDesc, TestResult, Vec<u8>);
-
-struct Sink(Arc<Mutex<Vec<u8>>>);
-impl Write for Sink {
-    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
-        Write::write(&mut *self.0.lock().unwrap(), data)
-    }
-    fn flush(&mut self) -> io::Result<()> {
-        Ok(())
-    }
-}
-
-pub fn run_tests<F>(opts: &TestOpts, tests: Vec<TestDescAndFn>, mut callback: F) -> io::Result<()>
-where
-    F: FnMut(TestEvent) -> io::Result<()>,
-{
-    use std::collections::{self, HashMap};
-    use std::hash::BuildHasherDefault;
-    use std::sync::mpsc::RecvTimeoutError;
-    // Use a deterministic hasher
-    type TestMap =
-        HashMap<TestDesc, Instant, BuildHasherDefault<collections::hash_map::DefaultHasher>>;
-
-    let tests_len = tests.len();
-
-    let mut filtered_tests = filter_tests(opts, tests);
-    if !opts.bench_benchmarks {
-        filtered_tests = convert_benchmarks_to_tests(filtered_tests);
-    }
-
-    let filtered_tests = {
-        let mut filtered_tests = filtered_tests;
-        for test in filtered_tests.iter_mut() {
-            test.desc.name = test.desc.name.with_padding(test.testfn.padding());
-        }
-
-        filtered_tests
-    };
-
-    let filtered_out = tests_len - filtered_tests.len();
-    callback(TeFilteredOut(filtered_out))?;
-
-    let filtered_descs = filtered_tests.iter().map(|t| t.desc.clone()).collect();
-
-    callback(TeFiltered(filtered_descs))?;
-
-    let (filtered_tests, filtered_benchs): (Vec<_>, _) =
-        filtered_tests.into_iter().partition(|e| match e.testfn {
-            StaticTestFn(_) | DynTestFn(_) => true,
-            _ => false,
-        });
-
-    let concurrency = opts.test_threads.unwrap_or_else(get_concurrency);
-
-    let mut remaining = filtered_tests;
-    remaining.reverse();
-    let mut pending = 0;
-
-    let (tx, rx) = channel::<MonitorMsg>();
-
-    let mut running_tests: TestMap = HashMap::default();
-
-    fn get_timed_out_tests(running_tests: &mut TestMap) -> Vec<TestDesc> {
-        let now = Instant::now();
-        let timed_out = running_tests
-            .iter()
-            .filter_map(|(desc, timeout)| {
-                if &now >= timeout {
-                    Some(desc.clone())
-                } else {
-                    None
-                }
-            })
-            .collect();
-        for test in &timed_out {
-            running_tests.remove(test);
-        }
-        timed_out
-    };
-
-    fn calc_timeout(running_tests: &TestMap) -> Option<Duration> {
-        running_tests.values().min().map(|next_timeout| {
-            let now = Instant::now();
-            if *next_timeout >= now {
-                *next_timeout - now
-            } else {
-                Duration::new(0, 0)
-            }
-        })
-    };
-
-    if concurrency == 1 {
-        while !remaining.is_empty() {
-            let test = remaining.pop().unwrap();
-            callback(TeWait(test.desc.clone()))?;
-            run_test(opts, !opts.run_tests, test, tx.clone(), Concurrent::No);
-            let (test, result, stdout) = rx.recv().unwrap();
-            callback(TeResult(test, result, stdout))?;
-        }
-    } else {
-        while pending > 0 || !remaining.is_empty() {
-            while pending < concurrency && !remaining.is_empty() {
-                let test = remaining.pop().unwrap();
-                let timeout = Instant::now() + Duration::from_secs(TEST_WARN_TIMEOUT_S);
-                running_tests.insert(test.desc.clone(), timeout);
-                callback(TeWait(test.desc.clone()))?; //here no pad
-                run_test(opts, !opts.run_tests, test, tx.clone(), Concurrent::Yes);
-                pending += 1;
-            }
-
-            let mut res;
-            loop {
-                if let Some(timeout) = calc_timeout(&running_tests) {
-                    res = rx.recv_timeout(timeout);
-                    for test in get_timed_out_tests(&mut running_tests) {
-                        callback(TeTimeout(test))?;
-                    }
-                    if res != Err(RecvTimeoutError::Timeout) {
-                        break;
-                    }
-                } else {
-                    res = rx.recv().map_err(|_| RecvTimeoutError::Disconnected);
-                    break;
-                }
-            }
-
-            let (desc, result, stdout) = res.unwrap();
-            running_tests.remove(&desc);
-
-            callback(TeResult(desc, result, stdout))?;
-            pending -= 1;
-        }
-    }
-
-    if opts.bench_benchmarks {
-        // All benchmarks run at the end, in serial.
-        for b in filtered_benchs {
-            callback(TeWait(b.desc.clone()))?;
-            run_test(opts, false, b, tx.clone(), Concurrent::No);
-            let (test, result, stdout) = rx.recv().unwrap();
-            callback(TeResult(test, result, stdout))?;
-        }
-    }
-    Ok(())
-}
-
-#[allow(deprecated)]
-fn get_concurrency() -> usize {
-    return match env::var("RUST_TEST_THREADS") {
-        Ok(s) => {
-            let opt_n: Option<usize> = s.parse().ok();
-            match opt_n {
-                Some(n) if n > 0 => n,
-                _ => panic!(
-                    "RUST_TEST_THREADS is `{}`, should be a positive integer.",
-                    s
-                ),
-            }
-        }
-        Err(..) => num_cpus(),
-    };
-
-    #[cfg(windows)]
-    #[allow(nonstandard_style)]
-    fn num_cpus() -> usize {
-        #[repr(C)]
-        struct SYSTEM_INFO {
-            wProcessorArchitecture: u16,
-            wReserved: u16,
-            dwPageSize: u32,
-            lpMinimumApplicationAddress: *mut u8,
-            lpMaximumApplicationAddress: *mut u8,
-            dwActiveProcessorMask: *mut u8,
-            dwNumberOfProcessors: u32,
-            dwProcessorType: u32,
-            dwAllocationGranularity: u32,
-            wProcessorLevel: u16,
-            wProcessorRevision: u16,
-        }
-        extern "system" {
-            fn GetSystemInfo(info: *mut SYSTEM_INFO) -> i32;
-        }
-        unsafe {
-            let mut sysinfo = std::mem::zeroed();
-            GetSystemInfo(&mut sysinfo);
-            sysinfo.dwNumberOfProcessors as usize
-        }
-    }
-
-    #[cfg(target_os = "redox")]
-    fn num_cpus() -> usize {
-        // FIXME: Implement num_cpus on Redox
-        1
-    }
-
-    #[cfg(any(
-        all(target_arch = "wasm32", not(target_os = "emscripten")),
-        all(target_vendor = "fortanix", target_env = "sgx")
-    ))]
-    fn num_cpus() -> usize {
-        1
-    }
-
-    #[cfg(any(
-        target_os = "android",
-        target_os = "cloudabi",
-        target_os = "emscripten",
-        target_os = "fuchsia",
-        target_os = "ios",
-        target_os = "linux",
-        target_os = "macos",
-        target_os = "solaris"
-    ))]
-    fn num_cpus() -> usize {
-        unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as usize }
-    }
-
-    #[cfg(any(
-        target_os = "freebsd",
-        target_os = "dragonfly",
-        target_os = "bitrig",
-        target_os = "netbsd"
-    ))]
-    fn num_cpus() -> usize {
-        use std::ptr;
-
-        let mut cpus: libc::c_uint = 0;
-        let mut cpus_size = std::mem::size_of_val(&cpus);
-
-        unsafe {
-            cpus = libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as libc::c_uint;
-        }
-        if cpus < 1 {
-            let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
-            unsafe {
-                libc::sysctl(
-                    mib.as_mut_ptr(),
-                    2,
-                    &mut cpus as *mut _ as *mut _,
-                    &mut cpus_size as *mut _ as *mut _,
-                    ptr::null_mut(),
-                    0,
-                );
-            }
-            if cpus < 1 {
-                cpus = 1;
-            }
-        }
-        cpus as usize
-    }
-
-    #[cfg(target_os = "openbsd")]
-    fn num_cpus() -> usize {
-        use std::ptr;
-
-        let mut cpus: libc::c_uint = 0;
-        let mut cpus_size = std::mem::size_of_val(&cpus);
-        let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
-
-        unsafe {
-            libc::sysctl(
-                mib.as_mut_ptr(),
-                2,
-                &mut cpus as *mut _ as *mut _,
-                &mut cpus_size as *mut _ as *mut _,
-                ptr::null_mut(),
-                0,
-            );
-        }
-        if cpus < 1 {
-            cpus = 1;
-        }
-        cpus as usize
-    }
-
-    #[cfg(target_os = "haiku")]
-    fn num_cpus() -> usize {
-        // FIXME: implement
-        1
-    }
-
-    #[cfg(target_os = "l4re")]
-    fn num_cpus() -> usize {
-        // FIXME: implement
-        1
-    }
-}
-
-pub fn filter_tests(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> Vec<TestDescAndFn> {
-    let mut filtered = tests;
-    let matches_filter = |test: &TestDescAndFn, filter: &str| {
-        let test_name = test.desc.name.as_slice();
-
-        match opts.filter_exact {
-            true => test_name == filter,
-            false => test_name.contains(filter),
-        }
-    };
-
-    // Remove tests that don't match the test filter
-    if let Some(ref filter) = opts.filter {
-        filtered.retain(|test| matches_filter(test, filter));
-    }
-
-    // Skip tests that match any of the skip filters
-    filtered.retain(|test| !opts.skip.iter().any(|sf| matches_filter(test, sf)));
-
-    // Excludes #[should_panic] tests
-    if opts.exclude_should_panic {
-        filtered.retain(|test| test.desc.should_panic == ShouldPanic::No);
-    }
-
-    // maybe unignore tests
-    match opts.run_ignored {
-        RunIgnored::Yes => {
-            filtered
-                .iter_mut()
-                .for_each(|test| test.desc.ignore = false);
-        }
-        RunIgnored::Only => {
-            filtered.retain(|test| test.desc.ignore);
-            filtered
-                .iter_mut()
-                .for_each(|test| test.desc.ignore = false);
-        }
-        RunIgnored::No => {}
-    }
-
-    // Sort the tests alphabetically
-    filtered.sort_by(|t1, t2| t1.desc.name.as_slice().cmp(t2.desc.name.as_slice()));
-
-    filtered
-}
-
-pub fn convert_benchmarks_to_tests(tests: Vec<TestDescAndFn>) -> Vec<TestDescAndFn> {
-    // convert benchmarks to tests, if we're not benchmarking them
-    tests
-        .into_iter()
-        .map(|x| {
-            let testfn = match x.testfn {
-                DynBenchFn(bench) => DynTestFn(Box::new(move || {
-                    bench::run_once(|b| __rust_begin_short_backtrace(|| bench.run(b)))
-                })),
-                StaticBenchFn(benchfn) => DynTestFn(Box::new(move || {
-                    bench::run_once(|b| __rust_begin_short_backtrace(|| benchfn(b)))
-                })),
-                f => f,
-            };
-            TestDescAndFn {
-                desc: x.desc,
-                testfn,
-            }
-        })
-        .collect()
-}
-
-pub fn run_test(
-    opts: &TestOpts,
-    force_ignore: bool,
-    test: TestDescAndFn,
-    monitor_ch: Sender<MonitorMsg>,
-    concurrency: Concurrent,
-) {
-    let TestDescAndFn { desc, testfn } = test;
-
-    let ignore_because_panic_abort = cfg!(target_arch = "wasm32")
-        && !cfg!(target_os = "emscripten")
-        && desc.should_panic != ShouldPanic::No;
-
-    if force_ignore || desc.ignore || ignore_because_panic_abort {
-        monitor_ch.send((desc, TrIgnored, Vec::new())).unwrap();
-        return;
-    }
-
-    fn run_test_inner(
-        desc: TestDesc,
-        monitor_ch: Sender<MonitorMsg>,
-        nocapture: bool,
-        testfn: Box<dyn FnBox() + Send>,
-        concurrency: Concurrent,
-    ) {
-        // Buffer for capturing standard I/O
-        let data = Arc::new(Mutex::new(Vec::new()));
-        let data2 = data.clone();
-
-        let name = desc.name.clone();
-        let runtest = move || {
-            let oldio = if !nocapture {
-                Some((
-                    io::set_print(Some(Box::new(Sink(data2.clone())))),
-                    io::set_panic(Some(Box::new(Sink(data2)))),
-                ))
-            } else {
-                None
-            };
-
-            let result = catch_unwind(AssertUnwindSafe(testfn));
-
-            if let Some((printio, panicio)) = oldio {
-                io::set_print(printio);
-                io::set_panic(panicio);
-            };
-
-            let test_result = calc_result(&desc, result);
-            let stdout = data.lock().unwrap().to_vec();
-            monitor_ch
-                .send((desc.clone(), test_result, stdout))
-                .unwrap();
-        };
-
-        // If the platform is single-threaded we're just going to run
-        // the test synchronously, regardless of the concurrency
-        // level.
-        let supports_threads = !cfg!(target_os = "emscripten") && !cfg!(target_arch = "wasm32");
-        if concurrency == Concurrent::Yes && supports_threads {
-            let cfg = thread::Builder::new().name(name.as_slice().to_owned());
-            cfg.spawn(runtest).unwrap();
-        } else {
-            runtest();
-        }
-    }
-
-    match testfn {
-        DynBenchFn(bencher) => {
-            crate::bench::benchmark(desc, monitor_ch, opts.nocapture, |harness| {
-                bencher.run(harness)
-            });
-        }
-        StaticBenchFn(benchfn) => {
-            crate::bench::benchmark(desc, monitor_ch, opts.nocapture, |harness| {
-                (benchfn.clone())(harness)
-            });
-        }
-        DynTestFn(f) => {
-            let cb = move || __rust_begin_short_backtrace(f);
-            run_test_inner(desc, monitor_ch, opts.nocapture, Box::new(cb), concurrency)
-        }
-        StaticTestFn(f) => run_test_inner(
-            desc,
-            monitor_ch,
-            opts.nocapture,
-            Box::new(move || __rust_begin_short_backtrace(f)),
-            concurrency,
-        ),
-    }
-}
-
-/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`.
-#[inline(never)]
-fn __rust_begin_short_backtrace<F: FnOnce()>(f: F) {
-    f()
-}
-
-fn calc_result(desc: &TestDesc, task_result: Result<(), Box<dyn Any + Send>>) -> TestResult {
-    match (&desc.should_panic, task_result) {
-        (&ShouldPanic::No, Ok(())) | (&ShouldPanic::Yes, Err(_)) => TrOk,
-        (&ShouldPanic::YesWithMessage(msg), Err(ref err)) => {
-            if err
-                .downcast_ref::<String>()
-                .map(|e| &**e)
-                .or_else(|| err.downcast_ref::<&'static str>().map(|e| *e))
-                .map(|e| e.contains(msg))
-                .unwrap_or(false)
-            {
-                TrOk
-            } else {
-                if desc.allow_fail {
-                    TrAllowedFail
-                } else {
-                    TrFailedMsg(format!("Panic did not include expected string '{}'", msg))
-                }
-            }
-        }
-        _ if desc.allow_fail => TrAllowedFail,
-        _ => TrFailed,
-    }
-}
-
-#[derive(Clone, PartialEq)]
-pub struct MetricMap(BTreeMap<String, Metric>);
-
-impl MetricMap {
-    pub fn new() -> MetricMap {
-        MetricMap(BTreeMap::new())
-    }
-
-    /// Insert a named `value` (+/- `noise`) metric into the map. The value
-    /// must be non-negative. The `noise` indicates the uncertainty of the
-    /// metric, which doubles as the "noise range" of acceptable
-    /// pairwise-regressions on this named value, when comparing from one
-    /// metric to the next using `compare_to_old`.
-    ///
-    /// If `noise` is positive, then it means this metric is of a value
-    /// you want to see grow smaller, so a change larger than `noise` in the
-    /// positive direction represents a regression.
-    ///
-    /// If `noise` is negative, then it means this metric is of a value
-    /// you want to see grow larger, so a change larger than `noise` in the
-    /// negative direction represents a regression.
-    pub fn insert_metric(&mut self, name: &str, value: f64, noise: f64) {
-        let m = Metric { value, noise };
-        self.0.insert(name.to_owned(), m);
-    }
-
-    pub fn fmt_metrics(&self) -> String {
-        let v = self
-            .0
-            .iter()
-            .map(|(k, v)| format!("{}: {} (+/- {})", *k, v.value, v.noise))
-            .collect::<Vec<_>>();
-        v.join(", ")
-    }
-}
-
-// Benchmarking
+// FIXME: we should be more explicit about the exact APIs that we
+// export to users.
+pub use libtest::{
+    assert_test_result, filter_tests, parse_opts, run_test, test_main, test_main_static,
+    Bencher, DynTestFn, DynTestName, Metric, MetricMap, Options, RunIgnored, ShouldPanic,
+    StaticBenchFn, StaticTestFn, StaticTestName, TestDesc, TestDescAndFn, TestName, TestOpts,
+    TestResult, TrFailed, TrFailedMsg, TrIgnored, TrOk, stats::Summary
+};
 
 /// A function that is opaque to the optimizer, to allow benchmarks to
 /// pretend to use outputs to assist in avoiding dead-code
@@ -1602,646 +44,3 @@
 pub fn black_box<T>(dummy: T) -> T {
     dummy
 }
-
-impl Bencher {
-    /// Callback for benchmark functions to run in their body.
-    pub fn iter<T, F>(&mut self, mut inner: F)
-    where
-        F: FnMut() -> T,
-    {
-        if self.mode == BenchMode::Single {
-            ns_iter_inner(&mut inner, 1);
-            return;
-        }
-
-        self.summary = Some(iter(&mut inner));
-    }
-
-    pub fn bench<F>(&mut self, mut f: F) -> Option<stats::Summary>
-    where
-        F: FnMut(&mut Bencher),
-    {
-        f(self);
-        return self.summary;
-    }
-}
-
-fn ns_from_dur(dur: Duration) -> u64 {
-    dur.as_secs() * 1_000_000_000 + (dur.subsec_nanos() as u64)
-}
-
-fn ns_iter_inner<T, F>(inner: &mut F, k: u64) -> u64
-where
-    F: FnMut() -> T,
-{
-    let start = Instant::now();
-    for _ in 0..k {
-        black_box(inner());
-    }
-    return ns_from_dur(start.elapsed());
-}
-
-pub fn iter<T, F>(inner: &mut F) -> stats::Summary
-where
-    F: FnMut() -> T,
-{
-    // Initial bench run to get ballpark figure.
-    let ns_single = ns_iter_inner(inner, 1);
-
-    // Try to estimate iter count for 1ms falling back to 1m
-    // iterations if first run took < 1ns.
-    let ns_target_total = 1_000_000; // 1ms
-    let mut n = ns_target_total / cmp::max(1, ns_single);
-
-    // if the first run took more than 1ms we don't want to just
-    // be left doing 0 iterations on every loop. The unfortunate
-    // side effect of not being able to do as many runs is
-    // automatically handled by the statistical analysis below
-    // (i.e., larger error bars).
-    n = cmp::max(1, n);
-
-    let mut total_run = Duration::new(0, 0);
-    let samples: &mut [f64] = &mut [0.0_f64; 50];
-    loop {
-        let loop_start = Instant::now();
-
-        for p in &mut *samples {
-            *p = ns_iter_inner(inner, n) as f64 / n as f64;
-        }
-
-        stats::winsorize(samples, 5.0);
-        let summ = stats::Summary::new(samples);
-
-        for p in &mut *samples {
-            let ns = ns_iter_inner(inner, 5 * n);
-            *p = ns as f64 / (5 * n) as f64;
-        }
-
-        stats::winsorize(samples, 5.0);
-        let summ5 = stats::Summary::new(samples);
-
-        let loop_run = loop_start.elapsed();
-
-        // If we've run for 100ms and seem to have converged to a
-        // stable median.
-        if loop_run > Duration::from_millis(100)
-            && summ.median_abs_dev_pct < 1.0
-            && summ.median - summ5.median < summ5.median_abs_dev
-        {
-            return summ5;
-        }
-
-        total_run = total_run + loop_run;
-        // Longest we ever run for is 3s.
-        if total_run > Duration::from_secs(3) {
-            return summ5;
-        }
-
-        // If we overflow here just return the results so far. We check a
-        // multiplier of 10 because we're about to multiply by 2 and the
-        // next iteration of the loop will also multiply by 5 (to calculate
-        // the summ5 result)
-        n = match n.checked_mul(10) {
-            Some(_) => n * 2,
-            None => {
-                return summ5;
-            }
-        };
-    }
-}
-
-pub mod bench {
-    use super::{BenchMode, BenchSamples, Bencher, MonitorMsg, Sender, Sink, TestDesc, TestResult};
-    use crate::stats;
-    use std::cmp;
-    use std::io;
-    use std::panic::{catch_unwind, AssertUnwindSafe};
-    use std::sync::{Arc, Mutex};
-
-    pub fn benchmark<F>(desc: TestDesc, monitor_ch: Sender<MonitorMsg>, nocapture: bool, f: F)
-    where
-        F: FnMut(&mut Bencher),
-    {
-        let mut bs = Bencher {
-            mode: BenchMode::Auto,
-            summary: None,
-            bytes: 0,
-        };
-
-        let data = Arc::new(Mutex::new(Vec::new()));
-        let data2 = data.clone();
-
-        let oldio = if !nocapture {
-            Some((
-                io::set_print(Some(Box::new(Sink(data2.clone())))),
-                io::set_panic(Some(Box::new(Sink(data2)))),
-            ))
-        } else {
-            None
-        };
-
-        let result = catch_unwind(AssertUnwindSafe(|| bs.bench(f)));
-
-        if let Some((printio, panicio)) = oldio {
-            io::set_print(printio);
-            io::set_panic(panicio);
-        };
-
-        let test_result = match result {
-            //bs.bench(f) {
-            Ok(Some(ns_iter_summ)) => {
-                let ns_iter = cmp::max(ns_iter_summ.median as u64, 1);
-                let mb_s = bs.bytes * 1000 / ns_iter;
-
-                let bs = BenchSamples {
-                    ns_iter_summ,
-                    mb_s: mb_s as usize,
-                };
-                TestResult::TrBench(bs)
-            }
-            Ok(None) => {
-                // iter not called, so no data.
-                // FIXME: error in this case?
-                let samples: &mut [f64] = &mut [0.0_f64; 1];
-                let bs = BenchSamples {
-                    ns_iter_summ: stats::Summary::new(samples),
-                    mb_s: 0,
-                };
-                TestResult::TrBench(bs)
-            }
-            Err(_) => TestResult::TrFailed,
-        };
-
-        let stdout = data.lock().unwrap().to_vec();
-        monitor_ch.send((desc, test_result, stdout)).unwrap();
-    }
-
-    pub fn run_once<F>(f: F)
-    where
-        F: FnMut(&mut Bencher),
-    {
-        let mut bs = Bencher {
-            mode: BenchMode::Single,
-            summary: None,
-            bytes: 0,
-        };
-        bs.bench(f);
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use crate::bench;
-    use crate::test::{
-        filter_tests, parse_opts, run_test, DynTestFn, DynTestName, MetricMap, RunIgnored,
-        ShouldPanic, StaticTestName, TestDesc, TestDescAndFn, TestOpts, TrFailed, TrFailedMsg,
-        TrIgnored, TrOk,
-    };
-    use crate::Bencher;
-    use crate::Concurrent;
-    use std::sync::mpsc::channel;
-
-    fn one_ignored_one_unignored_test() -> Vec<TestDescAndFn> {
-        vec![
-            TestDescAndFn {
-                desc: TestDesc {
-                    name: StaticTestName("1"),
-                    ignore: true,
-                    should_panic: ShouldPanic::No,
-                    allow_fail: false,
-                },
-                testfn: DynTestFn(Box::new(move || {})),
-            },
-            TestDescAndFn {
-                desc: TestDesc {
-                    name: StaticTestName("2"),
-                    ignore: false,
-                    should_panic: ShouldPanic::No,
-                    allow_fail: false,
-                },
-                testfn: DynTestFn(Box::new(move || {})),
-            },
-        ]
-    }
-
-    #[test]
-    pub fn do_not_run_ignored_tests() {
-        fn f() {
-            panic!();
-        }
-        let desc = TestDescAndFn {
-            desc: TestDesc {
-                name: StaticTestName("whatever"),
-                ignore: true,
-                should_panic: ShouldPanic::No,
-                allow_fail: false,
-            },
-            testfn: DynTestFn(Box::new(f)),
-        };
-        let (tx, rx) = channel();
-        run_test(&TestOpts::new(), false, desc, tx, Concurrent::No);
-        let (_, res, _) = rx.recv().unwrap();
-        assert!(res != TrOk);
-    }
-
-    #[test]
-    pub fn ignored_tests_result_in_ignored() {
-        fn f() {}
-        let desc = TestDescAndFn {
-            desc: TestDesc {
-                name: StaticTestName("whatever"),
-                ignore: true,
-                should_panic: ShouldPanic::No,
-                allow_fail: false,
-            },
-            testfn: DynTestFn(Box::new(f)),
-        };
-        let (tx, rx) = channel();
-        run_test(&TestOpts::new(), false, desc, tx, Concurrent::No);
-        let (_, res, _) = rx.recv().unwrap();
-        assert!(res == TrIgnored);
-    }
-
-    #[test]
-    fn test_should_panic() {
-        fn f() {
-            panic!();
-        }
-        let desc = TestDescAndFn {
-            desc: TestDesc {
-                name: StaticTestName("whatever"),
-                ignore: false,
-                should_panic: ShouldPanic::Yes,
-                allow_fail: false,
-            },
-            testfn: DynTestFn(Box::new(f)),
-        };
-        let (tx, rx) = channel();
-        run_test(&TestOpts::new(), false, desc, tx, Concurrent::No);
-        let (_, res, _) = rx.recv().unwrap();
-        assert!(res == TrOk);
-    }
-
-    #[test]
-    fn test_should_panic_good_message() {
-        fn f() {
-            panic!("an error message");
-        }
-        let desc = TestDescAndFn {
-            desc: TestDesc {
-                name: StaticTestName("whatever"),
-                ignore: false,
-                should_panic: ShouldPanic::YesWithMessage("error message"),
-                allow_fail: false,
-            },
-            testfn: DynTestFn(Box::new(f)),
-        };
-        let (tx, rx) = channel();
-        run_test(&TestOpts::new(), false, desc, tx, Concurrent::No);
-        let (_, res, _) = rx.recv().unwrap();
-        assert!(res == TrOk);
-    }
-
-    #[test]
-    fn test_should_panic_bad_message() {
-        fn f() {
-            panic!("an error message");
-        }
-        let expected = "foobar";
-        let failed_msg = "Panic did not include expected string";
-        let desc = TestDescAndFn {
-            desc: TestDesc {
-                name: StaticTestName("whatever"),
-                ignore: false,
-                should_panic: ShouldPanic::YesWithMessage(expected),
-                allow_fail: false,
-            },
-            testfn: DynTestFn(Box::new(f)),
-        };
-        let (tx, rx) = channel();
-        run_test(&TestOpts::new(), false, desc, tx, Concurrent::No);
-        let (_, res, _) = rx.recv().unwrap();
-        assert!(res == TrFailedMsg(format!("{} '{}'", failed_msg, expected)));
-    }
-
-    #[test]
-    fn test_should_panic_but_succeeds() {
-        fn f() {}
-        let desc = TestDescAndFn {
-            desc: TestDesc {
-                name: StaticTestName("whatever"),
-                ignore: false,
-                should_panic: ShouldPanic::Yes,
-                allow_fail: false,
-            },
-            testfn: DynTestFn(Box::new(f)),
-        };
-        let (tx, rx) = channel();
-        run_test(&TestOpts::new(), false, desc, tx, Concurrent::No);
-        let (_, res, _) = rx.recv().unwrap();
-        assert!(res == TrFailed);
-    }
-
-    #[test]
-    fn parse_ignored_flag() {
-        let args = vec![
-            "progname".to_string(),
-            "filter".to_string(),
-            "--ignored".to_string(),
-        ];
-        let opts = parse_opts(&args).unwrap().unwrap();
-        assert_eq!(opts.run_ignored, RunIgnored::Only);
-    }
-
-    #[test]
-    fn parse_include_ignored_flag() {
-        let args = vec![
-            "progname".to_string(),
-            "filter".to_string(),
-            "-Zunstable-options".to_string(),
-            "--include-ignored".to_string(),
-        ];
-        let opts = parse_opts(&args).unwrap().unwrap();
-        assert_eq!(opts.run_ignored, RunIgnored::Yes);
-    }
-
-    #[test]
-    pub fn filter_for_ignored_option() {
-        // When we run ignored tests the test filter should filter out all the
-        // unignored tests and flip the ignore flag on the rest to false
-
-        let mut opts = TestOpts::new();
-        opts.run_tests = true;
-        opts.run_ignored = RunIgnored::Only;
-
-        let tests = one_ignored_one_unignored_test();
-        let filtered = filter_tests(&opts, tests);
-
-        assert_eq!(filtered.len(), 1);
-        assert_eq!(filtered[0].desc.name.to_string(), "1");
-        assert!(!filtered[0].desc.ignore);
-    }
-
-    #[test]
-    pub fn run_include_ignored_option() {
-        // When we "--include-ignored" tests, the ignore flag should be set to false on
-        // all tests and no test filtered out
-
-        let mut opts = TestOpts::new();
-        opts.run_tests = true;
-        opts.run_ignored = RunIgnored::Yes;
-
-        let tests = one_ignored_one_unignored_test();
-        let filtered = filter_tests(&opts, tests);
-
-        assert_eq!(filtered.len(), 2);
-        assert!(!filtered[0].desc.ignore);
-        assert!(!filtered[1].desc.ignore);
-    }
-
-    #[test]
-    pub fn exclude_should_panic_option() {
-        let mut opts = TestOpts::new();
-        opts.run_tests = true;
-        opts.exclude_should_panic = true;
-
-        let mut tests = one_ignored_one_unignored_test();
-        tests.push(TestDescAndFn {
-            desc: TestDesc {
-                name: StaticTestName("3"),
-                ignore: false,
-                should_panic: ShouldPanic::Yes,
-                allow_fail: false,
-            },
-            testfn: DynTestFn(Box::new(move || {})),
-        });
-
-        let filtered = filter_tests(&opts, tests);
-
-        assert_eq!(filtered.len(), 2);
-        assert!(filtered.iter().all(|test| test.desc.should_panic == ShouldPanic::No));
-    }
-
-    #[test]
-    pub fn exact_filter_match() {
-        fn tests() -> Vec<TestDescAndFn> {
-            vec!["base", "base::test", "base::test1", "base::test2"]
-                .into_iter()
-                .map(|name| TestDescAndFn {
-                    desc: TestDesc {
-                        name: StaticTestName(name),
-                        ignore: false,
-                        should_panic: ShouldPanic::No,
-                        allow_fail: false,
-                    },
-                    testfn: DynTestFn(Box::new(move || {})),
-                })
-                .collect()
-        }
-
-        let substr = filter_tests(
-            &TestOpts {
-                filter: Some("base".into()),
-                ..TestOpts::new()
-            },
-            tests(),
-        );
-        assert_eq!(substr.len(), 4);
-
-        let substr = filter_tests(
-            &TestOpts {
-                filter: Some("bas".into()),
-                ..TestOpts::new()
-            },
-            tests(),
-        );
-        assert_eq!(substr.len(), 4);
-
-        let substr = filter_tests(
-            &TestOpts {
-                filter: Some("::test".into()),
-                ..TestOpts::new()
-            },
-            tests(),
-        );
-        assert_eq!(substr.len(), 3);
-
-        let substr = filter_tests(
-            &TestOpts {
-                filter: Some("base::test".into()),
-                ..TestOpts::new()
-            },
-            tests(),
-        );
-        assert_eq!(substr.len(), 3);
-
-        let exact = filter_tests(
-            &TestOpts {
-                filter: Some("base".into()),
-                filter_exact: true,
-                ..TestOpts::new()
-            },
-            tests(),
-        );
-        assert_eq!(exact.len(), 1);
-
-        let exact = filter_tests(
-            &TestOpts {
-                filter: Some("bas".into()),
-                filter_exact: true,
-                ..TestOpts::new()
-            },
-            tests(),
-        );
-        assert_eq!(exact.len(), 0);
-
-        let exact = filter_tests(
-            &TestOpts {
-                filter: Some("::test".into()),
-                filter_exact: true,
-                ..TestOpts::new()
-            },
-            tests(),
-        );
-        assert_eq!(exact.len(), 0);
-
-        let exact = filter_tests(
-            &TestOpts {
-                filter: Some("base::test".into()),
-                filter_exact: true,
-                ..TestOpts::new()
-            },
-            tests(),
-        );
-        assert_eq!(exact.len(), 1);
-    }
-
-    #[test]
-    pub fn sort_tests() {
-        let mut opts = TestOpts::new();
-        opts.run_tests = true;
-
-        let names = vec![
-            "sha1::test".to_string(),
-            "isize::test_to_str".to_string(),
-            "isize::test_pow".to_string(),
-            "test::do_not_run_ignored_tests".to_string(),
-            "test::ignored_tests_result_in_ignored".to_string(),
-            "test::first_free_arg_should_be_a_filter".to_string(),
-            "test::parse_ignored_flag".to_string(),
-            "test::parse_include_ignored_flag".to_string(),
-            "test::filter_for_ignored_option".to_string(),
-            "test::run_include_ignored_option".to_string(),
-            "test::sort_tests".to_string(),
-        ];
-        let tests = {
-            fn testfn() {}
-            let mut tests = Vec::new();
-            for name in &names {
-                let test = TestDescAndFn {
-                    desc: TestDesc {
-                        name: DynTestName((*name).clone()),
-                        ignore: false,
-                        should_panic: ShouldPanic::No,
-                        allow_fail: false,
-                    },
-                    testfn: DynTestFn(Box::new(testfn)),
-                };
-                tests.push(test);
-            }
-            tests
-        };
-        let filtered = filter_tests(&opts, tests);
-
-        let expected = vec![
-            "isize::test_pow".to_string(),
-            "isize::test_to_str".to_string(),
-            "sha1::test".to_string(),
-            "test::do_not_run_ignored_tests".to_string(),
-            "test::filter_for_ignored_option".to_string(),
-            "test::first_free_arg_should_be_a_filter".to_string(),
-            "test::ignored_tests_result_in_ignored".to_string(),
-            "test::parse_ignored_flag".to_string(),
-            "test::parse_include_ignored_flag".to_string(),
-            "test::run_include_ignored_option".to_string(),
-            "test::sort_tests".to_string(),
-        ];
-
-        for (a, b) in expected.iter().zip(filtered) {
-            assert!(*a == b.desc.name.to_string());
-        }
-    }
-
-    #[test]
-    pub fn test_metricmap_compare() {
-        let mut m1 = MetricMap::new();
-        let mut m2 = MetricMap::new();
-        m1.insert_metric("in-both-noise", 1000.0, 200.0);
-        m2.insert_metric("in-both-noise", 1100.0, 200.0);
-
-        m1.insert_metric("in-first-noise", 1000.0, 2.0);
-        m2.insert_metric("in-second-noise", 1000.0, 2.0);
-
-        m1.insert_metric("in-both-want-downwards-but-regressed", 1000.0, 10.0);
-        m2.insert_metric("in-both-want-downwards-but-regressed", 2000.0, 10.0);
-
-        m1.insert_metric("in-both-want-downwards-and-improved", 2000.0, 10.0);
-        m2.insert_metric("in-both-want-downwards-and-improved", 1000.0, 10.0);
-
-        m1.insert_metric("in-both-want-upwards-but-regressed", 2000.0, -10.0);
-        m2.insert_metric("in-both-want-upwards-but-regressed", 1000.0, -10.0);
-
-        m1.insert_metric("in-both-want-upwards-and-improved", 1000.0, -10.0);
-        m2.insert_metric("in-both-want-upwards-and-improved", 2000.0, -10.0);
-    }
-
-    #[test]
-    pub fn test_bench_once_no_iter() {
-        fn f(_: &mut Bencher) {}
-        bench::run_once(f);
-    }
-
-    #[test]
-    pub fn test_bench_once_iter() {
-        fn f(b: &mut Bencher) {
-            b.iter(|| {})
-        }
-        bench::run_once(f);
-    }
-
-    #[test]
-    pub fn test_bench_no_iter() {
-        fn f(_: &mut Bencher) {}
-
-        let (tx, rx) = channel();
-
-        let desc = TestDesc {
-            name: StaticTestName("f"),
-            ignore: false,
-            should_panic: ShouldPanic::No,
-            allow_fail: false,
-        };
-
-        crate::bench::benchmark(desc, tx, true, f);
-        rx.recv().unwrap();
-    }
-
-    #[test]
-    pub fn test_bench_iter() {
-        fn f(b: &mut Bencher) {
-            b.iter(|| {})
-        }
-
-        let (tx, rx) = channel();
-
-        let desc = TestDesc {
-            name: StaticTestName("f"),
-            ignore: false,
-            should_panic: ShouldPanic::No,
-            allow_fail: false,
-        };
-
-        crate::bench::benchmark(desc, tx, true, f);
-        rx.recv().unwrap();
-    }
-}
diff --git a/src/libtest/stats.rs b/src/libtest/stats.rs
deleted file mode 100644
index 5c9421d..0000000
--- a/src/libtest/stats.rs
+++ /dev/null
@@ -1,922 +0,0 @@
-#![allow(missing_docs)]
-#![allow(deprecated)] // Float
-
-use std::cmp::Ordering::{self, Equal, Greater, Less};
-use std::mem;
-
-fn local_cmp(x: f64, y: f64) -> Ordering {
-    // arbitrarily decide that NaNs are larger than everything.
-    if y.is_nan() {
-        Less
-    } else if x.is_nan() {
-        Greater
-    } else if x < y {
-        Less
-    } else if x == y {
-        Equal
-    } else {
-        Greater
-    }
-}
-
-fn local_sort(v: &mut [f64]) {
-    v.sort_by(|x: &f64, y: &f64| local_cmp(*x, *y));
-}
-
-/// Trait that provides simple descriptive statistics on a univariate set of numeric samples.
-pub trait Stats {
-    /// Sum of the samples.
-    ///
-    /// Note: this method sacrifices performance at the altar of accuracy
-    /// Depends on IEEE-754 arithmetic guarantees. See proof of correctness at:
-    /// ["Adaptive Precision Floating-Point Arithmetic and Fast Robust Geometric
-    /// Predicates"][paper]
-    ///
-    /// [paper]: http://www.cs.cmu.edu/~quake-papers/robust-arithmetic.ps
-    fn sum(&self) -> f64;
-
-    /// Minimum value of the samples.
-    fn min(&self) -> f64;
-
-    /// Maximum value of the samples.
-    fn max(&self) -> f64;
-
-    /// Arithmetic mean (average) of the samples: sum divided by sample-count.
-    ///
-    /// See: <https://en.wikipedia.org/wiki/Arithmetic_mean>
-    fn mean(&self) -> f64;
-
-    /// Median of the samples: value separating the lower half of the samples from the higher half.
-    /// Equal to `self.percentile(50.0)`.
-    ///
-    /// See: <https://en.wikipedia.org/wiki/Median>
-    fn median(&self) -> f64;
-
-    /// Variance of the samples: bias-corrected mean of the squares of the differences of each
-    /// sample from the sample mean. Note that this calculates the _sample variance_ rather than the
-    /// population variance, which is assumed to be unknown. It therefore corrects the `(n-1)/n`
-    /// bias that would appear if we calculated a population variance, by dividing by `(n-1)` rather
-    /// than `n`.
-    ///
-    /// See: <https://en.wikipedia.org/wiki/Variance>
-    fn var(&self) -> f64;
-
-    /// Standard deviation: the square root of the sample variance.
-    ///
-    /// Note: this is not a robust statistic for non-normal distributions. Prefer the
-    /// `median_abs_dev` for unknown distributions.
-    ///
-    /// See: <https://en.wikipedia.org/wiki/Standard_deviation>
-    fn std_dev(&self) -> f64;
-
-    /// Standard deviation as a percent of the mean value. See `std_dev` and `mean`.
-    ///
-    /// Note: this is not a robust statistic for non-normal distributions. Prefer the
-    /// `median_abs_dev_pct` for unknown distributions.
-    fn std_dev_pct(&self) -> f64;
-
-    /// Scaled median of the absolute deviations of each sample from the sample median. This is a
-    /// robust (distribution-agnostic) estimator of sample variability. Use this in preference to
-    /// `std_dev` if you cannot assume your sample is normally distributed. Note that this is scaled
-    /// by the constant `1.4826` to allow its use as a consistent estimator for the standard
-    /// deviation.
-    ///
-    /// See: <http://en.wikipedia.org/wiki/Median_absolute_deviation>
-    fn median_abs_dev(&self) -> f64;
-
-    /// Median absolute deviation as a percent of the median. See `median_abs_dev` and `median`.
-    fn median_abs_dev_pct(&self) -> f64;
-
-    /// Percentile: the value below which `pct` percent of the values in `self` fall. For example,
-    /// percentile(95.0) will return the value `v` such that 95% of the samples `s` in `self`
-    /// satisfy `s <= v`.
-    ///
-    /// Calculated by linear interpolation between closest ranks.
-    ///
-    /// See: <http://en.wikipedia.org/wiki/Percentile>
-    fn percentile(&self, pct: f64) -> f64;
-
-    /// Quartiles of the sample: three values that divide the sample into four equal groups, each
-    /// with 1/4 of the data. The middle value is the median. See `median` and `percentile`. This
-    /// function may calculate the 3 quartiles more efficiently than 3 calls to `percentile`, but
-    /// is otherwise equivalent.
-    ///
-    /// See also: <https://en.wikipedia.org/wiki/Quartile>
-    fn quartiles(&self) -> (f64, f64, f64);
-
-    /// Inter-quartile range: the difference between the 25th percentile (1st quartile) and the 75th
-    /// percentile (3rd quartile). See `quartiles`.
-    ///
-    /// See also: <https://en.wikipedia.org/wiki/Interquartile_range>
-    fn iqr(&self) -> f64;
-}
-
-/// Extracted collection of all the summary statistics of a sample set.
-#[derive(Clone, PartialEq, Copy)]
-#[allow(missing_docs)]
-pub struct Summary {
-    pub sum: f64,
-    pub min: f64,
-    pub max: f64,
-    pub mean: f64,
-    pub median: f64,
-    pub var: f64,
-    pub std_dev: f64,
-    pub std_dev_pct: f64,
-    pub median_abs_dev: f64,
-    pub median_abs_dev_pct: f64,
-    pub quartiles: (f64, f64, f64),
-    pub iqr: f64,
-}
-
-impl Summary {
-    /// Construct a new summary of a sample set.
-    pub fn new(samples: &[f64]) -> Summary {
-        Summary {
-            sum: samples.sum(),
-            min: samples.min(),
-            max: samples.max(),
-            mean: samples.mean(),
-            median: samples.median(),
-            var: samples.var(),
-            std_dev: samples.std_dev(),
-            std_dev_pct: samples.std_dev_pct(),
-            median_abs_dev: samples.median_abs_dev(),
-            median_abs_dev_pct: samples.median_abs_dev_pct(),
-            quartiles: samples.quartiles(),
-            iqr: samples.iqr(),
-        }
-    }
-}
-
-impl Stats for [f64] {
-    // FIXME #11059 handle NaN, inf and overflow
-    fn sum(&self) -> f64 {
-        let mut partials = vec![];
-
-        for &x in self {
-            let mut x = x;
-            let mut j = 0;
-            // This inner loop applies `hi`/`lo` summation to each
-            // partial so that the list of partial sums remains exact.
-            for i in 0..partials.len() {
-                let mut y: f64 = partials[i];
-                if x.abs() < y.abs() {
-                    mem::swap(&mut x, &mut y);
-                }
-                // Rounded `x+y` is stored in `hi` with round-off stored in
-                // `lo`. Together `hi+lo` are exactly equal to `x+y`.
-                let hi = x + y;
-                let lo = y - (hi - x);
-                if lo != 0.0 {
-                    partials[j] = lo;
-                    j += 1;
-                }
-                x = hi;
-            }
-            if j >= partials.len() {
-                partials.push(x);
-            } else {
-                partials[j] = x;
-                partials.truncate(j + 1);
-            }
-        }
-        let zero: f64 = 0.0;
-        partials.iter().fold(zero, |p, q| p + *q)
-    }
-
-    fn min(&self) -> f64 {
-        assert!(!self.is_empty());
-        self.iter().fold(self[0], |p, q| p.min(*q))
-    }
-
-    fn max(&self) -> f64 {
-        assert!(!self.is_empty());
-        self.iter().fold(self[0], |p, q| p.max(*q))
-    }
-
-    fn mean(&self) -> f64 {
-        assert!(!self.is_empty());
-        self.sum() / (self.len() as f64)
-    }
-
-    fn median(&self) -> f64 {
-        self.percentile(50 as f64)
-    }
-
-    fn var(&self) -> f64 {
-        if self.len() < 2 {
-            0.0
-        } else {
-            let mean = self.mean();
-            let mut v: f64 = 0.0;
-            for s in self {
-                let x = *s - mean;
-                v = v + x * x;
-            }
-            // N.B., this is _supposed to be_ len-1, not len. If you
-            // change it back to len, you will be calculating a
-            // population variance, not a sample variance.
-            let denom = (self.len() - 1) as f64;
-            v / denom
-        }
-    }
-
-    fn std_dev(&self) -> f64 {
-        self.var().sqrt()
-    }
-
-    fn std_dev_pct(&self) -> f64 {
-        let hundred = 100 as f64;
-        (self.std_dev() / self.mean()) * hundred
-    }
-
-    fn median_abs_dev(&self) -> f64 {
-        let med = self.median();
-        let abs_devs: Vec<f64> = self.iter().map(|&v| (med - v).abs()).collect();
-        // This constant is derived by smarter statistics brains than me, but it is
-        // consistent with how R and other packages treat the MAD.
-        let number = 1.4826;
-        abs_devs.median() * number
-    }
-
-    fn median_abs_dev_pct(&self) -> f64 {
-        let hundred = 100 as f64;
-        (self.median_abs_dev() / self.median()) * hundred
-    }
-
-    fn percentile(&self, pct: f64) -> f64 {
-        let mut tmp = self.to_vec();
-        local_sort(&mut tmp);
-        percentile_of_sorted(&tmp, pct)
-    }
-
-    fn quartiles(&self) -> (f64, f64, f64) {
-        let mut tmp = self.to_vec();
-        local_sort(&mut tmp);
-        let first = 25f64;
-        let a = percentile_of_sorted(&tmp, first);
-        let second = 50f64;
-        let b = percentile_of_sorted(&tmp, second);
-        let third = 75f64;
-        let c = percentile_of_sorted(&tmp, third);
-        (a, b, c)
-    }
-
-    fn iqr(&self) -> f64 {
-        let (a, _, c) = self.quartiles();
-        c - a
-    }
-}
-
-// Helper function: extract a value representing the `pct` percentile of a sorted sample-set, using
-// linear interpolation. If samples are not sorted, return nonsensical value.
-fn percentile_of_sorted(sorted_samples: &[f64], pct: f64) -> f64 {
-    assert!(!sorted_samples.is_empty());
-    if sorted_samples.len() == 1 {
-        return sorted_samples[0];
-    }
-    let zero: f64 = 0.0;
-    assert!(zero <= pct);
-    let hundred = 100f64;
-    assert!(pct <= hundred);
-    if pct == hundred {
-        return sorted_samples[sorted_samples.len() - 1];
-    }
-    let length = (sorted_samples.len() - 1) as f64;
-    let rank = (pct / hundred) * length;
-    let lrank = rank.floor();
-    let d = rank - lrank;
-    let n = lrank as usize;
-    let lo = sorted_samples[n];
-    let hi = sorted_samples[n + 1];
-    lo + (hi - lo) * d
-}
-
-/// Winsorize a set of samples, replacing values above the `100-pct` percentile
-/// and below the `pct` percentile with those percentiles themselves. This is a
-/// way of minimizing the effect of outliers, at the cost of biasing the sample.
-/// It differs from trimming in that it does not change the number of samples,
-/// just changes the values of those that are outliers.
-///
-/// See: <http://en.wikipedia.org/wiki/Winsorising>
-pub fn winsorize(samples: &mut [f64], pct: f64) {
-    let mut tmp = samples.to_vec();
-    local_sort(&mut tmp);
-    let lo = percentile_of_sorted(&tmp, pct);
-    let hundred = 100 as f64;
-    let hi = percentile_of_sorted(&tmp, hundred - pct);
-    for samp in samples {
-        if *samp > hi {
-            *samp = hi
-        } else if *samp < lo {
-            *samp = lo
-        }
-    }
-}
-
-// Test vectors generated from R, using the script src/etc/stat-test-vectors.r.
-
-#[cfg(test)]
-mod tests {
-    use crate::stats::Stats;
-    use crate::stats::Summary;
-    use std::f64;
-    use std::io::prelude::*;
-    use std::io;
-
-    macro_rules! assert_approx_eq {
-        ($a: expr, $b: expr) => {{
-            let (a, b) = (&$a, &$b);
-            assert!(
-                (*a - *b).abs() < 1.0e-6,
-                "{} is not approximately equal to {}",
-                *a,
-                *b
-            );
-        }};
-    }
-
-    fn check(samples: &[f64], summ: &Summary) {
-        let summ2 = Summary::new(samples);
-
-        let mut w = io::sink();
-        let w = &mut w;
-        (write!(w, "\n")).unwrap();
-
-        assert_eq!(summ.sum, summ2.sum);
-        assert_eq!(summ.min, summ2.min);
-        assert_eq!(summ.max, summ2.max);
-        assert_eq!(summ.mean, summ2.mean);
-        assert_eq!(summ.median, summ2.median);
-
-        // We needed a few more digits to get exact equality on these
-        // but they're within float epsilon, which is 1.0e-6.
-        assert_approx_eq!(summ.var, summ2.var);
-        assert_approx_eq!(summ.std_dev, summ2.std_dev);
-        assert_approx_eq!(summ.std_dev_pct, summ2.std_dev_pct);
-        assert_approx_eq!(summ.median_abs_dev, summ2.median_abs_dev);
-        assert_approx_eq!(summ.median_abs_dev_pct, summ2.median_abs_dev_pct);
-
-        assert_eq!(summ.quartiles, summ2.quartiles);
-        assert_eq!(summ.iqr, summ2.iqr);
-    }
-
-    #[test]
-    fn test_min_max_nan() {
-        let xs = &[1.0, 2.0, f64::NAN, 3.0, 4.0];
-        let summary = Summary::new(xs);
-        assert_eq!(summary.min, 1.0);
-        assert_eq!(summary.max, 4.0);
-    }
-
-    #[test]
-    fn test_norm2() {
-        let val = &[958.0000000000, 924.0000000000];
-        let summ = &Summary {
-            sum: 1882.0000000000,
-            min: 924.0000000000,
-            max: 958.0000000000,
-            mean: 941.0000000000,
-            median: 941.0000000000,
-            var: 578.0000000000,
-            std_dev: 24.0416305603,
-            std_dev_pct: 2.5549022912,
-            median_abs_dev: 25.2042000000,
-            median_abs_dev_pct: 2.6784484591,
-            quartiles: (932.5000000000, 941.0000000000, 949.5000000000),
-            iqr: 17.0000000000,
-        };
-        check(val, summ);
-    }
-    #[test]
-    fn test_norm10narrow() {
-        let val = &[
-            966.0000000000,
-            985.0000000000,
-            1110.0000000000,
-            848.0000000000,
-            821.0000000000,
-            975.0000000000,
-            962.0000000000,
-            1157.0000000000,
-            1217.0000000000,
-            955.0000000000,
-        ];
-        let summ = &Summary {
-            sum: 9996.0000000000,
-            min: 821.0000000000,
-            max: 1217.0000000000,
-            mean: 999.6000000000,
-            median: 970.5000000000,
-            var: 16050.7111111111,
-            std_dev: 126.6914010938,
-            std_dev_pct: 12.6742097933,
-            median_abs_dev: 102.2994000000,
-            median_abs_dev_pct: 10.5408964451,
-            quartiles: (956.7500000000, 970.5000000000, 1078.7500000000),
-            iqr: 122.0000000000,
-        };
-        check(val, summ);
-    }
-    #[test]
-    fn test_norm10medium() {
-        let val = &[
-            954.0000000000,
-            1064.0000000000,
-            855.0000000000,
-            1000.0000000000,
-            743.0000000000,
-            1084.0000000000,
-            704.0000000000,
-            1023.0000000000,
-            357.0000000000,
-            869.0000000000,
-        ];
-        let summ = &Summary {
-            sum: 8653.0000000000,
-            min: 357.0000000000,
-            max: 1084.0000000000,
-            mean: 865.3000000000,
-            median: 911.5000000000,
-            var: 48628.4555555556,
-            std_dev: 220.5186059170,
-            std_dev_pct: 25.4846418487,
-            median_abs_dev: 195.7032000000,
-            median_abs_dev_pct: 21.4704552935,
-            quartiles: (771.0000000000, 911.5000000000, 1017.2500000000),
-            iqr: 246.2500000000,
-        };
-        check(val, summ);
-    }
-    #[test]
-    fn test_norm10wide() {
-        let val = &[
-            505.0000000000,
-            497.0000000000,
-            1591.0000000000,
-            887.0000000000,
-            1026.0000000000,
-            136.0000000000,
-            1580.0000000000,
-            940.0000000000,
-            754.0000000000,
-            1433.0000000000,
-        ];
-        let summ = &Summary {
-            sum: 9349.0000000000,
-            min: 136.0000000000,
-            max: 1591.0000000000,
-            mean: 934.9000000000,
-            median: 913.5000000000,
-            var: 239208.9888888889,
-            std_dev: 489.0899599142,
-            std_dev_pct: 52.3146817750,
-            median_abs_dev: 611.5725000000,
-            median_abs_dev_pct: 66.9482758621,
-            quartiles: (567.2500000000, 913.5000000000, 1331.2500000000),
-            iqr: 764.0000000000,
-        };
-        check(val, summ);
-    }
-    #[test]
-    fn test_norm25verynarrow() {
-        let val = &[
-            991.0000000000,
-            1018.0000000000,
-            998.0000000000,
-            1013.0000000000,
-            974.0000000000,
-            1007.0000000000,
-            1014.0000000000,
-            999.0000000000,
-            1011.0000000000,
-            978.0000000000,
-            985.0000000000,
-            999.0000000000,
-            983.0000000000,
-            982.0000000000,
-            1015.0000000000,
-            1002.0000000000,
-            977.0000000000,
-            948.0000000000,
-            1040.0000000000,
-            974.0000000000,
-            996.0000000000,
-            989.0000000000,
-            1015.0000000000,
-            994.0000000000,
-            1024.0000000000,
-        ];
-        let summ = &Summary {
-            sum: 24926.0000000000,
-            min: 948.0000000000,
-            max: 1040.0000000000,
-            mean: 997.0400000000,
-            median: 998.0000000000,
-            var: 393.2066666667,
-            std_dev: 19.8294393937,
-            std_dev_pct: 1.9888308788,
-            median_abs_dev: 22.2390000000,
-            median_abs_dev_pct: 2.2283567134,
-            quartiles: (983.0000000000, 998.0000000000, 1013.0000000000),
-            iqr: 30.0000000000,
-        };
-        check(val, summ);
-    }
-    #[test]
-    fn test_exp10a() {
-        let val = &[
-            23.0000000000,
-            11.0000000000,
-            2.0000000000,
-            57.0000000000,
-            4.0000000000,
-            12.0000000000,
-            5.0000000000,
-            29.0000000000,
-            3.0000000000,
-            21.0000000000,
-        ];
-        let summ = &Summary {
-            sum: 167.0000000000,
-            min: 2.0000000000,
-            max: 57.0000000000,
-            mean: 16.7000000000,
-            median: 11.5000000000,
-            var: 287.7888888889,
-            std_dev: 16.9643416875,
-            std_dev_pct: 101.5828843560,
-            median_abs_dev: 13.3434000000,
-            median_abs_dev_pct: 116.0295652174,
-            quartiles: (4.2500000000, 11.5000000000, 22.5000000000),
-            iqr: 18.2500000000,
-        };
-        check(val, summ);
-    }
-    #[test]
-    fn test_exp10b() {
-        let val = &[
-            24.0000000000,
-            17.0000000000,
-            6.0000000000,
-            38.0000000000,
-            25.0000000000,
-            7.0000000000,
-            51.0000000000,
-            2.0000000000,
-            61.0000000000,
-            32.0000000000,
-        ];
-        let summ = &Summary {
-            sum: 263.0000000000,
-            min: 2.0000000000,
-            max: 61.0000000000,
-            mean: 26.3000000000,
-            median: 24.5000000000,
-            var: 383.5666666667,
-            std_dev: 19.5848580967,
-            std_dev_pct: 74.4671410520,
-            median_abs_dev: 22.9803000000,
-            median_abs_dev_pct: 93.7971428571,
-            quartiles: (9.5000000000, 24.5000000000, 36.5000000000),
-            iqr: 27.0000000000,
-        };
-        check(val, summ);
-    }
-    #[test]
-    fn test_exp10c() {
-        let val = &[
-            71.0000000000,
-            2.0000000000,
-            32.0000000000,
-            1.0000000000,
-            6.0000000000,
-            28.0000000000,
-            13.0000000000,
-            37.0000000000,
-            16.0000000000,
-            36.0000000000,
-        ];
-        let summ = &Summary {
-            sum: 242.0000000000,
-            min: 1.0000000000,
-            max: 71.0000000000,
-            mean: 24.2000000000,
-            median: 22.0000000000,
-            var: 458.1777777778,
-            std_dev: 21.4050876611,
-            std_dev_pct: 88.4507754589,
-            median_abs_dev: 21.4977000000,
-            median_abs_dev_pct: 97.7168181818,
-            quartiles: (7.7500000000, 22.0000000000, 35.0000000000),
-            iqr: 27.2500000000,
-        };
-        check(val, summ);
-    }
-    #[test]
-    fn test_exp25() {
-        let val = &[
-            3.0000000000,
-            24.0000000000,
-            1.0000000000,
-            19.0000000000,
-            7.0000000000,
-            5.0000000000,
-            30.0000000000,
-            39.0000000000,
-            31.0000000000,
-            13.0000000000,
-            25.0000000000,
-            48.0000000000,
-            1.0000000000,
-            6.0000000000,
-            42.0000000000,
-            63.0000000000,
-            2.0000000000,
-            12.0000000000,
-            108.0000000000,
-            26.0000000000,
-            1.0000000000,
-            7.0000000000,
-            44.0000000000,
-            25.0000000000,
-            11.0000000000,
-        ];
-        let summ = &Summary {
-            sum: 593.0000000000,
-            min: 1.0000000000,
-            max: 108.0000000000,
-            mean: 23.7200000000,
-            median: 19.0000000000,
-            var: 601.0433333333,
-            std_dev: 24.5161851301,
-            std_dev_pct: 103.3565983562,
-            median_abs_dev: 19.2738000000,
-            median_abs_dev_pct: 101.4410526316,
-            quartiles: (6.0000000000, 19.0000000000, 31.0000000000),
-            iqr: 25.0000000000,
-        };
-        check(val, summ);
-    }
-    #[test]
-    fn test_binom25() {
-        let val = &[
-            18.0000000000,
-            17.0000000000,
-            27.0000000000,
-            15.0000000000,
-            21.0000000000,
-            25.0000000000,
-            17.0000000000,
-            24.0000000000,
-            25.0000000000,
-            24.0000000000,
-            26.0000000000,
-            26.0000000000,
-            23.0000000000,
-            15.0000000000,
-            23.0000000000,
-            17.0000000000,
-            18.0000000000,
-            18.0000000000,
-            21.0000000000,
-            16.0000000000,
-            15.0000000000,
-            31.0000000000,
-            20.0000000000,
-            17.0000000000,
-            15.0000000000,
-        ];
-        let summ = &Summary {
-            sum: 514.0000000000,
-            min: 15.0000000000,
-            max: 31.0000000000,
-            mean: 20.5600000000,
-            median: 20.0000000000,
-            var: 20.8400000000,
-            std_dev: 4.5650848842,
-            std_dev_pct: 22.2037202539,
-            median_abs_dev: 5.9304000000,
-            median_abs_dev_pct: 29.6520000000,
-            quartiles: (17.0000000000, 20.0000000000, 24.0000000000),
-            iqr: 7.0000000000,
-        };
-        check(val, summ);
-    }
-    #[test]
-    fn test_pois25lambda30() {
-        let val = &[
-            27.0000000000,
-            33.0000000000,
-            34.0000000000,
-            34.0000000000,
-            24.0000000000,
-            39.0000000000,
-            28.0000000000,
-            27.0000000000,
-            31.0000000000,
-            28.0000000000,
-            38.0000000000,
-            21.0000000000,
-            33.0000000000,
-            36.0000000000,
-            29.0000000000,
-            37.0000000000,
-            32.0000000000,
-            34.0000000000,
-            31.0000000000,
-            39.0000000000,
-            25.0000000000,
-            31.0000000000,
-            32.0000000000,
-            40.0000000000,
-            24.0000000000,
-        ];
-        let summ = &Summary {
-            sum: 787.0000000000,
-            min: 21.0000000000,
-            max: 40.0000000000,
-            mean: 31.4800000000,
-            median: 32.0000000000,
-            var: 26.5933333333,
-            std_dev: 5.1568724372,
-            std_dev_pct: 16.3814245145,
-            median_abs_dev: 5.9304000000,
-            median_abs_dev_pct: 18.5325000000,
-            quartiles: (28.0000000000, 32.0000000000, 34.0000000000),
-            iqr: 6.0000000000,
-        };
-        check(val, summ);
-    }
-    #[test]
-    fn test_pois25lambda40() {
-        let val = &[
-            42.0000000000,
-            50.0000000000,
-            42.0000000000,
-            46.0000000000,
-            34.0000000000,
-            45.0000000000,
-            34.0000000000,
-            49.0000000000,
-            39.0000000000,
-            28.0000000000,
-            40.0000000000,
-            35.0000000000,
-            37.0000000000,
-            39.0000000000,
-            46.0000000000,
-            44.0000000000,
-            32.0000000000,
-            45.0000000000,
-            42.0000000000,
-            37.0000000000,
-            48.0000000000,
-            42.0000000000,
-            33.0000000000,
-            42.0000000000,
-            48.0000000000,
-        ];
-        let summ = &Summary {
-            sum: 1019.0000000000,
-            min: 28.0000000000,
-            max: 50.0000000000,
-            mean: 40.7600000000,
-            median: 42.0000000000,
-            var: 34.4400000000,
-            std_dev: 5.8685603004,
-            std_dev_pct: 14.3978417577,
-            median_abs_dev: 5.9304000000,
-            median_abs_dev_pct: 14.1200000000,
-            quartiles: (37.0000000000, 42.0000000000, 45.0000000000),
-            iqr: 8.0000000000,
-        };
-        check(val, summ);
-    }
-    #[test]
-    fn test_pois25lambda50() {
-        let val = &[
-            45.0000000000,
-            43.0000000000,
-            44.0000000000,
-            61.0000000000,
-            51.0000000000,
-            53.0000000000,
-            59.0000000000,
-            52.0000000000,
-            49.0000000000,
-            51.0000000000,
-            51.0000000000,
-            50.0000000000,
-            49.0000000000,
-            56.0000000000,
-            42.0000000000,
-            52.0000000000,
-            51.0000000000,
-            43.0000000000,
-            48.0000000000,
-            48.0000000000,
-            50.0000000000,
-            42.0000000000,
-            43.0000000000,
-            42.0000000000,
-            60.0000000000,
-        ];
-        let summ = &Summary {
-            sum: 1235.0000000000,
-            min: 42.0000000000,
-            max: 61.0000000000,
-            mean: 49.4000000000,
-            median: 50.0000000000,
-            var: 31.6666666667,
-            std_dev: 5.6273143387,
-            std_dev_pct: 11.3913245723,
-            median_abs_dev: 4.4478000000,
-            median_abs_dev_pct: 8.8956000000,
-            quartiles: (44.0000000000, 50.0000000000, 52.0000000000),
-            iqr: 8.0000000000,
-        };
-        check(val, summ);
-    }
-    #[test]
-    fn test_unif25() {
-        let val = &[
-            99.0000000000,
-            55.0000000000,
-            92.0000000000,
-            79.0000000000,
-            14.0000000000,
-            2.0000000000,
-            33.0000000000,
-            49.0000000000,
-            3.0000000000,
-            32.0000000000,
-            84.0000000000,
-            59.0000000000,
-            22.0000000000,
-            86.0000000000,
-            76.0000000000,
-            31.0000000000,
-            29.0000000000,
-            11.0000000000,
-            41.0000000000,
-            53.0000000000,
-            45.0000000000,
-            44.0000000000,
-            98.0000000000,
-            98.0000000000,
-            7.0000000000,
-        ];
-        let summ = &Summary {
-            sum: 1242.0000000000,
-            min: 2.0000000000,
-            max: 99.0000000000,
-            mean: 49.6800000000,
-            median: 45.0000000000,
-            var: 1015.6433333333,
-            std_dev: 31.8691595957,
-            std_dev_pct: 64.1488719719,
-            median_abs_dev: 45.9606000000,
-            median_abs_dev_pct: 102.1346666667,
-            quartiles: (29.0000000000, 45.0000000000, 79.0000000000),
-            iqr: 50.0000000000,
-        };
-        check(val, summ);
-    }
-
-    #[test]
-    fn test_sum_f64s() {
-        assert_eq!([0.5f64, 3.2321f64, 1.5678f64].sum(), 5.2999);
-    }
-    #[test]
-    fn test_sum_f64_between_ints_that_sum_to_0() {
-        assert_eq!([1e30f64, 1.2f64, -1e30f64].sum(), 1.2);
-    }
-}
-
-#[cfg(test)]
-mod bench {
-    extern crate test;
-    use self::test::Bencher;
-    use crate::stats::Stats;
-
-    #[bench]
-    pub fn sum_three_items(b: &mut Bencher) {
-        b.iter(|| {
-            [1e20f64, 1.5f64, -1e20f64].sum();
-        })
-    }
-    #[bench]
-    pub fn sum_many_f64(b: &mut Bencher) {
-        let nums = [-1e30f64, 1e60, 1e30, 1.0, -1e60];
-        let v = (0..500).map(|i| nums[i % 5]).collect::<Vec<_>>();
-
-        b.iter(|| {
-            v.sum();
-        })
-    }
-
-    #[bench]
-    pub fn no_iter(_: &mut Bencher) {}
-}
diff --git a/src/llvm-project b/src/llvm-project
index 38ad31b..4fc9fb8 160000
--- a/src/llvm-project
+++ b/src/llvm-project
@@ -1 +1 @@
-Subproject commit 38ad31bde8ff681d862dc0f96930a5dd9b7a472e
+Subproject commit 4fc9fb8245abe24680192535870c4522644a4212
diff --git a/src/test/assembly/auxiliary/breakpoint-panic-handler.rs b/src/test/assembly/auxiliary/breakpoint-panic-handler.rs
new file mode 100644
index 0000000..d54c118
--- /dev/null
+++ b/src/test/assembly/auxiliary/breakpoint-panic-handler.rs
@@ -0,0 +1,8 @@
+#![feature(core_intrinsics)]
+#![no_std]
+
+#[panic_handler]
+unsafe fn breakpoint_panic_handler(_: &::core::panic::PanicInfo) -> ! {
+    core::intrinsics::breakpoint();
+    core::hint::unreachable_unchecked();
+}
diff --git a/src/test/run-make/nvptx-dylib-crate/dep.rs b/src/test/assembly/auxiliary/non-inline-dependency.rs
similarity index 100%
rename from src/test/run-make/nvptx-dylib-crate/dep.rs
rename to src/test/assembly/auxiliary/non-inline-dependency.rs
diff --git a/src/test/assembly/nvptx-arch-default.rs b/src/test/assembly/nvptx-arch-default.rs
new file mode 100644
index 0000000..7fe71c3
--- /dev/null
+++ b/src/test/assembly/nvptx-arch-default.rs
@@ -0,0 +1,12 @@
+// assembly-output: ptx-linker
+// compile-flags: --crate-type cdylib
+// only-nvptx64
+
+#![no_std]
+
+// aux-build: breakpoint-panic-handler.rs
+extern crate breakpoint_panic_handler;
+
+// Verify default target arch with ptx-linker.
+// CHECK: .target sm_30
+// CHECK: .address_size 64
diff --git a/src/test/assembly/nvptx-arch-emit-asm.rs b/src/test/assembly/nvptx-arch-emit-asm.rs
new file mode 100644
index 0000000..0ca1772
--- /dev/null
+++ b/src/test/assembly/nvptx-arch-emit-asm.rs
@@ -0,0 +1,9 @@
+// assembly-output: emit-asm
+// compile-flags: --crate-type rlib
+// only-nvptx64
+
+#![no_std]
+
+// Verify default arch without ptx-linker involved.
+// CHECK: .target sm_30
+// CHECK: .address_size 64
diff --git a/src/test/assembly/nvptx-arch-link-arg.rs b/src/test/assembly/nvptx-arch-link-arg.rs
new file mode 100644
index 0000000..f6b6e8c
--- /dev/null
+++ b/src/test/assembly/nvptx-arch-link-arg.rs
@@ -0,0 +1,12 @@
+// assembly-output: ptx-linker
+// compile-flags: --crate-type cdylib -C link-arg=--arch=sm_60
+// only-nvptx64
+
+#![no_std]
+
+// aux-build: breakpoint-panic-handler.rs
+extern crate breakpoint_panic_handler;
+
+// Verify target arch override via `link-arg`.
+// CHECK: .target sm_60
+// CHECK: .address_size 64
diff --git a/src/test/assembly/nvptx-arch-target-cpu.rs b/src/test/assembly/nvptx-arch-target-cpu.rs
new file mode 100644
index 0000000..08a7a19
--- /dev/null
+++ b/src/test/assembly/nvptx-arch-target-cpu.rs
@@ -0,0 +1,12 @@
+// assembly-output: ptx-linker
+// compile-flags: --crate-type cdylib -C target-cpu=sm_50
+// only-nvptx64
+
+#![no_std]
+
+// aux-build: breakpoint-panic-handler.rs
+extern crate breakpoint_panic_handler;
+
+// Verify target arch override via `target-cpu`.
+// CHECK: .target sm_50
+// CHECK: .address_size 64
diff --git a/src/test/assembly/nvptx-atomics.rs b/src/test/assembly/nvptx-atomics.rs
new file mode 100644
index 0000000..3bbd7b3
--- /dev/null
+++ b/src/test/assembly/nvptx-atomics.rs
@@ -0,0 +1,85 @@
+// assembly-output: ptx-linker
+// compile-flags: --crate-type cdylib
+// only-nvptx64
+
+#![feature(abi_ptx, core_intrinsics)]
+#![no_std]
+
+use core::intrinsics::*;
+
+// aux-build: breakpoint-panic-handler.rs
+extern crate breakpoint_panic_handler;
+
+// Currently, LLVM NVPTX backend can only emit atomic instructions with
+// `relaxed` (PTX default) ordering. But it's also useful to make sure
+// the backend won't fail with other orders. Apparently, the backend
+// doesn't support fences as well. As a workaround `llvm.nvvm.membar.*`
+// could work, and perhaps on the long run, all the atomic operations
+// should rather be provided by `core::arch::nvptx`.
+
+// Also, PTX ISA doesn't have atomic `load`, `store` and `nand`.
+
+// FIXME(denzp): add tests for `core::sync::atomic::*`.
+
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn atomics_kernel(a: *mut u32) {
+    // CHECK: atom.global.and.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    // CHECK: atom.global.and.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    atomic_and(a, 1);
+    atomic_and_relaxed(a, 1);
+
+    // CHECK: atom.global.cas.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1, 2;
+    // CHECK: atom.global.cas.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1, 2;
+    atomic_cxchg(a, 1, 2);
+    atomic_cxchg_relaxed(a, 1, 2);
+
+    // CHECK: atom.global.max.s32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    // CHECK: atom.global.max.s32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    atomic_max(a, 1);
+    atomic_max_relaxed(a, 1);
+
+    // CHECK: atom.global.min.s32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    // CHECK: atom.global.min.s32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    atomic_min(a, 1);
+    atomic_min_relaxed(a, 1);
+
+    // CHECK: atom.global.or.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    // CHECK: atom.global.or.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    atomic_or(a, 1);
+    atomic_or_relaxed(a, 1);
+
+    // CHECK: atom.global.max.u32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    // CHECK: atom.global.max.u32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    atomic_umax(a, 1);
+    atomic_umax_relaxed(a, 1);
+
+    // CHECK: atom.global.min.u32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    // CHECK: atom.global.min.u32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    atomic_umin(a, 1);
+    atomic_umin_relaxed(a, 1);
+
+    // CHECK: atom.global.add.u32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    // CHECK: atom.global.add.u32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    atomic_xadd(a, 1);
+    atomic_xadd_relaxed(a, 1);
+
+    // CHECK: atom.global.exch.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    // CHECK: atom.global.exch.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    atomic_xchg(a, 1);
+    atomic_xchg_relaxed(a, 1);
+
+    // CHECK: atom.global.xor.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    // CHECK: atom.global.xor.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    atomic_xor(a, 1);
+    atomic_xor_relaxed(a, 1);
+
+    // CHECK: mov.u32 %[[sub_0_arg:r[0-9]+]], 100;
+    // CHECK: neg.s32 temp, %[[sub_0_arg]];
+    // CHECK: atom.global.add.u32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], temp;
+    atomic_xsub(a, 100);
+
+    // CHECK: mov.u32 %[[sub_1_arg:r[0-9]+]], 200;
+    // CHECK: neg.s32 temp, %[[sub_1_arg]];
+    // CHECK: atom.global.add.u32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], temp;
+    atomic_xsub_relaxed(a, 200);
+}
diff --git a/src/test/assembly/nvptx-internalizing.rs b/src/test/assembly/nvptx-internalizing.rs
new file mode 100644
index 0000000..db82264
--- /dev/null
+++ b/src/test/assembly/nvptx-internalizing.rs
@@ -0,0 +1,27 @@
+// assembly-output: ptx-linker
+// compile-flags: --crate-type cdylib
+// only-nvptx64
+
+#![feature(abi_ptx)]
+#![no_std]
+
+// aux-build: breakpoint-panic-handler.rs
+extern crate breakpoint_panic_handler;
+
+// aux-build: non-inline-dependency.rs
+extern crate non_inline_dependency as dep;
+
+// Verify that no extra function declarations are present.
+// CHECK-NOT: .func
+
+// CHECK: .visible .entry top_kernel(
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn top_kernel(a: *const u32, b: *mut u32) {
+    // CHECK: add.s32 %{{r[0-9]+}}, %{{r[0-9]+}}, 5;
+    *b = *a + 5;
+}
+
+// Verify that no extra function definitions are here.
+// CHECK-NOT: .func
+// CHECK-NOT: .entry
+
diff --git a/src/test/assembly/nvptx-linking-binary.rs b/src/test/assembly/nvptx-linking-binary.rs
new file mode 100644
index 0000000..d88ed91
--- /dev/null
+++ b/src/test/assembly/nvptx-linking-binary.rs
@@ -0,0 +1,39 @@
+// assembly-output: ptx-linker
+// compile-flags: --crate-type bin
+// only-nvptx64
+
+#![feature(abi_ptx)]
+#![no_main]
+#![no_std]
+
+// aux-build: breakpoint-panic-handler.rs
+extern crate breakpoint_panic_handler;
+
+// aux-build: non-inline-dependency.rs
+extern crate non_inline_dependency as dep;
+
+// Make sure declarations are there.
+// CHECK: .func (.param .b32 func_retval0) wrapping_external_fn
+// CHECK: .func (.param .b32 func_retval0) panicking_external_fn
+
+// CHECK-LABEL: .visible .entry top_kernel(
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn top_kernel(a: *const u32, b: *mut u32) {
+    // CHECK:      call.uni (retval0),
+    // CHECK-NEXT: wrapping_external_fn
+    // CHECK:      ld.param.b32 %[[LHS:r[0-9]+]], [retval0+0];
+    let lhs = dep::wrapping_external_fn(*a);
+
+    // CHECK:      call.uni (retval0),
+    // CHECK-NEXT: panicking_external_fn
+    // CHECK:      ld.param.b32 %[[RHS:r[0-9]+]], [retval0+0];
+    let rhs = dep::panicking_external_fn(*a);
+
+    // CHECK: add.s32 %[[RES:r[0-9]+]], %[[RHS]], %[[LHS]];
+    // CHECK: st.global.u32 [%{{rd[0-9]+}}], %[[RES]];
+    *b = lhs + rhs;
+}
+
+// Verify that external function bodies are available.
+// CHECK: .func (.param .b32 func_retval0) wrapping_external_fn
+// CHECK: .func (.param .b32 func_retval0) panicking_external_fn
diff --git a/src/test/assembly/nvptx-linking-cdylib.rs b/src/test/assembly/nvptx-linking-cdylib.rs
new file mode 100644
index 0000000..1145f56
--- /dev/null
+++ b/src/test/assembly/nvptx-linking-cdylib.rs
@@ -0,0 +1,38 @@
+// assembly-output: ptx-linker
+// compile-flags: --crate-type cdylib
+// only-nvptx64
+
+#![feature(abi_ptx)]
+#![no_std]
+
+// aux-build: breakpoint-panic-handler.rs
+extern crate breakpoint_panic_handler;
+
+// aux-build: non-inline-dependency.rs
+extern crate non_inline_dependency as dep;
+
+// Make sure declarations are there.
+// CHECK: .func (.param .b32 func_retval0) wrapping_external_fn
+// CHECK: .func (.param .b32 func_retval0) panicking_external_fn
+
+// CHECK-LABEL: .visible .entry top_kernel(
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn top_kernel(a: *const u32, b: *mut u32) {
+    // CHECK:      call.uni (retval0),
+    // CHECK-NEXT: wrapping_external_fn
+    // CHECK:      ld.param.b32 %[[LHS:r[0-9]+]], [retval0+0];
+    let lhs = dep::wrapping_external_fn(*a);
+
+    // CHECK:      call.uni (retval0),
+    // CHECK-NEXT: panicking_external_fn
+    // CHECK:      ld.param.b32 %[[RHS:r[0-9]+]], [retval0+0];
+    let rhs = dep::panicking_external_fn(*a);
+
+    // CHECK: add.s32 %[[RES:r[0-9]+]], %[[RHS]], %[[LHS]];
+    // CHECK: st.global.u32 [%{{rd[0-9]+}}], %[[RES]];
+    *b = lhs + rhs;
+}
+
+// Verify that external function bodies are available.
+// CHECK: .func (.param .b32 func_retval0) wrapping_external_fn
+// CHECK: .func (.param .b32 func_retval0) panicking_external_fn
diff --git a/src/test/run-make/nvptx-emit-asm/kernel.rs b/src/test/assembly/nvptx-safe-naming.rs
similarity index 63%
rename from src/test/run-make/nvptx-emit-asm/kernel.rs
rename to src/test/assembly/nvptx-safe-naming.rs
index b71e18d..ab6f914 100644
--- a/src/test/run-make/nvptx-emit-asm/kernel.rs
+++ b/src/test/assembly/nvptx-safe-naming.rs
@@ -1,13 +1,15 @@
-#![no_std]
-#![deny(warnings)]
-#![feature(abi_ptx)]
+// assembly-output: ptx-linker
+// compile-flags: --crate-type cdylib
+// only-nvptx64
 
-// Verify the default CUDA arch.
-// CHECK: .target sm_30
-// CHECK: .address_size 64
+#![feature(abi_ptx)]
+#![no_std]
+
+// aux-build: breakpoint-panic-handler.rs
+extern crate breakpoint_panic_handler;
 
 // Verify function name doesn't contain unacceaptable characters.
-// CHECK: .func (.param .b32 func_retval0) [[IMPL_FN:_ZN[a-zA-Z0-9$_]+square[a-zA-Z0-9$_]+]]
+// CHECK: .func (.param .b32 func_retval0) [[IMPL_FN:[a-zA-Z0-9$_]+square[a-zA-Z0-9$_]+]](
 
 // CHECK-LABEL: .visible .entry top_kernel(
 #[no_mangle]
@@ -33,9 +35,3 @@
         }
     }
 }
-
-// Verify that external function bodies are available.
-// CHECK: .func (.param .b32 func_retval0) [[IMPL_FN]]
-// CHECK: {
-// CHECK:   mul.lo.s32 %{{r[0-9]+}}, %{{r[0-9]+}}, %{{r[0-9]+}}
-// CHECK: }
diff --git a/src/test/incremental/hashes/consts.rs b/src/test/incremental/hashes/consts.rs
index 0ab0915..516276a 100644
--- a/src/test/incremental/hashes/consts.rs
+++ b/src/test/incremental/hashes/consts.rs
@@ -29,7 +29,7 @@
 const CONST_CHANGE_TYPE_1: i32 = 0;
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")]
+#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
 #[rustc_clean(cfg="cfail3")]
 const CONST_CHANGE_TYPE_1: u32 = 0;
 
@@ -39,7 +39,7 @@
 const CONST_CHANGE_TYPE_2: Option<u32> = None;
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")]
+#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
 #[rustc_clean(cfg="cfail3")]
 const CONST_CHANGE_TYPE_2: Option<u64> = None;
 
@@ -99,11 +99,11 @@
     #[cfg(not(cfail1))]
     use super::ReferencedType2 as Type;
 
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")]
+    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
     #[rustc_clean(cfg="cfail3")]
     const CONST_CHANGE_TYPE_INDIRECTLY_1: Type = Type;
 
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")]
+    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
     #[rustc_clean(cfg="cfail3")]
     const CONST_CHANGE_TYPE_INDIRECTLY_2: Option<Type> = None;
 }
diff --git a/src/test/incremental/hashes/enum_defs.rs b/src/test/incremental/hashes/enum_defs.rs
index 2944762..aa2dc79 100644
--- a/src/test/incremental/hashes/enum_defs.rs
+++ b/src/test/incremental/hashes/enum_defs.rs
@@ -42,7 +42,7 @@
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")]
+#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumChangeNameCStyleVariant {
     Variant1,
@@ -59,7 +59,7 @@
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")]
+#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumChangeNameTupleStyleVariant {
     Variant1,
@@ -76,7 +76,7 @@
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")]
+#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumChangeNameStructStyleVariant {
     Variant1,
@@ -109,7 +109,7 @@
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")]
+#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumChangeValueCStyleVariant1 {
     Variant1,
@@ -125,7 +125,7 @@
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")]
+#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumAddCStyleVariant {
     Variant1,
@@ -142,7 +142,7 @@
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")]
+#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumRemoveCStyleVariant {
     Variant1,
@@ -157,7 +157,7 @@
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")]
+#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumAddTupleStyleVariant {
     Variant1,
@@ -174,7 +174,7 @@
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")]
+#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumRemoveTupleStyleVariant {
     Variant1,
@@ -189,7 +189,7 @@
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")]
+#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumAddStructStyleVariant {
     Variant1,
@@ -206,7 +206,7 @@
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")]
+#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumRemoveStructStyleVariant {
     Variant1,
@@ -257,7 +257,7 @@
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")]
+#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumChangeFieldNameStructStyleVariant {
     Variant1 { a: u32, c: u32 },
@@ -289,7 +289,7 @@
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")]
+#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumChangeFieldOrderStructStyleVariant {
     Variant1 { b: f32, a: u32 },
@@ -304,7 +304,7 @@
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")]
+#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumAddFieldTupleStyleVariant {
     Variant1(u32, u32, u32),
@@ -319,7 +319,7 @@
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")]
+#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumAddFieldStructStyleVariant {
     Variant1 { a: u32, b: u32, c: u32 },
@@ -353,7 +353,7 @@
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")]
+#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
 #[rustc_clean(cfg="cfail3")]
 #[repr(C)]
 enum EnumAddReprC {
@@ -402,7 +402,7 @@
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2", except="PredicatesOfItem")]
+#[rustc_dirty(cfg="cfail2", except="predicates_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumChangeNameOfLifetimeParameter<'b> {
     Variant1(&'b u32),
@@ -418,7 +418,7 @@
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2", except="PredicatesOfItem")]
+#[rustc_dirty(cfg="cfail2", except="predicates_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumAddLifetimeParameter<'a, 'b> {
     Variant1(&'a u32),
@@ -435,7 +435,7 @@
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2", except="GenericsOfItem,TypeOfItem")]
+#[rustc_dirty(cfg="cfail2", except="generics_of,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumAddLifetimeParameterBound<'a, 'b: 'a> {
     Variant1(&'a u32),
@@ -450,7 +450,7 @@
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2", except="TypeOfItem")]
+#[rustc_dirty(cfg="cfail2", except="type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumAddLifetimeBoundToParameter<'a, T: 'a> {
     Variant1(T),
@@ -482,7 +482,7 @@
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2", except="GenericsOfItem,TypeOfItem")]
+#[rustc_dirty(cfg="cfail2", except="generics_of,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumAddLifetimeParameterBoundWhere<'a, 'b> where 'b: 'a {
     Variant1(&'a u32),
@@ -499,7 +499,7 @@
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2", except="TypeOfItem")]
+#[rustc_dirty(cfg="cfail2", except="type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumAddLifetimeBoundToParameterWhere<'a, T> where T: 'a {
     Variant1(T),
@@ -618,7 +618,7 @@
     #[cfg(not(cfail1))]
     use super::ReferencedTrait2 as Trait;
 
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,PredicatesOfItem")]
+    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,predicates_of")]
     #[rustc_clean(cfg="cfail3")]
     enum Enum<T: Trait> {
         Variant1(T)
@@ -634,7 +634,7 @@
     #[cfg(not(cfail1))]
     use super::ReferencedTrait2 as Trait;
 
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,PredicatesOfItem")]
+    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,predicates_of")]
     #[rustc_clean(cfg="cfail3")]
     enum Enum<T> where T: Trait {
         Variant1(T)
diff --git a/src/test/incremental/hashes/function_interfaces.rs b/src/test/incremental/hashes/function_interfaces.rs
index 4330b00..fccec70 100644
--- a/src/test/incremental/hashes/function_interfaces.rs
+++ b/src/test/incremental/hashes/function_interfaces.rs
@@ -117,7 +117,7 @@
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg = "cfail2",
-              except = "Hir, HirBody, GenericsOfItem, TypeOfItem, PredicatesOfItem")]
+              except = "Hir, HirBody, generics_of, type_of, predicates_of")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn type_parameter<T>() {}
 
@@ -128,7 +128,7 @@
 pub fn lifetime_parameter() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, GenericsOfItem")]
+#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, generics_of")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn lifetime_parameter<'a>() {}
 
@@ -139,7 +139,7 @@
 pub fn trait_bound<T>() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, PredicatesOfItem")]
+#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, predicates_of")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn trait_bound<T: Eq>() {}
 
@@ -150,7 +150,7 @@
 pub fn builtin_bound<T>() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, PredicatesOfItem")]
+#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, predicates_of")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn builtin_bound<T: Send>() {}
 
@@ -162,7 +162,7 @@
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg = "cfail2",
-              except = "Hir, HirBody, GenericsOfItem, TypeOfItem, PredicatesOfItem")]
+              except = "Hir, HirBody, generics_of, type_of, predicates_of")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn lifetime_bound<'a, T: 'a>() {}
 
@@ -173,7 +173,7 @@
 pub fn second_trait_bound<T: Eq>() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, PredicatesOfItem")]
+#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, predicates_of")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn second_trait_bound<T: Eq + Clone>() {}
 
@@ -184,7 +184,7 @@
 pub fn second_builtin_bound<T: Send>() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, PredicatesOfItem")]
+#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, predicates_of")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn second_builtin_bound<T: Send + Sized>() {}
 
@@ -196,7 +196,7 @@
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg = "cfail2",
-              except = "Hir, HirBody, GenericsOfItem, TypeOfItem, PredicatesOfItem")]
+              except = "Hir, HirBody, generics_of, type_of, predicates_of")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn second_lifetime_bound<'a, 'b, T: 'a + 'b>() {}
 
@@ -326,7 +326,7 @@
     #[cfg(not(cfail1))]
     use super::ReferencedTrait2 as Trait;
 
-    #[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, PredicatesOfItem")]
+    #[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, predicates_of")]
     #[rustc_clean(cfg = "cfail3")]
     pub fn indirect_trait_bound<T: Trait>(p: T) {}
 }
@@ -340,7 +340,7 @@
     #[cfg(not(cfail1))]
     use super::ReferencedTrait2 as Trait;
 
-    #[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, PredicatesOfItem")]
+    #[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, predicates_of")]
     #[rustc_clean(cfg = "cfail3")]
     pub fn indirect_trait_bound_where<T>(p: T)
     where
diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs
index d1574ae..ebafd07 100644
--- a/src/test/incremental/hashes/inherent_impls.rs
+++ b/src/test/incremental/hashes/inherent_impls.rs
@@ -97,7 +97,7 @@
 #[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
-    #[rustc_dirty(cfg="cfail2", except="TypeOfItem,PredicatesOfItem")]
+    #[rustc_dirty(cfg="cfail2", except="type_of,predicates_of")]
     #[rustc_clean(cfg="cfail3")]
     pub fn method_selfness(&self) { }
 }
@@ -334,7 +334,7 @@
     // appear dirty, that might be the cause. -nmatsakis
     #[rustc_clean(
         cfg="cfail2",
-        except="Hir,HirBody,GenericsOfItem,PredicatesOfItem,TypeOfItem",
+        except="Hir,HirBody,generics_of,predicates_of,type_of",
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn add_type_parameter_to_method<T>(&self) { }
@@ -354,7 +354,7 @@
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
-        except="Hir,HirBody,GenericsOfItem,PredicatesOfItem,TypeOfItem,TypeckTables"
+        except="Hir,HirBody,generics_of,predicates_of,type_of,TypeckTables"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b: 'a>(&self) { }
@@ -381,8 +381,8 @@
     // generics before the body, then the `HirId` for things in the
     // body will be affected. So if you start to see `TypeckTables`
     // appear dirty, that might be the cause. -nmatsakis
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,GenericsOfItem,PredicatesOfItem,\
-                                        TypeOfItem")]
+    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,generics_of,predicates_of,\
+                                        type_of")]
     #[rustc_clean(cfg="cfail3")]
     pub fn add_lifetime_bound_to_type_param_of_method<'a, T: 'a>(&self) { }
 }
@@ -408,7 +408,7 @@
     // generics before the body, then the `HirId` for things in the
     // body will be affected. So if you start to see `TypeckTables`
     // appear dirty, that might be the cause. -nmatsakis
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,PredicatesOfItem")]
+    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,predicates_of")]
     #[rustc_clean(cfg="cfail3")]
     pub fn add_trait_bound_to_type_param_of_method<T: Clone>(&self) { }
 }
@@ -442,12 +442,12 @@
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,GenericsOfItem")]
+#[rustc_clean(cfg="cfail2", except="Hir,HirBody,generics_of")]
 #[rustc_clean(cfg="cfail3")]
 impl<T> Bar<T> {
     #[rustc_clean(
         cfg="cfail2",
-        except="GenericsOfItem,FnSignature,TypeckTables,TypeOfItem,MirOptimized,MirBuilt"
+        except="generics_of,FnSignature,TypeckTables,type_of,MirOptimized,MirBuilt"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn add_type_parameter_to_impl(&self) { }
diff --git a/src/test/incremental/hashes/statics.rs b/src/test/incremental/hashes/statics.rs
index c3db436..3bee2ac 100644
--- a/src/test/incremental/hashes/statics.rs
+++ b/src/test/incremental/hashes/statics.rs
@@ -74,7 +74,7 @@
 static STATIC_CHANGE_TYPE_1: i16 = 0;
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")]
+#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
 #[rustc_clean(cfg="cfail3")]
 static STATIC_CHANGE_TYPE_1: u64 = 0;
 
@@ -84,7 +84,7 @@
 static STATIC_CHANGE_TYPE_2: Option<i8> = None;
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")]
+#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
 #[rustc_clean(cfg="cfail3")]
 static STATIC_CHANGE_TYPE_2: Option<u16> = None;
 
@@ -144,11 +144,11 @@
     #[cfg(not(cfail1))]
     use super::ReferencedType2 as Type;
 
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")]
+    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
     #[rustc_clean(cfg="cfail3")]
     static STATIC_CHANGE_TYPE_INDIRECTLY_1: Type = Type;
 
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")]
+    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
     #[rustc_clean(cfg="cfail3")]
     static STATIC_CHANGE_TYPE_INDIRECTLY_2: Option<Type> = None;
 }
diff --git a/src/test/incremental/hashes/struct_defs.rs b/src/test/incremental/hashes/struct_defs.rs
index 9fca1ce..8d32e33 100644
--- a/src/test/incremental/hashes/struct_defs.rs
+++ b/src/test/incremental/hashes/struct_defs.rs
@@ -26,14 +26,14 @@
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_dirty(label="TypeOfItem", cfg="cfail2")]
-#[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
-#[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
+#[rustc_dirty(label="type_of", cfg="cfail2")]
+#[rustc_clean(label="generics_of", cfg="cfail2")]
+#[rustc_clean(label="predicates_of", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_clean(label="HirBody", cfg="cfail3")]
-#[rustc_clean(label="TypeOfItem", cfg="cfail3")]
-#[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
-#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
+#[rustc_clean(label="type_of", cfg="cfail3")]
+#[rustc_clean(label="generics_of", cfg="cfail3")]
+#[rustc_clean(label="predicates_of", cfg="cfail3")]
 #[repr(packed)]
 pub struct LayoutPacked;
 
@@ -43,14 +43,14 @@
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_dirty(label="TypeOfItem", cfg="cfail2")]
-#[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
-#[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
+#[rustc_dirty(label="type_of", cfg="cfail2")]
+#[rustc_clean(label="generics_of", cfg="cfail2")]
+#[rustc_clean(label="predicates_of", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_clean(label="HirBody", cfg="cfail3")]
-#[rustc_clean(label="TypeOfItem", cfg="cfail3")]
-#[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
-#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
+#[rustc_clean(label="type_of", cfg="cfail3")]
+#[rustc_clean(label="generics_of", cfg="cfail3")]
+#[rustc_clean(label="predicates_of", cfg="cfail3")]
 #[repr(C)]
 struct LayoutC;
 
@@ -63,14 +63,14 @@
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="TypeOfItem", cfg="cfail2")]
-#[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
-#[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
+#[rustc_clean(label="type_of", cfg="cfail2")]
+#[rustc_clean(label="generics_of", cfg="cfail2")]
+#[rustc_clean(label="predicates_of", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_clean(label="HirBody", cfg="cfail3")]
-#[rustc_clean(label="TypeOfItem", cfg="cfail3")]
-#[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
-#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
+#[rustc_clean(label="type_of", cfg="cfail3")]
+#[rustc_clean(label="generics_of", cfg="cfail3")]
+#[rustc_clean(label="predicates_of", cfg="cfail3")]
 // Note that changing the type of a field does not change the type of the struct or enum, but
 // adding/removing fields or changing a fields name or visibility does.
 struct TupleStructFieldType(
@@ -86,14 +86,14 @@
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_dirty(label="TypeOfItem", cfg="cfail2")]
-#[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
-#[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
+#[rustc_dirty(label="type_of", cfg="cfail2")]
+#[rustc_clean(label="generics_of", cfg="cfail2")]
+#[rustc_clean(label="predicates_of", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_clean(label="HirBody", cfg="cfail3")]
-#[rustc_clean(label="TypeOfItem", cfg="cfail3")]
-#[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
-#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
+#[rustc_clean(label="type_of", cfg="cfail3")]
+#[rustc_clean(label="generics_of", cfg="cfail3")]
+#[rustc_clean(label="predicates_of", cfg="cfail3")]
 struct TupleStructAddField(
     i32,
     u32
@@ -108,14 +108,14 @@
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_dirty(label="TypeOfItem", cfg="cfail2")]
-#[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
-#[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
+#[rustc_dirty(label="type_of", cfg="cfail2")]
+#[rustc_clean(label="generics_of", cfg="cfail2")]
+#[rustc_clean(label="predicates_of", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_clean(label="HirBody", cfg="cfail3")]
-#[rustc_clean(label="TypeOfItem", cfg="cfail3")]
-#[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
-#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
+#[rustc_clean(label="type_of", cfg="cfail3")]
+#[rustc_clean(label="generics_of", cfg="cfail3")]
+#[rustc_clean(label="predicates_of", cfg="cfail3")]
 struct TupleStructFieldVisibility(pub char);
 
 
@@ -127,14 +127,14 @@
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="TypeOfItem", cfg="cfail2")]
-#[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
-#[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
+#[rustc_clean(label="type_of", cfg="cfail2")]
+#[rustc_clean(label="generics_of", cfg="cfail2")]
+#[rustc_clean(label="predicates_of", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_clean(label="HirBody", cfg="cfail3")]
-#[rustc_clean(label="TypeOfItem", cfg="cfail3")]
-#[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
-#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
+#[rustc_clean(label="type_of", cfg="cfail3")]
+#[rustc_clean(label="generics_of", cfg="cfail3")]
+#[rustc_clean(label="predicates_of", cfg="cfail3")]
 // Note that changing the type of a field does not change the type of the struct or enum, but
 // adding/removing fields or changing a fields name or visibility does.
 struct RecordStructFieldType {
@@ -150,14 +150,14 @@
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_dirty(label="TypeOfItem", cfg="cfail2")]
-#[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
-#[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
+#[rustc_dirty(label="type_of", cfg="cfail2")]
+#[rustc_clean(label="generics_of", cfg="cfail2")]
+#[rustc_clean(label="predicates_of", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_clean(label="HirBody", cfg="cfail3")]
-#[rustc_clean(label="TypeOfItem", cfg="cfail3")]
-#[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
-#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
+#[rustc_clean(label="type_of", cfg="cfail3")]
+#[rustc_clean(label="generics_of", cfg="cfail3")]
+#[rustc_clean(label="predicates_of", cfg="cfail3")]
 struct RecordStructFieldName { y: f32 }
 
 
@@ -169,14 +169,14 @@
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_dirty(label="TypeOfItem", cfg="cfail2")]
-#[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
-#[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
+#[rustc_dirty(label="type_of", cfg="cfail2")]
+#[rustc_clean(label="generics_of", cfg="cfail2")]
+#[rustc_clean(label="predicates_of", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_clean(label="HirBody", cfg="cfail3")]
-#[rustc_clean(label="TypeOfItem", cfg="cfail3")]
-#[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
-#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
+#[rustc_clean(label="type_of", cfg="cfail3")]
+#[rustc_clean(label="generics_of", cfg="cfail3")]
+#[rustc_clean(label="predicates_of", cfg="cfail3")]
 struct RecordStructAddField {
     x: f32,
     y: () }
@@ -190,14 +190,14 @@
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_dirty(label="TypeOfItem", cfg="cfail2")]
-#[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
-#[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
+#[rustc_dirty(label="type_of", cfg="cfail2")]
+#[rustc_clean(label="generics_of", cfg="cfail2")]
+#[rustc_clean(label="predicates_of", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_clean(label="HirBody", cfg="cfail3")]
-#[rustc_clean(label="TypeOfItem", cfg="cfail3")]
-#[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
-#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
+#[rustc_clean(label="type_of", cfg="cfail3")]
+#[rustc_clean(label="generics_of", cfg="cfail3")]
+#[rustc_clean(label="predicates_of", cfg="cfail3")]
 struct RecordStructFieldVisibility {
     pub x: f32
 }
@@ -211,14 +211,14 @@
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_dirty(label="TypeOfItem", cfg="cfail2")]
-#[rustc_dirty(label="GenericsOfItem", cfg="cfail2")]
-#[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
+#[rustc_dirty(label="type_of", cfg="cfail2")]
+#[rustc_dirty(label="generics_of", cfg="cfail2")]
+#[rustc_clean(label="predicates_of", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_clean(label="HirBody", cfg="cfail3")]
-#[rustc_clean(label="TypeOfItem", cfg="cfail3")]
-#[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
-#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
+#[rustc_clean(label="type_of", cfg="cfail3")]
+#[rustc_clean(label="generics_of", cfg="cfail3")]
+#[rustc_clean(label="predicates_of", cfg="cfail3")]
 struct AddLifetimeParameter<'a, 'b>(&'a f32, &'b f64);
 
 
@@ -230,14 +230,14 @@
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="TypeOfItem", cfg="cfail2")]
-#[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
-#[rustc_dirty(label="PredicatesOfItem", cfg="cfail2")]
+#[rustc_clean(label="type_of", cfg="cfail2")]
+#[rustc_clean(label="generics_of", cfg="cfail2")]
+#[rustc_dirty(label="predicates_of", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_clean(label="HirBody", cfg="cfail3")]
-#[rustc_clean(label="TypeOfItem", cfg="cfail3")]
-#[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
-#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
+#[rustc_clean(label="type_of", cfg="cfail3")]
+#[rustc_clean(label="generics_of", cfg="cfail3")]
+#[rustc_clean(label="predicates_of", cfg="cfail3")]
 struct AddLifetimeParameterBound<'a, 'b: 'a>(
     &'a f32,
     &'b f64
@@ -249,14 +249,14 @@
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="TypeOfItem", cfg="cfail2")]
-#[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
-#[rustc_dirty(label="PredicatesOfItem", cfg="cfail2")]
+#[rustc_clean(label="type_of", cfg="cfail2")]
+#[rustc_clean(label="generics_of", cfg="cfail2")]
+#[rustc_dirty(label="predicates_of", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_clean(label="HirBody", cfg="cfail3")]
-#[rustc_clean(label="TypeOfItem", cfg="cfail3")]
-#[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
-#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
+#[rustc_clean(label="type_of", cfg="cfail3")]
+#[rustc_clean(label="generics_of", cfg="cfail3")]
+#[rustc_clean(label="predicates_of", cfg="cfail3")]
 struct AddLifetimeParameterBoundWhereClause<'a, 'b>(
     &'a f32,
     &'b f64)
@@ -271,14 +271,14 @@
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_dirty(label="TypeOfItem", cfg="cfail2")]
-#[rustc_dirty(label="GenericsOfItem", cfg="cfail2")]
-#[rustc_dirty(label="PredicatesOfItem", cfg="cfail2")]
+#[rustc_dirty(label="type_of", cfg="cfail2")]
+#[rustc_dirty(label="generics_of", cfg="cfail2")]
+#[rustc_dirty(label="predicates_of", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_clean(label="HirBody", cfg="cfail3")]
-#[rustc_clean(label="TypeOfItem", cfg="cfail3")]
-#[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
-#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
+#[rustc_clean(label="type_of", cfg="cfail3")]
+#[rustc_clean(label="generics_of", cfg="cfail3")]
+#[rustc_clean(label="predicates_of", cfg="cfail3")]
 struct AddTypeParameter<T1, T2>(
      // The field contains the parent's Generics, so it's dirty even though its
      // type hasn't changed.
@@ -295,14 +295,14 @@
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="TypeOfItem", cfg="cfail2")]
-#[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
-#[rustc_dirty(label="PredicatesOfItem", cfg="cfail2")]
+#[rustc_clean(label="type_of", cfg="cfail2")]
+#[rustc_clean(label="generics_of", cfg="cfail2")]
+#[rustc_dirty(label="predicates_of", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_clean(label="HirBody", cfg="cfail3")]
-#[rustc_clean(label="TypeOfItem", cfg="cfail3")]
-#[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
-#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
+#[rustc_clean(label="type_of", cfg="cfail3")]
+#[rustc_clean(label="generics_of", cfg="cfail3")]
+#[rustc_clean(label="predicates_of", cfg="cfail3")]
 struct AddTypeParameterBound<T: Send>(
     T
 );
@@ -314,14 +314,14 @@
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="TypeOfItem", cfg="cfail2")]
-#[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
-#[rustc_dirty(label="PredicatesOfItem", cfg="cfail2")]
+#[rustc_clean(label="type_of", cfg="cfail2")]
+#[rustc_clean(label="generics_of", cfg="cfail2")]
+#[rustc_dirty(label="predicates_of", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_clean(label="HirBody", cfg="cfail3")]
-#[rustc_clean(label="TypeOfItem", cfg="cfail3")]
-#[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
-#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
+#[rustc_clean(label="type_of", cfg="cfail3")]
+#[rustc_clean(label="generics_of", cfg="cfail3")]
+#[rustc_clean(label="predicates_of", cfg="cfail3")]
 struct AddTypeParameterBoundWhereClause<T>(
     T
 ) where T: Sync;
@@ -334,14 +334,14 @@
 // Note: there is no #[cfg(...)], so this is ALWAYS compiled
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="TypeOfItem", cfg="cfail2")]
-#[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
-#[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
+#[rustc_clean(label="type_of", cfg="cfail2")]
+#[rustc_clean(label="generics_of", cfg="cfail2")]
+#[rustc_clean(label="predicates_of", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_clean(label="HirBody", cfg="cfail3")]
-#[rustc_clean(label="TypeOfItem", cfg="cfail3")]
-#[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
-#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
+#[rustc_clean(label="type_of", cfg="cfail3")]
+#[rustc_clean(label="generics_of", cfg="cfail3")]
+#[rustc_clean(label="predicates_of", cfg="cfail3")]
 pub struct EmptyStruct;
 
 
@@ -353,14 +353,14 @@
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="TypeOfItem", cfg="cfail2")]
-#[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
-#[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
+#[rustc_clean(label="type_of", cfg="cfail2")]
+#[rustc_clean(label="generics_of", cfg="cfail2")]
+#[rustc_clean(label="predicates_of", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_clean(label="HirBody", cfg="cfail3")]
-#[rustc_clean(label="TypeOfItem", cfg="cfail3")]
-#[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
-#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
+#[rustc_clean(label="type_of", cfg="cfail3")]
+#[rustc_clean(label="generics_of", cfg="cfail3")]
+#[rustc_clean(label="predicates_of", cfg="cfail3")]
 pub struct Visibility;
 
 struct ReferencedType1;
@@ -375,14 +375,14 @@
 
     #[rustc_dirty(label="Hir", cfg="cfail2")]
     #[rustc_dirty(label="HirBody", cfg="cfail2")]
-    #[rustc_clean(label="TypeOfItem", cfg="cfail2")]
-    #[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
-    #[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
+    #[rustc_clean(label="type_of", cfg="cfail2")]
+    #[rustc_clean(label="generics_of", cfg="cfail2")]
+    #[rustc_clean(label="predicates_of", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
     #[rustc_clean(label="HirBody", cfg="cfail3")]
-    #[rustc_clean(label="TypeOfItem", cfg="cfail3")]
-    #[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
-    #[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
+    #[rustc_clean(label="type_of", cfg="cfail3")]
+    #[rustc_clean(label="generics_of", cfg="cfail3")]
+    #[rustc_clean(label="predicates_of", cfg="cfail3")]
     struct TupleStruct(
         FieldType
     );
@@ -398,14 +398,14 @@
 
     #[rustc_dirty(label="Hir", cfg="cfail2")]
     #[rustc_dirty(label="HirBody", cfg="cfail2")]
-    #[rustc_clean(label="TypeOfItem", cfg="cfail2")]
-    #[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
-    #[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
+    #[rustc_clean(label="type_of", cfg="cfail2")]
+    #[rustc_clean(label="generics_of", cfg="cfail2")]
+    #[rustc_clean(label="predicates_of", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
     #[rustc_clean(label="HirBody", cfg="cfail3")]
-    #[rustc_clean(label="TypeOfItem", cfg="cfail3")]
-    #[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
-    #[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
+    #[rustc_clean(label="type_of", cfg="cfail3")]
+    #[rustc_clean(label="generics_of", cfg="cfail3")]
+    #[rustc_clean(label="predicates_of", cfg="cfail3")]
     struct RecordStruct {
         _x: FieldType
     }
@@ -426,14 +426,14 @@
 
     #[rustc_dirty(label="Hir", cfg="cfail2")]
     #[rustc_dirty(label="HirBody", cfg="cfail2")]
-    #[rustc_clean(label="TypeOfItem", cfg="cfail2")]
-    #[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
-    #[rustc_dirty(label="PredicatesOfItem", cfg="cfail2")]
+    #[rustc_clean(label="type_of", cfg="cfail2")]
+    #[rustc_clean(label="generics_of", cfg="cfail2")]
+    #[rustc_dirty(label="predicates_of", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
     #[rustc_clean(label="HirBody", cfg="cfail3")]
-    #[rustc_clean(label="TypeOfItem", cfg="cfail3")]
-    #[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
-    #[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
+    #[rustc_clean(label="type_of", cfg="cfail3")]
+    #[rustc_clean(label="generics_of", cfg="cfail3")]
+    #[rustc_clean(label="predicates_of", cfg="cfail3")]
     struct Struct<T: Trait>(T);
 }
 
@@ -446,13 +446,13 @@
 
     #[rustc_dirty(label="Hir", cfg="cfail2")]
     #[rustc_dirty(label="HirBody", cfg="cfail2")]
-    #[rustc_clean(label="TypeOfItem", cfg="cfail2")]
-    #[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
-    #[rustc_dirty(label="PredicatesOfItem", cfg="cfail2")]
+    #[rustc_clean(label="type_of", cfg="cfail2")]
+    #[rustc_clean(label="generics_of", cfg="cfail2")]
+    #[rustc_dirty(label="predicates_of", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
     #[rustc_clean(label="HirBody", cfg="cfail3")]
-    #[rustc_clean(label="TypeOfItem", cfg="cfail3")]
-    #[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
-    #[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
+    #[rustc_clean(label="type_of", cfg="cfail3")]
+    #[rustc_clean(label="generics_of", cfg="cfail3")]
+    #[rustc_clean(label="predicates_of", cfg="cfail3")]
     struct Struct<T>(T) where T : Trait;
 }
diff --git a/src/test/mir-opt/basic_assignment.rs b/src/test/mir-opt/basic_assignment.rs
index 1bbbe67..c771013 100644
--- a/src/test/mir-opt/basic_assignment.rs
+++ b/src/test/mir-opt/basic_assignment.rs
@@ -35,7 +35,7 @@
 //        _2 = move _3;
 //        StorageDead(_3);
 //        StorageLive(_4);
-//        _4 = std::option::Option<std::boxed::Box<u32>>::None;
+//        _4 = std::option::Option::<std::boxed::Box<u32>>::None;
 //        FakeRead(ForLet, _4);
 //        AscribeUserType(_4, o, UserTypeProjection { base: UserType(1), projs: [] });
 //        StorageLive(_5);
@@ -48,7 +48,7 @@
 //        drop(_6) -> [return: bb6, unwind: bb4];
 //    }
 //    ...
-//    bb5: {
+//    bb5 (cleanup): {
 //        drop(_6) -> bb4;
 //    }
 // END rustc.main.SimplifyCfg-initial.after.mir
diff --git a/src/test/mir-opt/box_expr.rs b/src/test/mir-opt/box_expr.rs
index ad5cf42..14d302f 100644
--- a/src/test/mir-opt/box_expr.rs
+++ b/src/test/mir-opt/box_expr.rs
@@ -38,7 +38,7 @@
 //         (*_2) = const S::new() -> [return: bb2, unwind: bb3];
 //     }
 //
-//     bb1: {
+//     bb1 (cleanup): {
 //         resume;
 //     }
 //
@@ -47,7 +47,7 @@
 //         drop(_2) -> bb4;
 //     }
 //
-//     bb3: {
+//     bb3 (cleanup): {
 //         drop(_2) -> bb1;
 //     }
 //
@@ -62,11 +62,11 @@
 //         drop(_4) -> [return: bb8, unwind: bb6];
 //     }
 //
-//     bb6: {
+//     bb6 (cleanup): {
 //         drop(_1) -> bb1;
 //     }
 //
-//     bb7: {
+//     bb7 (cleanup): {
 //         drop(_4) -> bb6;
 //     }
 //
diff --git a/src/test/mir-opt/generator-drop-cleanup.rs b/src/test/mir-opt/generator-drop-cleanup.rs
new file mode 100644
index 0000000..48398691
--- /dev/null
+++ b/src/test/mir-opt/generator-drop-cleanup.rs
@@ -0,0 +1,43 @@
+#![feature(generators, generator_trait)]
+
+// Regression test for #58892, generator drop shims should not have blocks
+// spuriously marked as cleanup
+
+fn main() {
+    let gen = || {
+        yield;
+    };
+}
+
+// END RUST SOURCE
+
+// START rustc.main-{{closure}}.generator_drop.0.mir
+// bb0: {
+//     switchInt(((*_1).0: u32)) -> [0u32: bb4, 3u32: bb7, otherwise: bb8];
+// }
+// bb1: {
+//     goto -> bb5;
+// }
+// bb2: {
+//     return;
+// }
+// bb3: {
+//     return;
+// }
+// bb4: {
+//     goto -> bb6;
+// }
+// bb5: {
+//     goto -> bb2;
+// }
+// bb6: {
+//     goto -> bb3;
+// }
+// bb7: {
+//     StorageLive(_3);
+//     goto -> bb1;
+// }
+// bb8: {
+//     return;
+// }
+// END rustc.main-{{closure}}.generator_drop.0.mir
diff --git a/src/test/mir-opt/issue-38669.rs b/src/test/mir-opt/issue-38669.rs
index 618ee2f..047e623 100644
--- a/src/test/mir-opt/issue-38669.rs
+++ b/src/test/mir-opt/issue-38669.rs
@@ -18,7 +18,7 @@
 //         FakeRead(ForLet, _1);
 //         goto -> bb2;
 //     }
-//     bb1: {
+//     bb1 (cleanup): {
 //         resume;
 //     }
 //     bb2: {
diff --git a/src/test/mir-opt/issue-41697.rs b/src/test/mir-opt/issue-41697.rs
index 9db25b1..5a461d6 100644
--- a/src/test/mir-opt/issue-41697.rs
+++ b/src/test/mir-opt/issue-41697.rs
@@ -1,7 +1,7 @@
 // Regression test for #41697. Using dump-mir was triggering
 // artificial cycles: during type-checking, we had to get the MIR for
 // the constant expressions in `[u8; 2]`, which in turn would trigger
-// an attempt to get the item-path, which in turn would request the
+// an attempt to get the def-path, which in turn would request the
 // types of the impl, which would trigger a cycle. We suppressed this
 // cycle now by forcing mir-dump to avoid asking for types of an impl.
 
diff --git a/src/test/mir-opt/issue-49232.rs b/src/test/mir-opt/issue-49232.rs
index 0f0401a..5f4f4ab 100644
--- a/src/test/mir-opt/issue-49232.rs
+++ b/src/test/mir-opt/issue-49232.rs
@@ -43,7 +43,7 @@
 //         FakeRead(ForMatchedPlace, _3);
 //         switchInt(_3) -> [false: bb9, otherwise: bb8];
 //     }
-//     bb4: {
+//     bb4 (cleanup): {
 //         resume;
 //     }
 //     bb5: {
diff --git a/src/test/mir-opt/loop_test.rs b/src/test/mir-opt/loop_test.rs
index e44743a..34891ee 100644
--- a/src/test/mir-opt/loop_test.rs
+++ b/src/test/mir-opt/loop_test.rs
@@ -18,7 +18,7 @@
 // END RUST SOURCE
 // START rustc.main.SimplifyCfg-qualify-consts.after.mir
 //    ...
-//    bb1: { // The cleanup block
+//    bb1 (cleanup): {
 //        resume;
 //    }
 //    ...
diff --git a/src/test/mir-opt/match_false_edges.rs b/src/test/mir-opt/match_false_edges.rs
index ab6de71..0cbf048 100644
--- a/src/test/mir-opt/match_false_edges.rs
+++ b/src/test/mir-opt/match_false_edges.rs
@@ -42,12 +42,12 @@
 // START rustc.full_tested_match.QualifyAndPromoteConstants.after.mir
 //  bb0: {
 //      ...
-//      _2 = std::option::Option<i32>::Some(const 42i32,);
+//      _2 = std::option::Option::<i32>::Some(const 42i32,);
 //      FakeRead(ForMatchedPlace, _2);
 //      _3 = discriminant(_2);
 //      switchInt(move _3) -> [0isize: bb4, 1isize: bb2, otherwise: bb7];
 //  }
-//  bb1: {
+//  bb1 (cleanup): {
 //      resume;
 //  }
 //  bb2: {
@@ -111,12 +111,12 @@
 // START rustc.full_tested_match2.QualifyAndPromoteConstants.before.mir
 //  bb0: {
 //      ...
-//      _2 = std::option::Option<i32>::Some(const 42i32,);
+//      _2 = std::option::Option::<i32>::Some(const 42i32,);
 //      FakeRead(ForMatchedPlace, _2);
 //      _3 = discriminant(_2);
 //      switchInt(move _3) -> [0isize: bb3, 1isize: bb2, otherwise: bb7];
 //  }
-//  bb1: {
+//  bb1 (cleanup): {
 //      resume;
 //  }
 //  bb2: {
@@ -180,12 +180,12 @@
 // START rustc.main.QualifyAndPromoteConstants.before.mir
 // bb0: {
 //     ...
-//      _2 = std::option::Option<i32>::Some(const 1i32,);
+//      _2 = std::option::Option::<i32>::Some(const 1i32,);
 //      FakeRead(ForMatchedPlace, _2);
 //      _3 = discriminant(_2);
 //      switchInt(move _3) -> [1isize: bb2, otherwise: bb3];
 //  }
-//  bb1: {
+//  bb1 (cleanup): {
 //      resume;
 //  }
 //  bb2: {
diff --git a/src/test/mir-opt/packed-struct-drop-aligned.rs b/src/test/mir-opt/packed-struct-drop-aligned.rs
index 01402f2..167a6eb 100644
--- a/src/test/mir-opt/packed-struct-drop-aligned.rs
+++ b/src/test/mir-opt/packed-struct-drop-aligned.rs
@@ -38,14 +38,14 @@
 //         _6 = move (_1.0: Aligned);
 //         drop(_6) -> [return: bb4, unwind: bb3];
 //     }
-//     bb1: {
+//     bb1 (cleanup): {
 //         resume;
 //     }
 //     bb2: {
 //         StorageDead(_1);
 //         return;
 //     }
-//     bb3: {
+//     bb3 (cleanup): {
 //         (_1.0: Aligned) = move _4;
 //         drop(_1) -> bb1;
 //     }
diff --git a/src/test/mir-opt/remove_fake_borrows.rs b/src/test/mir-opt/remove_fake_borrows.rs
index 48d1c99..1443484 100644
--- a/src/test/mir-opt/remove_fake_borrows.rs
+++ b/src/test/mir-opt/remove_fake_borrows.rs
@@ -63,7 +63,7 @@
 //     StorageDead(_8);
 //     return;
 // }
-// bb10: {
+// bb10 (cleanup): {
 //     resume;
 // }
 // END rustc.match_guard.CleanupNonCodegenStatements.before.mir
@@ -114,7 +114,7 @@
 //     StorageDead(_8);
 //     return;
 // }
-// bb10: {
+// bb10 (cleanup): {
 //     resume;
 // }
 // END rustc.match_guard.CleanupNonCodegenStatements.after.mir
diff --git a/src/test/mir-opt/retag.rs b/src/test/mir-opt/retag.rs
index cdf6355..3b333b5 100644
--- a/src/test/mir-opt/retag.rs
+++ b/src/test/mir-opt/retag.rs
@@ -98,7 +98,7 @@
 // }
 // END rustc.main.EraseRegions.after.mir
 // START rustc.main-{{closure}}.EraseRegions.after.mir
-// fn main::{{closure}}(_1: &[closure@HirId { owner: DefIndex(0:7), local_id: 70 }], _2: &i32) -> &i32 {
+// fn main::{{closure}}#0(_1: &[closure@HirId { owner: DefIndex(0:7), local_id: 70 }], _2: &i32) -> &i32 {
 //     ...
 //     bb0: {
 //         Retag([fn entry] _1);
diff --git a/src/test/mir-opt/simplify_match.rs b/src/test/mir-opt/simplify_match.rs
new file mode 100644
index 0000000..0192aa0
--- /dev/null
+++ b/src/test/mir-opt/simplify_match.rs
@@ -0,0 +1,22 @@
+fn main() {
+    match { let x = false; x } {
+        true => println!("hello world!"),
+        false => {},
+    }
+}
+
+// END RUST SOURCE
+// START rustc.main.SimplifyBranches-after-copy-prop.before.mir
+// bb0: {
+//     ...
+//     switchInt(const false) -> [false: bb3, otherwise: bb1];
+// }
+// bb1: {
+// END rustc.main.SimplifyBranches-after-copy-prop.before.mir
+// START rustc.main.SimplifyBranches-after-copy-prop.after.mir
+// bb0: {
+//     ...
+//     goto -> bb3;
+// }
+// bb1: {
+// END rustc.main.SimplifyBranches-after-copy-prop.after.mir
diff --git a/src/test/mir-opt/storage_ranges.rs b/src/test/mir-opt/storage_ranges.rs
index a5d6ced..9a22f57 100644
--- a/src/test/mir-opt/storage_ranges.rs
+++ b/src/test/mir-opt/storage_ranges.rs
@@ -18,7 +18,7 @@
 //         StorageLive(_4);
 //         StorageLive(_5);
 //         _5 = _1;
-//         _4 = std::option::Option<i32>::Some(move _5,);
+//         _4 = std::option::Option::<i32>::Some(move _5,);
 //         StorageDead(_5);
 //         _3 = &_4;
 //         FakeRead(ForLet, _3);
diff --git a/src/test/mir-opt/unusual-item-types.rs b/src/test/mir-opt/unusual-item-types.rs
index fe85baa..ef41373 100644
--- a/src/test/mir-opt/unusual-item-types.rs
+++ b/src/test/mir-opt/unusual-item-types.rs
@@ -7,11 +7,18 @@
     const ASSOCIATED_CONSTANT: i32 = 2;
 }
 
+// See #59021
+enum Test {
+    X(usize),
+    Y { a: usize },
+}
+
 enum E {
     V = 5,
 }
 
 fn main() {
+    let f = Test::X as fn(usize) -> Test;
     let v = Vec::<i32>::new();
 }
 
@@ -22,7 +29,7 @@
 //     _0 = const 2i32;
 //     return;
 // }
-// bb1: {
+// bb1 (cleanup): {
 //     resume;
 // }
 // END rustc.{{impl}}-ASSOCIATED_CONSTANT.mir_map.0.mir
@@ -32,7 +39,7 @@
 //     _0 = const 5isize;
 //     return;
 // }
-// bb1: {
+// bb1 (cleanup): {
 //     resume;
 // }
 // END rustc.E-V-{{constant}}.mir_map.0.mir
@@ -44,16 +51,16 @@
 // bb1: {
 //     return;
 // }
-// bb2: {
+// bb2 (cleanup): {
 //     resume;
 // }
 // bb3: {
 //     goto -> bb1;
 // }
-// bb4: {
+// bb4 (cleanup): {
 //     goto -> bb2;
 // }
-// bb5: {
+// bb5 (cleanup): {
 //     drop(((*_1).0: alloc::raw_vec::RawVec<i32>)) -> bb4;
 // }
 // bb6: {
@@ -64,3 +71,14 @@
 //     _3 = const std::ops::Drop::drop(move _2) -> [return: bb6, unwind: bb5];
 // }
 // END rustc.ptr-real_drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir
+
+// START rustc.Test-X.mir_map.0.mir
+// fn Test::X(_1: usize) -> Test {
+//     let mut _0: Test;
+//
+//     bb0: {
+//         _0 = Test::X(move _1,);
+//         return;
+//     }
+// }
+// END rustc.Test-X.mir_map.0.mir
diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp
index b529beb..ad66341 100644
--- a/src/test/pretty/issue-4264.pp
+++ b/src/test/pretty/issue-4264.pp
@@ -32,27 +32,27 @@
                   (($crate::fmt::format as
                        for<'r> fn(std::fmt::Arguments<'r>) -> std::string::String {std::fmt::format})(((<$crate::fmt::Arguments>::new_v1
                                                                                                            as
-                                                                                                           fn(&[&str], &[std::fmt::ArgumentV1<'_>]) -> std::fmt::Arguments<'_> {std::fmt::Arguments<'_>::new_v1})((&([("test"
+                                                                                                           fn(&[&str], &[std::fmt::ArgumentV1<'_>]) -> std::fmt::Arguments<'_> {std::fmt::Arguments::<'_>::new_v1})((&([("test"
+                                                                                                                                                                                                                            as
+                                                                                                                                                                                                                            &'static str)]
                                                                                                                                                                                                                           as
-                                                                                                                                                                                                                          &'static str)]
+                                                                                                                                                                                                                          [&str; 1])
                                                                                                                                                                                                                         as
-                                                                                                                                                                                                                        [&str; 1])
-                                                                                                                                                                                                                      as
-                                                                                                                                                                                                                      &[&str; 1]),
-                                                                                                                                                                                                                  (&(match (()
+                                                                                                                                                                                                                        &[&str; 1]),
+                                                                                                                                                                                                                    (&(match (()
+                                                                                                                                                                                                                                 as
+                                                                                                                                                                                                                                 ())
+                                                                                                                                                                                                                           {
+                                                                                                                                                                                                                           ()
+                                                                                                                                                                                                                           =>
+                                                                                                                                                                                                                           ([]
                                                                                                                                                                                                                                as
-                                                                                                                                                                                                                               ())
-                                                                                                                                                                                                                         {
-                                                                                                                                                                                                                         ()
-                                                                                                                                                                                                                         =>
-                                                                                                                                                                                                                         ([]
-                                                                                                                                                                                                                             as
-                                                                                                                                                                                                                             [std::fmt::ArgumentV1<'_>; 0]),
-                                                                                                                                                                                                                     }
+                                                                                                                                                                                                                               [std::fmt::ArgumentV1<'_>; 0]),
+                                                                                                                                                                                                                       }
+                                                                                                                                                                                                                          as
+                                                                                                                                                                                                                          [std::fmt::ArgumentV1<'_>; 0])
                                                                                                                                                                                                                         as
-                                                                                                                                                                                                                        [std::fmt::ArgumentV1<'_>; 0])
-                                                                                                                                                                                                                      as
-                                                                                                                                                                                                                      &[std::fmt::ArgumentV1<'_>; 0]))
+                                                                                                                                                                                                                        &[std::fmt::ArgumentV1<'_>; 0]))
                                                                                                           as
                                                                                                           std::fmt::Arguments<'_>))
                       as std::string::String);
diff --git a/src/test/run-fail/generator-resume-after-panic.rs b/src/test/run-fail/generator-resume-after-panic.rs
new file mode 100644
index 0000000..910b490
--- /dev/null
+++ b/src/test/run-fail/generator-resume-after-panic.rs
@@ -0,0 +1,22 @@
+// error-pattern:generator resumed after panicking
+
+// Test that we get the correct message for resuming a panicked generator.
+
+#![feature(generators, generator_trait)]
+
+use std::{
+    ops::Generator,
+    pin::Pin,
+    panic,
+};
+
+fn main() {
+    let mut g = || {
+        panic!();
+        yield;
+    };
+    panic::catch_unwind(panic::AssertUnwindSafe(|| {
+        let x = Pin::new(&mut g).resume();
+    }));
+    Pin::new(&mut g).resume();
+}
diff --git a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
index 641ff18..5330470 100644
--- a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
+++ b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
@@ -3,9 +3,13 @@
 extern crate syntax;
 extern crate rustc;
 extern crate rustc_codegen_utils;
+#[macro_use]
+extern crate rustc_data_structures;
+extern crate rustc_target;
 
 use std::any::Any;
-use std::sync::mpsc;
+use std::sync::{Arc, mpsc};
+use std::path::Path;
 use syntax::symbol::Symbol;
 use rustc::session::Session;
 use rustc::session::config::OutputFilenames;
@@ -14,21 +18,44 @@
 use rustc::middle::cstore::MetadataLoader;
 use rustc::dep_graph::DepGraph;
 use rustc::util::common::ErrorReported;
-use rustc_codegen_utils::codegen_backend::{CodegenBackend, MetadataOnlyCodegenBackend};
+use rustc_codegen_utils::codegen_backend::CodegenBackend;
+use rustc_data_structures::sync::MetadataRef;
+use rustc_data_structures::owning_ref::OwningRef;
+use rustc_target::spec::Target;
 
-struct TheBackend(Box<CodegenBackend>);
+pub struct NoLlvmMetadataLoader;
+
+impl MetadataLoader for NoLlvmMetadataLoader {
+    fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result<MetadataRef, String> {
+        let buf = std::fs::read(filename).map_err(|e| format!("metadata file open err: {:?}", e))?;
+        let buf: OwningRef<Vec<u8>, [u8]> = OwningRef::new(buf);
+        Ok(rustc_erase_owner!(buf.map_owner_box()))
+    }
+
+    fn get_dylib_metadata(&self, target: &Target, filename: &Path) -> Result<MetadataRef, String> {
+        self.get_rlib_metadata(target, filename)
+    }
+}
+
+struct TheBackend;
 
 impl CodegenBackend for TheBackend {
     fn metadata_loader(&self) -> Box<MetadataLoader + Sync> {
-        self.0.metadata_loader()
+        Box::new(NoLlvmMetadataLoader)
     }
 
     fn provide(&self, providers: &mut Providers) {
-        self.0.provide(providers);
+        rustc_codegen_utils::symbol_names::provide(providers);
+
+        providers.target_features_whitelist = |_tcx, _cnum| {
+            Default::default() // Just a dummy
+        };
+        providers.is_reachable_non_generic = |_tcx, _defid| true;
+        providers.exported_symbols = |_tcx, _crate| Arc::new(Vec::new());
     }
 
     fn provide_extern(&self, providers: &mut Providers) {
-        self.0.provide_extern(providers);
+        providers.is_reachable_non_generic = |_tcx, _defid| true;
     }
 
     fn codegen_crate<'a, 'tcx>(
@@ -69,5 +96,5 @@
 /// This is the entrypoint for a hot plugged rustc_codegen_llvm
 #[no_mangle]
 pub fn __rustc_codegen_backend() -> Box<CodegenBackend> {
-    Box::new(TheBackend(MetadataOnlyCodegenBackend::boxed()))
+    Box::new(TheBackend)
 }
diff --git a/src/test/run-make-fulldeps/redundant-libs/Makefile b/src/test/run-make-fulldeps/redundant-libs/Makefile
new file mode 100644
index 0000000..9486e07
--- /dev/null
+++ b/src/test/run-make-fulldeps/redundant-libs/Makefile
@@ -0,0 +1,27 @@
+-include ../tools.mk
+
+ifdef IS_WINDOWS
+all:
+else
+
+# rustc will remove one of the two redundant references to foo below.  Depending
+# on which one gets removed, we'll get a linker error on SOME platforms (like
+# Linux).  On these platforms, when a library is referenced, the linker will
+# only pull in the symbols needed _at that point in time_.  If a later library
+# depends on additional symbols from the library, they will not have been pulled
+# in, and you'll get undefined symbols errors.
+#
+# So in this example, we need to ensure that rustc keeps the _later_ reference
+# to foo, and not the former one.
+RUSTC_FLAGS = \
+    -l static=bar \
+    -l foo \
+    -l static=baz \
+    -l foo \
+    -Z print-link-args
+
+all: $(call DYLIB,foo) $(call STATICLIB,bar) $(call STATICLIB,baz)
+	$(RUSTC) $(RUSTC_FLAGS) main.rs
+	$(call RUN,main)
+
+endif
diff --git a/src/test/run-make-fulldeps/redundant-libs/bar.c b/src/test/run-make-fulldeps/redundant-libs/bar.c
new file mode 100644
index 0000000..e425999
--- /dev/null
+++ b/src/test/run-make-fulldeps/redundant-libs/bar.c
@@ -0,0 +1 @@
+void bar() {}
diff --git a/src/test/run-make-fulldeps/redundant-libs/baz.c b/src/test/run-make-fulldeps/redundant-libs/baz.c
new file mode 100644
index 0000000..a4e2c2b
--- /dev/null
+++ b/src/test/run-make-fulldeps/redundant-libs/baz.c
@@ -0,0 +1,7 @@
+extern void foo1();
+extern void foo2();
+
+void baz() {
+  foo1();
+  foo2();
+}
diff --git a/src/test/run-make-fulldeps/redundant-libs/foo.c b/src/test/run-make-fulldeps/redundant-libs/foo.c
new file mode 100644
index 0000000..339ee86
--- /dev/null
+++ b/src/test/run-make-fulldeps/redundant-libs/foo.c
@@ -0,0 +1,2 @@
+void foo1() {}
+void foo2() {}
diff --git a/src/test/run-make-fulldeps/redundant-libs/main.rs b/src/test/run-make-fulldeps/redundant-libs/main.rs
new file mode 100644
index 0000000..90d185f
--- /dev/null
+++ b/src/test/run-make-fulldeps/redundant-libs/main.rs
@@ -0,0 +1,11 @@
+extern "C" {
+    fn bar();
+    fn baz();
+}
+
+fn main() {
+    unsafe {
+        bar();
+        baz();
+    }
+}
diff --git a/src/test/run-make/nvptx-binary-crate/Makefile b/src/test/run-make/nvptx-binary-crate/Makefile
deleted file mode 100644
index 2c211b5..0000000
--- a/src/test/run-make/nvptx-binary-crate/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
--include ../../run-make-fulldeps/tools.mk
-
-ifeq ($(TARGET),nvptx64-nvidia-cuda)
-all:
-	$(RUSTC) main.rs --crate-type="bin" --target $(TARGET) -O -C link-arg=--arch=sm_60 -o $(TMPDIR)/main.link_arg.ptx
-	$(RUSTC) main.rs --crate-type="bin" --target $(TARGET) -O -C target-cpu=sm_60 -o $(TMPDIR)/main.target_cpu.ptx
-
-	FileCheck main.rs --input-file $(TMPDIR)/main.link_arg.ptx
-	FileCheck main.rs --input-file $(TMPDIR)/main.target_cpu.ptx
-else
-all:
-endif
diff --git a/src/test/run-make/nvptx-binary-crate/main.rs b/src/test/run-make/nvptx-binary-crate/main.rs
deleted file mode 100644
index 826bc3a..0000000
--- a/src/test/run-make/nvptx-binary-crate/main.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-#![no_std]
-#![no_main]
-#![deny(warnings)]
-#![feature(abi_ptx, core_intrinsics)]
-
-// Check the overriden CUDA arch.
-// CHECK: .target sm_60
-// CHECK: .address_size 64
-
-// Verify that no extra function declarations are present.
-// CHECK-NOT: .func
-
-// CHECK-LABEL: .visible .entry top_kernel(
-#[no_mangle]
-pub unsafe extern "ptx-kernel" fn top_kernel(a: *const u32, b: *mut u32) {
-    // CHECK: add.s32 %{{r[0-9]+}}, %{{r[0-9]+}}, 5;
-    *b = *a + 5;
-}
-
-// Verify that no extra function definitions are there.
-// CHECK-NOT: .func
-// CHECK-NOT: .entry
-
-#[panic_handler]
-unsafe fn breakpoint_panic_handler(_: &::core::panic::PanicInfo) -> ! {
-    core::intrinsics::breakpoint();
-    core::hint::unreachable_unchecked();
-}
diff --git a/src/test/run-make/nvptx-dylib-crate/Makefile b/src/test/run-make/nvptx-dylib-crate/Makefile
deleted file mode 100644
index 7284e9d..0000000
--- a/src/test/run-make/nvptx-dylib-crate/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
--include ../../run-make-fulldeps/tools.mk
-
-ifeq ($(TARGET),nvptx64-nvidia-cuda)
-all:
-	$(RUSTC) dep.rs --crate-type="rlib" --target $(TARGET)
-	$(RUSTC) kernel.rs --crate-type="cdylib" -O --target $(TARGET)
-	FileCheck kernel.rs --input-file $(TMPDIR)/kernel.ptx
-else
-all:
-endif
diff --git a/src/test/run-make/nvptx-dylib-crate/kernel.rs b/src/test/run-make/nvptx-dylib-crate/kernel.rs
deleted file mode 100644
index 63fd6b0..0000000
--- a/src/test/run-make/nvptx-dylib-crate/kernel.rs
+++ /dev/null
@@ -1,59 +0,0 @@
-#![no_std]
-#![deny(warnings)]
-#![feature(abi_ptx, core_intrinsics)]
-
-extern crate dep;
-
-// Verify the default CUDA arch.
-// CHECK: .target sm_30
-// CHECK: .address_size 64
-
-// Make sure declarations are there.
-// CHECK: .func (.param .b32 func_retval0) wrapping_external_fn
-// CHECK: .func (.param .b32 func_retval0) panicking_external_fn
-// CHECK: .func [[PANIC_HANDLER:_ZN4core9panicking5panic[a-zA-Z0-9]+]]
-
-// CHECK-LABEL: .visible .entry top_kernel(
-#[no_mangle]
-pub unsafe extern "ptx-kernel" fn top_kernel(a: *const u32, b: *mut u32) {
-    // CHECK:      call.uni (retval0),
-    // CHECK-NEXT: wrapping_external_fn
-    // CHECK:      ld.param.b32 %[[LHS:r[0-9]+]], [retval0+0];
-    let lhs = dep::wrapping_external_fn(*a);
-
-    // CHECK:      call.uni (retval0),
-    // CHECK-NEXT: panicking_external_fn
-    // CHECK:      ld.param.b32 %[[RHS:r[0-9]+]], [retval0+0];
-    let rhs = dep::panicking_external_fn(*a);
-
-    // CHECK: add.s32 %[[RES:r[0-9]+]], %[[RHS]], %[[LHS]];
-    // CHECK: st.global.u32 [%{{rd[0-9]+}}], %[[RES]];
-    *b = lhs + rhs;
-}
-
-// Verify that external function bodies are available.
-// CHECK-LABEL: .func (.param .b32 func_retval0) wrapping_external_fn
-// CHECK: {
-// CHECK:   st.param.b32 [func_retval0+0], %{{r[0-9]+}};
-// CHECK: }
-
-// Also verify panic behavior.
-// CHECK-LABEL: .func (.param .b32 func_retval0) panicking_external_fn
-// CHECK: {
-// CHECK:   %{{p[0-9]+}} bra [[PANIC_LABEL:[a-zA-Z0-9_]+]];
-// CHECK: [[PANIC_LABEL]]:
-// CHECK:   call.uni
-// CHECK:   [[PANIC_HANDLER]]
-// CHECK: }
-
-// Verify whether out dummy panic formatter has a correct body.
-// CHECK: .func [[PANIC_FMT:_ZN4core9panicking9panic_fmt[a-zA-Z0-9]+]]()
-// CHECK: {
-// CHECK:   trap;
-// CHECK: }
-
-#[panic_handler]
-unsafe fn breakpoint_panic_handler(_: &::core::panic::PanicInfo) -> ! {
-    core::intrinsics::breakpoint();
-    core::hint::unreachable_unchecked();
-}
diff --git a/src/test/run-make/nvptx-emit-asm/Makefile b/src/test/run-make/nvptx-emit-asm/Makefile
deleted file mode 100644
index e036018..0000000
--- a/src/test/run-make/nvptx-emit-asm/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
--include ../../run-make-fulldeps/tools.mk
-
-ifeq ($(TARGET),nvptx64-nvidia-cuda)
-all:
-	$(RUSTC) kernel.rs --crate-type="rlib" --emit asm,llvm-ir -O --target $(TARGET)
-	FileCheck kernel.rs --input-file $(TMPDIR)/kernel.s
-else
-all:
-endif
diff --git a/src/test/run-pass-fulldeps/undef_mask.rs b/src/test/run-pass-fulldeps/undef_mask.rs
new file mode 100644
index 0000000..cf6e6f7
--- /dev/null
+++ b/src/test/run-pass-fulldeps/undef_mask.rs
@@ -0,0 +1,26 @@
+// ignore-cross-compile
+// ignore-stage1
+
+#![feature(rustc_private)]
+
+extern crate rustc;
+
+use rustc::mir::interpret::UndefMask;
+use rustc::ty::layout::Size;
+
+fn main() {
+    let mut mask = UndefMask::new(Size::from_bytes(500), false);
+    assert!(!mask.get(Size::from_bytes(499)));
+    mask.set(Size::from_bytes(499), true);
+    assert!(mask.get(Size::from_bytes(499)));
+    mask.set_range_inbounds(Size::from_bytes(100), Size::from_bytes(256), true);
+    for i in 0..100 {
+        assert!(!mask.get(Size::from_bytes(i)));
+    }
+    for i in 100..256 {
+        assert!(mask.get(Size::from_bytes(i)));
+    }
+    for i in 256..499 {
+        assert!(!mask.get(Size::from_bytes(i)));
+    }
+}
diff --git a/src/test/run-pass/array-slice-vec/estr-slice.rs b/src/test/run-pass/array-slice-vec/estr-slice.rs
index 02b88f6..cd2c172 100644
--- a/src/test/run-pass/array-slice-vec/estr-slice.rs
+++ b/src/test/run-pass/array-slice-vec/estr-slice.rs
@@ -14,7 +14,7 @@
 
     let z : &str = "thing";
     assert_eq!(v, x);
-    assert!(x != z);
+    assert_ne!(x, z);
 
     let a = "aaaa";
     let b = "bbbb";
@@ -26,7 +26,7 @@
 
     assert!(a < b);
     assert!(a <= b);
-    assert!(a != b);
+    assert_ne!(a, b);
     assert!(b >= a);
     assert!(b > a);
 
@@ -34,7 +34,7 @@
 
     assert!(a < c);
     assert!(a <= c);
-    assert!(a != c);
+    assert_ne!(a, c);
     assert!(c >= a);
     assert!(c > a);
 
@@ -42,7 +42,7 @@
 
     assert!(c < cc);
     assert!(c <= cc);
-    assert!(c != cc);
+    assert_ne!(c, cc);
     assert!(cc >= c);
     assert!(cc > c);
 
diff --git a/src/test/run-pass/issue-55809.rs b/src/test/run-pass/issue-55809.rs
new file mode 100644
index 0000000..86b0977
--- /dev/null
+++ b/src/test/run-pass/issue-55809.rs
@@ -0,0 +1,30 @@
+// edition:2018
+// run-pass
+
+#![feature(async_await, await_macro, futures_api)]
+
+trait Foo { }
+
+impl Foo for () { }
+
+impl<'a, T> Foo for &'a mut T where T: Foo { }
+
+async fn foo_async<T>(_v: T) -> u8 where T: Foo {
+    0
+}
+
+async fn bad<T>(v: T) -> u8 where T: Foo {
+    await!(foo_async(v))
+}
+
+async fn async_main() {
+    let mut v = ();
+
+    let _ = await!(bad(&mut v));
+    let _ = await!(foo_async(&mut v));
+    let _ = await!(bad(v));
+}
+
+fn main() {
+    let _ = async_main();
+}
diff --git a/src/test/run-pass/issues/issue-57924.rs b/src/test/run-pass/issues/issue-57924.rs
new file mode 100644
index 0000000..2325963
--- /dev/null
+++ b/src/test/run-pass/issues/issue-57924.rs
@@ -0,0 +1,9 @@
+pub struct Gcm<E>(E);
+
+impl<E> Gcm<E> {
+    pub fn crash(e: E) -> Self {
+        Self::<E>(e)
+    }
+}
+
+fn main() {}
diff --git a/src/test/run-pass/simd/simd-size-align.rs b/src/test/run-pass/simd/simd-size-align.rs
index 0a53707..5560137 100644
--- a/src/test/run-pass/simd/simd-size-align.rs
+++ b/src/test/run-pass/simd/simd-size-align.rs
@@ -37,6 +37,22 @@
     check::<f32x6>();
     check::<f32x7>();
     check::<f32x8>();
+
+    check::<usizex2>();
+    check::<usizex3>();
+    check::<usizex4>();
+    check::<usizex5>();
+    check::<usizex6>();
+    check::<usizex7>();
+    check::<usizex8>();
+
+    check::<isizex2>();
+    check::<isizex3>();
+    check::<isizex4>();
+    check::<isizex5>();
+    check::<isizex6>();
+    check::<isizex7>();
+    check::<isizex8>();
 }
 
 #[repr(simd)] struct u8x2(u8, u8);
@@ -62,3 +78,19 @@
 #[repr(simd)] struct f32x6(f32, f32, f32, f32, f32, f32);
 #[repr(simd)] struct f32x7(f32, f32, f32, f32, f32, f32, f32);
 #[repr(simd)] struct f32x8(f32, f32, f32, f32, f32, f32, f32, f32);
+
+#[repr(simd)] struct usizex2(usize, usize);
+#[repr(simd)] struct usizex3(usize, usize, usize);
+#[repr(simd)] struct usizex4(usize, usize, usize, usize);
+#[repr(simd)] struct usizex5(usize, usize, usize, usize, usize);
+#[repr(simd)] struct usizex6(usize, usize, usize, usize, usize, usize);
+#[repr(simd)] struct usizex7(usize, usize, usize, usize, usize, usize, usize);
+#[repr(simd)] struct usizex8(usize, usize, usize, usize, usize, usize, usize, usize);
+
+#[repr(simd)] struct isizex2(isize, isize);
+#[repr(simd)] struct isizex3(isize, isize, isize);
+#[repr(simd)] struct isizex4(isize, isize, isize, isize);
+#[repr(simd)] struct isizex5(isize, isize, isize, isize, isize);
+#[repr(simd)] struct isizex6(isize, isize, isize, isize, isize, isize);
+#[repr(simd)] struct isizex7(isize, isize, isize, isize, isize, isize, isize);
+#[repr(simd)] struct isizex8(isize, isize, isize, isize, isize, isize, isize, isize);
diff --git a/src/test/rustdoc-ui/intra-links-ambiguity.rs b/src/test/rustdoc-ui/intra-links-ambiguity.rs
new file mode 100644
index 0000000..7316fcd
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-links-ambiguity.rs
@@ -0,0 +1,36 @@
+#![deny(intra_doc_link_resolution_failure)]
+#![allow(non_camel_case_types)]
+#![allow(non_upper_case_globals)]
+
+pub fn ambiguous() {}
+
+pub struct ambiguous {}
+
+#[macro_export]
+macro_rules! multi_conflict { () => {} }
+
+#[allow(non_camel_case_types)]
+pub struct multi_conflict {}
+
+pub fn multi_conflict() {}
+
+pub mod type_and_value {}
+
+pub const type_and_value: i32 = 0;
+
+pub mod foo {
+    pub enum bar {}
+
+    pub fn bar() {}
+}
+
+/// [`ambiguous`] is ambiguous. //~ERROR `ambiguous`
+///
+/// [ambiguous] is ambiguous. //~ERROR ambiguous
+///
+/// [`multi_conflict`] is a three-way conflict. //~ERROR `multi_conflict`
+///
+/// Ambiguous [type_and_value]. //~ERROR type_and_value
+///
+/// Ambiguous non-implied shortcut link [`foo::bar`]. //~ERROR `foo::bar`
+pub struct Docs {}
diff --git a/src/test/rustdoc-ui/intra-links-ambiguity.stderr b/src/test/rustdoc-ui/intra-links-ambiguity.stderr
new file mode 100644
index 0000000..5d66cc1
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-links-ambiguity.stderr
@@ -0,0 +1,82 @@
+error: `ambiguous` is both a struct and a function
+  --> $DIR/intra-links-ambiguity.rs:27:6
+   |
+LL | /// [`ambiguous`] is ambiguous.
+   |      ^^^^^^^^^^^ ambiguous link
+   |
+note: lint level defined here
+  --> $DIR/intra-links-ambiguity.rs:1:9
+   |
+LL | #![deny(intra_doc_link_resolution_failure)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: to link to the struct, prefix with the item type
+   |
+LL | /// [`struct@ambiguous`] is ambiguous.
+   |      ^^^^^^^^^^^^^^^^^^
+help: to link to the function, add parentheses
+   |
+LL | /// [`ambiguous()`] is ambiguous.
+   |      ^^^^^^^^^^^^^
+
+error: `ambiguous` is both a struct and a function
+  --> $DIR/intra-links-ambiguity.rs:29:6
+   |
+LL | /// [ambiguous] is ambiguous.
+   |      ^^^^^^^^^ ambiguous link
+help: to link to the struct, prefix with the item type
+   |
+LL | /// [struct@ambiguous] is ambiguous.
+   |      ^^^^^^^^^^^^^^^^
+help: to link to the function, add parentheses
+   |
+LL | /// [ambiguous()] is ambiguous.
+   |      ^^^^^^^^^^^
+
+error: `multi_conflict` is a struct, a function, and a macro
+  --> $DIR/intra-links-ambiguity.rs:31:6
+   |
+LL | /// [`multi_conflict`] is a three-way conflict.
+   |      ^^^^^^^^^^^^^^^^ ambiguous link
+help: to link to the struct, prefix with the item type
+   |
+LL | /// [`struct@multi_conflict`] is a three-way conflict.
+   |      ^^^^^^^^^^^^^^^^^^^^^^^
+help: to link to the function, add parentheses
+   |
+LL | /// [`multi_conflict()`] is a three-way conflict.
+   |      ^^^^^^^^^^^^^^^^^^
+help: to link to the macro, add an exclamation mark
+   |
+LL | /// [`multi_conflict!`] is a three-way conflict.
+   |      ^^^^^^^^^^^^^^^^^
+
+error: `type_and_value` is both a module and a constant
+  --> $DIR/intra-links-ambiguity.rs:33:16
+   |
+LL | /// Ambiguous [type_and_value].
+   |                ^^^^^^^^^^^^^^ ambiguous link
+help: to link to the module, prefix with the item type
+   |
+LL | /// Ambiguous [module@type_and_value].
+   |                ^^^^^^^^^^^^^^^^^^^^^
+help: to link to the constant, prefix with the item type
+   |
+LL | /// Ambiguous [const@type_and_value].
+   |                ^^^^^^^^^^^^^^^^^^^^
+
+error: `foo::bar` is both an enum and a function
+  --> $DIR/intra-links-ambiguity.rs:35:42
+   |
+LL | /// Ambiguous non-implied shortcut link [`foo::bar`].
+   |                                          ^^^^^^^^^^ ambiguous link
+help: to link to the enum, prefix with the item type
+   |
+LL | /// Ambiguous non-implied shortcut link [`enum@foo::bar`].
+   |                                          ^^^^^^^^^^^^^^^
+help: to link to the function, add parentheses
+   |
+LL | /// Ambiguous non-implied shortcut link [`foo::bar()`].
+   |                                          ^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/rustdoc/default_trait_method.rs b/src/test/rustdoc/default_trait_method.rs
new file mode 100644
index 0000000..dfbd8f2
--- /dev/null
+++ b/src/test/rustdoc/default_trait_method.rs
@@ -0,0 +1,15 @@
+#![feature(specialization)]
+
+pub trait Item {
+    fn foo();
+    fn bar();
+}
+
+// @has default_trait_method/trait.Item.html
+// @has - '//*[@id="method.foo"]' 'default fn foo()'
+// @has - '//*[@id="method.bar"]' 'fn bar()'
+// @!has - '//*[@id="method.bar"]' 'default fn bar()'
+impl<T: ?Sized> Item for T {
+    default fn foo() {}
+    fn bar() {}
+}
diff --git a/src/test/rustdoc/intra-links.rs b/src/test/rustdoc/intra-links.rs
index 9139fc5..c356ab3 100644
--- a/src/test/rustdoc/intra-links.rs
+++ b/src/test/rustdoc/intra-links.rs
@@ -22,6 +22,7 @@
 //! * [`ThisType::this_method`](ThisType::this_method)
 //! * [`ThisEnum`](ThisEnum)
 //! * [`ThisEnum::ThisVariant`](ThisEnum::ThisVariant)
+//! * [`ThisEnum::ThisVariantCtor`](ThisEnum::ThisVariantCtor)
 //! * [`ThisTrait`](ThisTrait)
 //! * [`ThisTrait::this_associated_method`](ThisTrait::this_associated_method)
 //! * [`ThisTrait::ThisAssociatedType`](ThisTrait::ThisAssociatedType)
@@ -50,7 +51,7 @@
 impl ThisType {
     pub fn this_method() {}
 }
-pub enum ThisEnum { ThisVariant, }
+pub enum ThisEnum { ThisVariant, ThisVariantCtor(u32), }
 pub trait ThisTrait {
     type ThisAssociatedType;
     const THIS_ASSOCIATED_CONST: u8;
diff --git a/src/test/ui/E0501.ast.nll.stderr b/src/test/ui/E0501.ast.nll.stderr
index 1d0102d..74f14beb 100644
--- a/src/test/ui/E0501.ast.nll.stderr
+++ b/src/test/ui/E0501.ast.nll.stderr
@@ -6,7 +6,7 @@
 LL |         inside_closure(a)
    |                        - first borrow occurs due to use of `a` in closure
 LL |     };
-LL |     outside_closure_1(a); //[ast]~ ERROR cannot borrow `*a` as mutable because previous closure requires unique access
+LL |     outside_closure_1(a);
    |                       ^ second borrow occurs here
 ...
 LL |     drop(bar);
@@ -20,7 +20,7 @@
 LL |         inside_closure(a)
    |                        - first borrow occurs due to use of `a` in closure
 ...
-LL |     outside_closure_2(a); //[ast]~ ERROR cannot borrow `*a` as immutable because previous closure requires unique access
+LL |     outside_closure_2(a);
    |                       ^ second borrow occurs here
 ...
 LL |     drop(bar);
diff --git a/src/test/ui/E0501.ast.stderr b/src/test/ui/E0501.ast.stderr
index e0bd7a0..e2f54c6 100644
--- a/src/test/ui/E0501.ast.stderr
+++ b/src/test/ui/E0501.ast.stderr
@@ -6,7 +6,7 @@
 LL |         inside_closure(a)
    |                        - previous borrow occurs due to use of `a` in closure
 LL |     };
-LL |     outside_closure_1(a); //[ast]~ ERROR cannot borrow `*a` as mutable because previous closure requires unique access
+LL |     outside_closure_1(a);
    |                       ^ borrow occurs here
 ...
 LL | }
@@ -20,7 +20,7 @@
 LL |         inside_closure(a)
    |                        - previous borrow occurs due to use of `a` in closure
 ...
-LL |     outside_closure_2(a); //[ast]~ ERROR cannot borrow `*a` as immutable because previous closure requires unique access
+LL |     outside_closure_2(a);
    |                       ^ borrow occurs here
 ...
 LL | }
diff --git a/src/test/ui/E0501.mir.stderr b/src/test/ui/E0501.mir.stderr
index 1d0102d..74f14beb 100644
--- a/src/test/ui/E0501.mir.stderr
+++ b/src/test/ui/E0501.mir.stderr
@@ -6,7 +6,7 @@
 LL |         inside_closure(a)
    |                        - first borrow occurs due to use of `a` in closure
 LL |     };
-LL |     outside_closure_1(a); //[ast]~ ERROR cannot borrow `*a` as mutable because previous closure requires unique access
+LL |     outside_closure_1(a);
    |                       ^ second borrow occurs here
 ...
 LL |     drop(bar);
@@ -20,7 +20,7 @@
 LL |         inside_closure(a)
    |                        - first borrow occurs due to use of `a` in closure
 ...
-LL |     outside_closure_2(a); //[ast]~ ERROR cannot borrow `*a` as immutable because previous closure requires unique access
+LL |     outside_closure_2(a);
    |                       ^ second borrow occurs here
 ...
 LL |     drop(bar);
diff --git a/src/test/ui/E0506.ast.nll.stderr b/src/test/ui/E0506.ast.nll.stderr
index b66c1d1..6e2d634 100644
--- a/src/test/ui/E0506.ast.nll.stderr
+++ b/src/test/ui/E0506.ast.nll.stderr
@@ -3,7 +3,7 @@
    |
 LL |     let fancy_ref = &fancy_num;
    |                     ---------- borrow of `fancy_num` occurs here
-LL |     fancy_num = FancyNum { num: 6 }; //[ast]~ ERROR E0506
+LL |     fancy_num = FancyNum { num: 6 };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `fancy_num` occurs here
 ...
 LL |     println!("Num: {}, Ref: {}", fancy_num.num, fancy_ref.num);
diff --git a/src/test/ui/E0506.ast.stderr b/src/test/ui/E0506.ast.stderr
index d459dcd..3e3001f 100644
--- a/src/test/ui/E0506.ast.stderr
+++ b/src/test/ui/E0506.ast.stderr
@@ -3,7 +3,7 @@
    |
 LL |     let fancy_ref = &fancy_num;
    |                      --------- borrow of `fancy_num` occurs here
-LL |     fancy_num = FancyNum { num: 6 }; //[ast]~ ERROR E0506
+LL |     fancy_num = FancyNum { num: 6 };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `fancy_num` occurs here
 
 error: aborting due to previous error
diff --git a/src/test/ui/E0506.mir.stderr b/src/test/ui/E0506.mir.stderr
index b66c1d1..6e2d634 100644
--- a/src/test/ui/E0506.mir.stderr
+++ b/src/test/ui/E0506.mir.stderr
@@ -3,7 +3,7 @@
    |
 LL |     let fancy_ref = &fancy_num;
    |                     ---------- borrow of `fancy_num` occurs here
-LL |     fancy_num = FancyNum { num: 6 }; //[ast]~ ERROR E0506
+LL |     fancy_num = FancyNum { num: 6 };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `fancy_num` occurs here
 ...
 LL |     println!("Num: {}, Ref: {}", fancy_num.num, fancy_ref.num);
diff --git a/src/test/ui/E0508-fail.ast.nll.stderr b/src/test/ui/E0508-fail.ast.nll.stderr
index 4cc1cf8..972b84e 100644
--- a/src/test/ui/E0508-fail.ast.nll.stderr
+++ b/src/test/ui/E0508-fail.ast.nll.stderr
@@ -1,7 +1,7 @@
 error[E0508]: cannot move out of type `[NonCopy; 1]`, a non-copy array
   --> $DIR/E0508-fail.rs:8:18
    |
-LL |     let _value = array[0];  //[ast]~ ERROR [E0508]
+LL |     let _value = array[0];
    |                  ^^^^^^^^
    |                  |
    |                  cannot move out of here
diff --git a/src/test/ui/E0508-fail.ast.stderr b/src/test/ui/E0508-fail.ast.stderr
index 57959c9..8b24983 100644
--- a/src/test/ui/E0508-fail.ast.stderr
+++ b/src/test/ui/E0508-fail.ast.stderr
@@ -1,7 +1,7 @@
 error[E0508]: cannot move out of type `[NonCopy; 1]`, a non-copy array
   --> $DIR/E0508-fail.rs:8:18
    |
-LL |     let _value = array[0];  //[ast]~ ERROR [E0508]
+LL |     let _value = array[0];
    |                  ^^^^^^^^
    |                  |
    |                  cannot move out of here
diff --git a/src/test/ui/E0508-fail.mir.stderr b/src/test/ui/E0508-fail.mir.stderr
index 4cc1cf8..972b84e 100644
--- a/src/test/ui/E0508-fail.mir.stderr
+++ b/src/test/ui/E0508-fail.mir.stderr
@@ -1,7 +1,7 @@
 error[E0508]: cannot move out of type `[NonCopy; 1]`, a non-copy array
   --> $DIR/E0508-fail.rs:8:18
    |
-LL |     let _value = array[0];  //[ast]~ ERROR [E0508]
+LL |     let _value = array[0];
    |                  ^^^^^^^^
    |                  |
    |                  cannot move out of here
diff --git a/src/test/ui/E0508.ast.stderr b/src/test/ui/E0508.ast.stderr
deleted file mode 100644
index 5878b79..0000000
--- a/src/test/ui/E0508.ast.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0508]: cannot move out of type `[NonCopy; 1]`, a non-copy array
-  --> $DIR/E0508.rs:18:18
-   |
-LL |     let _value = array[0];  //[ast]~ ERROR [E0508]
-   |                  ^^^^^^^^
-   |                  |
-   |                  cannot move out of here
-   |                  help: consider using a reference instead: `&array[0]`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0508`.
diff --git a/src/test/ui/E0508.mir.stderr b/src/test/ui/E0508.mir.stderr
deleted file mode 100644
index 5878b79..0000000
--- a/src/test/ui/E0508.mir.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0508]: cannot move out of type `[NonCopy; 1]`, a non-copy array
-  --> $DIR/E0508.rs:18:18
-   |
-LL |     let _value = array[0];  //[ast]~ ERROR [E0508]
-   |                  ^^^^^^^^
-   |                  |
-   |                  cannot move out of here
-   |                  help: consider using a reference instead: `&array[0]`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0508`.
diff --git a/src/test/ui/E0594.ast.nll.stderr b/src/test/ui/E0594.ast.nll.stderr
index 54681a2..cc1c968 100644
--- a/src/test/ui/E0594.ast.nll.stderr
+++ b/src/test/ui/E0594.ast.nll.stderr
@@ -1,7 +1,7 @@
 error[E0594]: cannot assign to immutable static item `NUM`
   --> $DIR/E0594.rs:7:5
    |
-LL |     NUM = 20; //[ast]~ ERROR E0594
+LL |     NUM = 20;
    |     ^^^^^^^^ cannot assign
 
 error: aborting due to previous error
diff --git a/src/test/ui/E0594.ast.stderr b/src/test/ui/E0594.ast.stderr
index 4eb9ba1..0c5316d 100644
--- a/src/test/ui/E0594.ast.stderr
+++ b/src/test/ui/E0594.ast.stderr
@@ -1,7 +1,7 @@
 error[E0594]: cannot assign to immutable static item
   --> $DIR/E0594.rs:7:5
    |
-LL |     NUM = 20; //[ast]~ ERROR E0594
+LL |     NUM = 20;
    |     ^^^^^^^^
 
 error: aborting due to previous error
diff --git a/src/test/ui/E0594.mir.stderr b/src/test/ui/E0594.mir.stderr
index 54681a2..cc1c968 100644
--- a/src/test/ui/E0594.mir.stderr
+++ b/src/test/ui/E0594.mir.stderr
@@ -1,7 +1,7 @@
 error[E0594]: cannot assign to immutable static item `NUM`
   --> $DIR/E0594.rs:7:5
    |
-LL |     NUM = 20; //[ast]~ ERROR E0594
+LL |     NUM = 20;
    |     ^^^^^^^^ cannot assign
 
 error: aborting due to previous error
diff --git a/src/test/ui/E0596.ast.nll.stderr b/src/test/ui/E0596.ast.nll.stderr
index e5da664..c89a915 100644
--- a/src/test/ui/E0596.ast.nll.stderr
+++ b/src/test/ui/E0596.ast.nll.stderr
@@ -3,7 +3,7 @@
    |
 LL |     let x = 1;
    |         - help: consider changing this to be mutable: `mut x`
-LL |     let y = &mut x; //[ast]~ ERROR [E0596]
+LL |     let y = &mut x;
    |             ^^^^^^ cannot borrow as mutable
 
 error: aborting due to previous error
diff --git a/src/test/ui/E0596.ast.stderr b/src/test/ui/E0596.ast.stderr
index 6e65cc8..4b66e49 100644
--- a/src/test/ui/E0596.ast.stderr
+++ b/src/test/ui/E0596.ast.stderr
@@ -3,7 +3,7 @@
    |
 LL |     let x = 1;
    |         - help: make this binding mutable: `mut x`
-LL |     let y = &mut x; //[ast]~ ERROR [E0596]
+LL |     let y = &mut x;
    |                  ^ cannot borrow mutably
 
 error: aborting due to previous error
diff --git a/src/test/ui/E0596.mir.stderr b/src/test/ui/E0596.mir.stderr
index e5da664..c89a915 100644
--- a/src/test/ui/E0596.mir.stderr
+++ b/src/test/ui/E0596.mir.stderr
@@ -3,7 +3,7 @@
    |
 LL |     let x = 1;
    |         - help: consider changing this to be mutable: `mut x`
-LL |     let y = &mut x; //[ast]~ ERROR [E0596]
+LL |     let y = &mut x;
    |             ^^^^^^ cannot borrow as mutable
 
 error: aborting due to previous error
diff --git a/src/test/ui/assign-imm-local-twice.ast.nll.stderr b/src/test/ui/assign-imm-local-twice.ast.nll.stderr
index 311a83a..2995a13 100644
--- a/src/test/ui/assign-imm-local-twice.ast.nll.stderr
+++ b/src/test/ui/assign-imm-local-twice.ast.nll.stderr
@@ -4,10 +4,10 @@
 LL |     let v: isize;
    |         - help: make this binding mutable: `mut v`
 ...
-LL |     v = 1; //[ast]~ NOTE first assignment
+LL |     v = 1;
    |     ----- first assignment to `v`
 ...
-LL |     v = 2; //[ast]~ ERROR cannot assign twice to immutable variable
+LL |     v = 2;
    |     ^^^^^ cannot assign twice to immutable variable
 
 error: aborting due to previous error
diff --git a/src/test/ui/assign-imm-local-twice.ast.stderr b/src/test/ui/assign-imm-local-twice.ast.stderr
index d57acb2..f16b8e2 100644
--- a/src/test/ui/assign-imm-local-twice.ast.stderr
+++ b/src/test/ui/assign-imm-local-twice.ast.stderr
@@ -1,10 +1,10 @@
 error[E0384]: cannot assign twice to immutable variable `v`
   --> $DIR/assign-imm-local-twice.rs:11:5
    |
-LL |     v = 1; //[ast]~ NOTE first assignment
+LL |     v = 1;
    |     ----- first assignment to `v`
 ...
-LL |     v = 2; //[ast]~ ERROR cannot assign twice to immutable variable
+LL |     v = 2;
    |     ^^^^^ cannot assign twice to immutable variable
 
 error: aborting due to previous error
diff --git a/src/test/ui/assign-imm-local-twice.mir.stderr b/src/test/ui/assign-imm-local-twice.mir.stderr
index 311a83a..2995a13 100644
--- a/src/test/ui/assign-imm-local-twice.mir.stderr
+++ b/src/test/ui/assign-imm-local-twice.mir.stderr
@@ -4,10 +4,10 @@
 LL |     let v: isize;
    |         - help: make this binding mutable: `mut v`
 ...
-LL |     v = 1; //[ast]~ NOTE first assignment
+LL |     v = 1;
    |     ----- first assignment to `v`
 ...
-LL |     v = 2; //[ast]~ ERROR cannot assign twice to immutable variable
+LL |     v = 2;
    |     ^^^^^ cannot assign twice to immutable variable
 
 error: aborting due to previous error
diff --git a/src/test/ui/associated-types/associated-types-eq-3.stderr b/src/test/ui/associated-types/associated-types-eq-3.stderr
index c1a8e20..31d2c5f 100644
--- a/src/test/ui/associated-types/associated-types-eq-3.stderr
+++ b/src/test/ui/associated-types/associated-types-eq-3.stderr
@@ -29,7 +29,7 @@
    |
    = note: expected type `usize`
               found type `Bar`
-   = note: required for the cast to the object type `dyn Foo<A=Bar>`
+   = note: required for the cast to the object type `dyn Foo<A = Bar>`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr b/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr
index 8c0e557..ad0b651 100644
--- a/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr
+++ b/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr
@@ -6,7 +6,7 @@
    |
    = note: expected type `u32`
               found type `i32`
-   = note: required for the cast to the object type `dyn I32Iterator<Item=u32, Item=i32>`
+   = note: required for the cast to the object type `dyn I32Iterator<Item = u32, Item = i32>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr b/src/test/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr
index 3a5ff9d..fcdb371 100644
--- a/src/test/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr
+++ b/src/test/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr
@@ -1,7 +1,7 @@
 error: compilation successful
   --> $DIR/bound-lifetime-in-binding-only.rs:71:1
    |
-LL | fn main() { } //[ok]~ ERROR compilation successful
+LL | fn main() { }
    | ^^^^^^^^^^^^^
 
 error: aborting due to previous error
diff --git a/src/test/ui/associated-types/bound-lifetime-in-return-only.ok.stderr b/src/test/ui/associated-types/bound-lifetime-in-return-only.ok.stderr
index 650383b..504d68e 100644
--- a/src/test/ui/associated-types/bound-lifetime-in-return-only.ok.stderr
+++ b/src/test/ui/associated-types/bound-lifetime-in-return-only.ok.stderr
@@ -1,7 +1,7 @@
 error: compilation successful
   --> $DIR/bound-lifetime-in-return-only.rs:49:1
    |
-LL | fn main() { } //[ok]~ ERROR compilation successful
+LL | fn main() { }
    | ^^^^^^^^^^^^^
 
 error: aborting due to previous error
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.krisskross.stderr b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.krisskross.stderr
index 0fed413..fa4c6ad 100644
--- a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.krisskross.stderr
+++ b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.krisskross.stderr
@@ -6,7 +6,7 @@
    |                        |
    |                        this parameter and the return type are declared with different lifetimes...
 ...
-LL |    (a, b) //[krisskross]~ ERROR lifetime mismatch [E0623]
+LL |    (a, b)
    |     ^ ...but data from `y` is returned here
 
 error[E0623]: lifetime mismatch
@@ -17,7 +17,7 @@
    |                                    |
    |                                    this parameter and the return type are declared with different lifetimes...
 ...
-LL |    (a, b) //[krisskross]~ ERROR lifetime mismatch [E0623]
+LL |    (a, b)
    |        ^ ...but data from `x` is returned here
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr
index ab14836..4309373 100644
--- a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr
+++ b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr
@@ -1,7 +1,7 @@
 error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
   --> $DIR/project-fn-ret-contravariant.rs:38:8
    |
-LL |    bar(foo, x) //[transmute]~ ERROR E0495
+LL |    bar(foo, x)
    |        ^^^
    |
 note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 37:8...
@@ -12,13 +12,13 @@
 note: ...so that reference does not outlive borrowed content
   --> $DIR/project-fn-ret-contravariant.rs:38:13
    |
-LL |    bar(foo, x) //[transmute]~ ERROR E0495
+LL |    bar(foo, x)
    |             ^
    = note: but, the lifetime must be valid for the static lifetime...
 note: ...so that reference does not outlive borrowed content
   --> $DIR/project-fn-ret-contravariant.rs:38:4
    |
-LL |    bar(foo, x) //[transmute]~ ERROR E0495
+LL |    bar(foo, x)
    |    ^^^^^^^^^^^
 
 error: aborting due to previous error
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr
index fa831ea..5009e08 100644
--- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr
+++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr
@@ -5,7 +5,7 @@
    |                                     --------     --------------------
    |                                     |
    |                                     this parameter and the return type are declared with different lifetimes...
-LL |    let a = bar(foo, y); //[krisskross]~ ERROR E0623
+LL |    let a = bar(foo, y);
    |                     ^ ...but data from `x` is returned here
 
 error[E0623]: lifetime mismatch
@@ -15,8 +15,8 @@
    |                        --------                  --------------------
    |                        |
    |                        this parameter and the return type are declared with different lifetimes...
-LL |    let a = bar(foo, y); //[krisskross]~ ERROR E0623
-LL |    let b = bar(foo, x); //[krisskross]~ ERROR E0623
+LL |    let a = bar(foo, y);
+LL |    let b = bar(foo, x);
    |                     ^ ...but data from `y` is returned here
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr
index 6b78d66..65d16440 100644
--- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr
+++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr
@@ -6,7 +6,7 @@
    |                               |
    |                               this parameter and the return type are declared with different lifetimes...
 ...
-LL |    let b = bar(f, y); //[oneuse]~ ERROR lifetime mismatch [E0623]
+LL |    let b = bar(f, y);
    |                   ^ ...but data from `x` is returned here
 
 error: aborting due to previous error
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr
index dd1212e..b8b1a97 100644
--- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr
+++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr
@@ -1,7 +1,7 @@
 error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
   --> $DIR/project-fn-ret-invariant.rs:48:8
    |
-LL |    bar(foo, x) //[transmute]~ ERROR E0495
+LL |    bar(foo, x)
    |        ^^^
    |
 note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 44:8...
diff --git a/src/test/ui/associated-types/higher-ranked-projection.good.stderr b/src/test/ui/associated-types/higher-ranked-projection.good.stderr
index 165e521..16fef05 100644
--- a/src/test/ui/associated-types/higher-ranked-projection.good.stderr
+++ b/src/test/ui/associated-types/higher-ranked-projection.good.stderr
@@ -1,9 +1,9 @@
 error: compilation successful
   --> $DIR/higher-ranked-projection.rs:24:1
    |
-LL | / fn main() { //[good]~ ERROR compilation successful
+LL | / fn main() {
 LL | |     foo(());
-LL | |     //[bad]~^ ERROR type mismatch
+LL | |
 LL | | }
    | |_^
 
diff --git a/src/test/ui/bad/bad-sized.stderr b/src/test/ui/bad/bad-sized.stderr
index 9565888..51b8474 100644
--- a/src/test/ui/bad/bad-sized.stderr
+++ b/src/test/ui/bad/bad-sized.stderr
@@ -22,7 +22,7 @@
    |
    = help: the trait `std::marker::Sized` is not implemented for `dyn Trait`
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
-   = note: required by `<std::vec::Vec<T>>::new`
+   = note: required by `std::vec::Vec::<T>::new`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-access-permissions.ast.nll.stderr b/src/test/ui/borrowck/borrowck-access-permissions.ast.nll.stderr
index 0d771a5..12f9ad8 100644
--- a/src/test/ui/borrowck/borrowck-access-permissions.ast.nll.stderr
+++ b/src/test/ui/borrowck/borrowck-access-permissions.ast.nll.stderr
@@ -4,13 +4,13 @@
 LL |     let x = 1;
    |         - help: consider changing this to be mutable: `mut x`
 ...
-LL |         let _y1 = &mut x; //[ast]~ ERROR [E0596]
+LL |         let _y1 = &mut x;
    |                   ^^^^^^ cannot borrow as mutable
 
 error[E0596]: cannot borrow immutable static item `static_x` as mutable
   --> $DIR/borrowck-access-permissions.rs:18:19
    |
-LL |         let _y1 = &mut static_x; //[ast]~ ERROR [E0596]
+LL |         let _y1 = &mut static_x;
    |                   ^^^^^^^^^^^^^ cannot borrow as mutable
 
 error[E0596]: cannot borrow `*box_x` as mutable, as `box_x` is not declared as mutable
@@ -19,7 +19,7 @@
 LL |         let box_x = Box::new(1);
    |             ----- help: consider changing this to be mutable: `mut box_x`
 ...
-LL |         let _y1 = &mut *box_x; //[ast]~ ERROR [E0596]
+LL |         let _y1 = &mut *box_x;
    |                   ^^^^^^^^^^^ cannot borrow as mutable
 
 error[E0596]: cannot borrow `*ref_x` as mutable, as it is behind a `&` reference
@@ -28,7 +28,7 @@
 LL |         let ref_x = &x;
    |                     -- help: consider changing this to be a mutable reference: `&mut x`
 ...
-LL |         let _y1 = &mut *ref_x; //[ast]~ ERROR [E0596]
+LL |         let _y1 = &mut *ref_x;
    |                   ^^^^^^^^^^^ `ref_x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
 error[E0596]: cannot borrow `*ptr_x` as mutable, as it is behind a `*const` pointer
@@ -37,7 +37,7 @@
 LL |         let ptr_x : *const _ = &x;
    |                                -- help: consider changing this to be a mutable pointer: `&mut x`
 ...
-LL |             let _y1 = &mut *ptr_x; //[ast]~ ERROR [E0596]
+LL |             let _y1 = &mut *ptr_x;
    |                       ^^^^^^^^^^^ `ptr_x` is a `*const` pointer, so the data it refers to cannot be borrowed as mutable
 
 error[E0596]: cannot borrow `*foo_ref.f` as mutable, as it is behind a `&` reference
@@ -45,7 +45,7 @@
    |
 LL |         let foo_ref = &foo;
    |                       ---- help: consider changing this to be a mutable reference: `&mut foo`
-LL |         let _y = &mut *foo_ref.f; //[ast]~ ERROR [E0389]
+LL |         let _y = &mut *foo_ref.f;
    |                  ^^^^^^^^^^^^^^^ `foo_ref` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
 error: aborting due to 6 previous errors
diff --git a/src/test/ui/borrowck/borrowck-access-permissions.ast.stderr b/src/test/ui/borrowck/borrowck-access-permissions.ast.stderr
index 4b0e261..a1cc063 100644
--- a/src/test/ui/borrowck/borrowck-access-permissions.ast.stderr
+++ b/src/test/ui/borrowck/borrowck-access-permissions.ast.stderr
@@ -4,13 +4,13 @@
 LL |     let x = 1;
    |         - help: make this binding mutable: `mut x`
 ...
-LL |         let _y1 = &mut x; //[ast]~ ERROR [E0596]
+LL |         let _y1 = &mut x;
    |                        ^ cannot borrow mutably
 
 error[E0596]: cannot borrow immutable static item as mutable
   --> $DIR/borrowck-access-permissions.rs:18:24
    |
-LL |         let _y1 = &mut static_x; //[ast]~ ERROR [E0596]
+LL |         let _y1 = &mut static_x;
    |                        ^^^^^^^^
 
 error[E0596]: cannot borrow immutable `Box` content `*box_x` as mutable
@@ -19,25 +19,25 @@
 LL |         let box_x = Box::new(1);
    |             ----- help: make this binding mutable: `mut box_x`
 ...
-LL |         let _y1 = &mut *box_x; //[ast]~ ERROR [E0596]
+LL |         let _y1 = &mut *box_x;
    |                        ^^^^^^ cannot borrow as mutable
 
 error[E0596]: cannot borrow immutable borrowed content `*ref_x` as mutable
   --> $DIR/borrowck-access-permissions.rs:36:24
    |
-LL |         let _y1 = &mut *ref_x; //[ast]~ ERROR [E0596]
+LL |         let _y1 = &mut *ref_x;
    |                        ^^^^^^ cannot borrow as mutable
 
 error[E0596]: cannot borrow immutable dereference of raw pointer `*ptr_x` as mutable
   --> $DIR/borrowck-access-permissions.rs:46:28
    |
-LL |             let _y1 = &mut *ptr_x; //[ast]~ ERROR [E0596]
+LL |             let _y1 = &mut *ptr_x;
    |                            ^^^^^^ cannot borrow as mutable
 
 error[E0389]: cannot borrow data mutably in a `&` reference
   --> $DIR/borrowck-access-permissions.rs:56:23
    |
-LL |         let _y = &mut *foo_ref.f; //[ast]~ ERROR [E0389]
+LL |         let _y = &mut *foo_ref.f;
    |                       ^^^^^^^^^^ assignment into an immutable reference
 
 error: aborting due to 6 previous errors
diff --git a/src/test/ui/borrowck/borrowck-access-permissions.mir.stderr b/src/test/ui/borrowck/borrowck-access-permissions.mir.stderr
index 0d771a5..12f9ad8 100644
--- a/src/test/ui/borrowck/borrowck-access-permissions.mir.stderr
+++ b/src/test/ui/borrowck/borrowck-access-permissions.mir.stderr
@@ -4,13 +4,13 @@
 LL |     let x = 1;
    |         - help: consider changing this to be mutable: `mut x`
 ...
-LL |         let _y1 = &mut x; //[ast]~ ERROR [E0596]
+LL |         let _y1 = &mut x;
    |                   ^^^^^^ cannot borrow as mutable
 
 error[E0596]: cannot borrow immutable static item `static_x` as mutable
   --> $DIR/borrowck-access-permissions.rs:18:19
    |
-LL |         let _y1 = &mut static_x; //[ast]~ ERROR [E0596]
+LL |         let _y1 = &mut static_x;
    |                   ^^^^^^^^^^^^^ cannot borrow as mutable
 
 error[E0596]: cannot borrow `*box_x` as mutable, as `box_x` is not declared as mutable
@@ -19,7 +19,7 @@
 LL |         let box_x = Box::new(1);
    |             ----- help: consider changing this to be mutable: `mut box_x`
 ...
-LL |         let _y1 = &mut *box_x; //[ast]~ ERROR [E0596]
+LL |         let _y1 = &mut *box_x;
    |                   ^^^^^^^^^^^ cannot borrow as mutable
 
 error[E0596]: cannot borrow `*ref_x` as mutable, as it is behind a `&` reference
@@ -28,7 +28,7 @@
 LL |         let ref_x = &x;
    |                     -- help: consider changing this to be a mutable reference: `&mut x`
 ...
-LL |         let _y1 = &mut *ref_x; //[ast]~ ERROR [E0596]
+LL |         let _y1 = &mut *ref_x;
    |                   ^^^^^^^^^^^ `ref_x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
 error[E0596]: cannot borrow `*ptr_x` as mutable, as it is behind a `*const` pointer
@@ -37,7 +37,7 @@
 LL |         let ptr_x : *const _ = &x;
    |                                -- help: consider changing this to be a mutable pointer: `&mut x`
 ...
-LL |             let _y1 = &mut *ptr_x; //[ast]~ ERROR [E0596]
+LL |             let _y1 = &mut *ptr_x;
    |                       ^^^^^^^^^^^ `ptr_x` is a `*const` pointer, so the data it refers to cannot be borrowed as mutable
 
 error[E0596]: cannot borrow `*foo_ref.f` as mutable, as it is behind a `&` reference
@@ -45,7 +45,7 @@
    |
 LL |         let foo_ref = &foo;
    |                       ---- help: consider changing this to be a mutable reference: `&mut foo`
-LL |         let _y = &mut *foo_ref.f; //[ast]~ ERROR [E0389]
+LL |         let _y = &mut *foo_ref.f;
    |                  ^^^^^^^^^^^^^^^ `foo_ref` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
 error: aborting due to 6 previous errors
diff --git a/src/test/ui/borrowck/borrowck-asm.ast.nll.stderr b/src/test/ui/borrowck/borrowck-asm.ast.nll.stderr
index 86e4832..dd6e5eb 100644
--- a/src/test/ui/borrowck/borrowck-asm.ast.nll.stderr
+++ b/src/test/ui/borrowck/borrowck-asm.ast.nll.stderr
@@ -7,7 +7,7 @@
 LL |             asm!("nop" : : "r"(x));
    |                                - value moved here
 LL |         }
-LL |         let z = x;  //[ast]~ ERROR use of moved value: `x`
+LL |         let z = x;
    |                 ^ value used here after move
 
 error[E0503]: cannot use `x` because it was mutably borrowed
@@ -16,7 +16,7 @@
 LL |         let y = &mut x;
    |                 ------ borrow of `x` occurs here
 LL |         unsafe {
-LL |             asm!("nop" : : "r"(x)); //[ast]~ ERROR cannot use
+LL |             asm!("nop" : : "r"(x));
    |                                ^ use of borrowed `x`
 ...
 LL |         let z = y;
@@ -31,7 +31,7 @@
    |             first assignment to `x`
    |             help: make this binding mutable: `mut x`
 LL |         unsafe {
-LL |             asm!("nop" : "=r"(x));  //[ast]~ ERROR cannot assign twice
+LL |             asm!("nop" : "=r"(x));
    |                               ^ cannot assign twice to immutable variable
 
 error[E0384]: cannot assign twice to immutable variable `x`
@@ -43,13 +43,13 @@
    |             first assignment to `x`
    |             help: make this binding mutable: `mut x`
 LL |         unsafe {
-LL |             asm!("nop" : "+r"(x));  //[ast]~ ERROR cannot assign twice
+LL |             asm!("nop" : "+r"(x));
    |                               ^ cannot assign twice to immutable variable
 
 error[E0381]: use of possibly uninitialized variable: `x`
   --> $DIR/borrowck-asm.rs:68:32
    |
-LL |             asm!("nop" : "=*r"(x)); //[ast]~ ERROR use of possibly uninitialized variable
+LL |             asm!("nop" : "=*r"(x));
    |                                ^ use of possibly uninitialized `x`
 
 error[E0506]: cannot assign to `x` because it is borrowed
@@ -58,7 +58,7 @@
 LL |         let y = &*x;
    |                 --- borrow of `x` occurs here
 LL |         unsafe {
-LL |             asm!("nop" : "+r"(x));  //[ast]~ ERROR cannot assign to `x` because it is borrowed
+LL |             asm!("nop" : "+r"(x));
    |                               ^ assignment to borrowed `x` occurs here
 ...
 LL |         let z = y;
@@ -70,7 +70,7 @@
 LL |         let x = &mut 2;
    |             - move occurs because `x` has type `&mut i32`, which does not implement the `Copy` trait
 LL |         unsafe {
-LL |             asm!("nop" : : "r"(x), "r"(x) );    //[ast]~ ERROR use of moved value
+LL |             asm!("nop" : : "r"(x), "r"(x) );
    |                                -       ^ value used here after move
    |                                |
    |                                value moved here
diff --git a/src/test/ui/borrowck/borrowck-asm.ast.stderr b/src/test/ui/borrowck/borrowck-asm.ast.stderr
index 73eb08b..8418bb7 100644
--- a/src/test/ui/borrowck/borrowck-asm.ast.stderr
+++ b/src/test/ui/borrowck/borrowck-asm.ast.stderr
@@ -4,7 +4,7 @@
 LL |             asm!("nop" : : "r"(x));
    |                                - value moved here
 LL |         }
-LL |         let z = x;  //[ast]~ ERROR use of moved value: `x`
+LL |         let z = x;
    |             ^ value used here after move
    |
    = note: move occurs because `x` has type `&mut isize`, which does not implement the `Copy` trait
@@ -15,7 +15,7 @@
 LL |         let y = &mut x;
    |                      - borrow of `x` occurs here
 LL |         unsafe {
-LL |             asm!("nop" : : "r"(x)); //[ast]~ ERROR cannot use
+LL |             asm!("nop" : : "r"(x));
    |                                ^ use of borrowed `x`
 
 error[E0384]: cannot assign twice to immutable variable `x`
@@ -24,7 +24,7 @@
 LL |         let x = 3;
    |             - first assignment to `x`
 LL |         unsafe {
-LL |             asm!("nop" : "=r"(x));  //[ast]~ ERROR cannot assign twice
+LL |             asm!("nop" : "=r"(x));
    |                               ^ cannot assign twice to immutable variable
 
 error[E0506]: cannot assign to `a` because it is borrowed
@@ -33,7 +33,7 @@
 LL |         let b = &*a;
    |                  -- borrow of `a` occurs here
 LL |         unsafe {
-LL |             asm!("nop" : "=r"(a));  //[ast]~ ERROR cannot assign to `a` because it is borrowed
+LL |             asm!("nop" : "=r"(a));
    |                               ^ assignment to borrowed `a` occurs here
 
 error[E0384]: cannot assign twice to immutable variable `x`
@@ -42,13 +42,13 @@
 LL |         let x = 3;
    |             - first assignment to `x`
 LL |         unsafe {
-LL |             asm!("nop" : "+r"(x));  //[ast]~ ERROR cannot assign twice
+LL |             asm!("nop" : "+r"(x));
    |                               ^ cannot assign twice to immutable variable
 
 error[E0381]: use of possibly uninitialized variable: `x`
   --> $DIR/borrowck-asm.rs:68:32
    |
-LL |             asm!("nop" : "=*r"(x)); //[ast]~ ERROR use of possibly uninitialized variable
+LL |             asm!("nop" : "=*r"(x));
    |                                ^ use of possibly uninitialized `x`
 
 error[E0506]: cannot assign to `x` because it is borrowed
@@ -57,13 +57,13 @@
 LL |         let y = &*x;
    |                  -- borrow of `x` occurs here
 LL |         unsafe {
-LL |             asm!("nop" : "+r"(x));  //[ast]~ ERROR cannot assign to `x` because it is borrowed
+LL |             asm!("nop" : "+r"(x));
    |                               ^ assignment to borrowed `x` occurs here
 
 error[E0382]: use of moved value: `x`
   --> $DIR/borrowck-asm.rs:86:40
    |
-LL |             asm!("nop" : : "r"(x), "r"(x) );    //[ast]~ ERROR use of moved value
+LL |             asm!("nop" : : "r"(x), "r"(x) );
    |                                -       ^ value used here after move
    |                                |
    |                                value moved here
diff --git a/src/test/ui/borrowck/borrowck-asm.mir.stderr b/src/test/ui/borrowck/borrowck-asm.mir.stderr
index 86e4832..dd6e5eb 100644
--- a/src/test/ui/borrowck/borrowck-asm.mir.stderr
+++ b/src/test/ui/borrowck/borrowck-asm.mir.stderr
@@ -7,7 +7,7 @@
 LL |             asm!("nop" : : "r"(x));
    |                                - value moved here
 LL |         }
-LL |         let z = x;  //[ast]~ ERROR use of moved value: `x`
+LL |         let z = x;
    |                 ^ value used here after move
 
 error[E0503]: cannot use `x` because it was mutably borrowed
@@ -16,7 +16,7 @@
 LL |         let y = &mut x;
    |                 ------ borrow of `x` occurs here
 LL |         unsafe {
-LL |             asm!("nop" : : "r"(x)); //[ast]~ ERROR cannot use
+LL |             asm!("nop" : : "r"(x));
    |                                ^ use of borrowed `x`
 ...
 LL |         let z = y;
@@ -31,7 +31,7 @@
    |             first assignment to `x`
    |             help: make this binding mutable: `mut x`
 LL |         unsafe {
-LL |             asm!("nop" : "=r"(x));  //[ast]~ ERROR cannot assign twice
+LL |             asm!("nop" : "=r"(x));
    |                               ^ cannot assign twice to immutable variable
 
 error[E0384]: cannot assign twice to immutable variable `x`
@@ -43,13 +43,13 @@
    |             first assignment to `x`
    |             help: make this binding mutable: `mut x`
 LL |         unsafe {
-LL |             asm!("nop" : "+r"(x));  //[ast]~ ERROR cannot assign twice
+LL |             asm!("nop" : "+r"(x));
    |                               ^ cannot assign twice to immutable variable
 
 error[E0381]: use of possibly uninitialized variable: `x`
   --> $DIR/borrowck-asm.rs:68:32
    |
-LL |             asm!("nop" : "=*r"(x)); //[ast]~ ERROR use of possibly uninitialized variable
+LL |             asm!("nop" : "=*r"(x));
    |                                ^ use of possibly uninitialized `x`
 
 error[E0506]: cannot assign to `x` because it is borrowed
@@ -58,7 +58,7 @@
 LL |         let y = &*x;
    |                 --- borrow of `x` occurs here
 LL |         unsafe {
-LL |             asm!("nop" : "+r"(x));  //[ast]~ ERROR cannot assign to `x` because it is borrowed
+LL |             asm!("nop" : "+r"(x));
    |                               ^ assignment to borrowed `x` occurs here
 ...
 LL |         let z = y;
@@ -70,7 +70,7 @@
 LL |         let x = &mut 2;
    |             - move occurs because `x` has type `&mut i32`, which does not implement the `Copy` trait
 LL |         unsafe {
-LL |             asm!("nop" : : "r"(x), "r"(x) );    //[ast]~ ERROR use of moved value
+LL |             asm!("nop" : : "r"(x), "r"(x) );
    |                                -       ^ value used here after move
    |                                |
    |                                value moved here
diff --git a/src/test/ui/borrowck/borrowck-assign-comp.ast.nll.stderr b/src/test/ui/borrowck/borrowck-assign-comp.ast.nll.stderr
index c204248..53af41c 100644
--- a/src/test/ui/borrowck/borrowck-assign-comp.ast.nll.stderr
+++ b/src/test/ui/borrowck/borrowck-assign-comp.ast.nll.stderr
@@ -4,9 +4,9 @@
 LL |     let q = &p;
    |             -- borrow of `p.x` occurs here
 ...
-LL |     p.x = 5; //[ast]~ ERROR cannot assign to `p.x`
+LL |     p.x = 5;
    |     ^^^^^^^ assignment to borrowed `p.x` occurs here
-LL |              //[mir]~^ ERROR cannot assign to `p.x` because it is borrowed
+LL |
 LL |     q.x;
    |     --- borrow later used here
 
@@ -15,7 +15,7 @@
    |
 LL |     let q = &p.y;
    |             ---- borrow of `p` occurs here
-LL |     p = Point {x: 5, y: 7};//[ast]~ ERROR cannot assign to `p`
+LL |     p = Point {x: 5, y: 7};
    |     ^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `p` occurs here
 ...
 LL |     *q; // stretch loan
@@ -26,9 +26,9 @@
    |
 LL |     let q = &p.y;
    |             ---- borrow of `p.y` occurs here
-LL |     p.y = 5; //[ast]~ ERROR cannot assign to `p.y`
+LL |     p.y = 5;
    |     ^^^^^^^ assignment to borrowed `p.y` occurs here
-LL |              //[mir]~^ ERROR cannot assign to `p.y` because it is borrowed
+LL |
 LL |     *q;
    |     -- borrow later used here
 
diff --git a/src/test/ui/borrowck/borrowck-assign-comp.ast.stderr b/src/test/ui/borrowck/borrowck-assign-comp.ast.stderr
index 735c168..4adb19c 100644
--- a/src/test/ui/borrowck/borrowck-assign-comp.ast.stderr
+++ b/src/test/ui/borrowck/borrowck-assign-comp.ast.stderr
@@ -4,7 +4,7 @@
 LL |     let q = &p;
    |              - borrow of `p.x` occurs here
 ...
-LL |     p.x = 5; //[ast]~ ERROR cannot assign to `p.x`
+LL |     p.x = 5;
    |     ^^^^^^^ assignment to borrowed `p.x` occurs here
 
 error[E0506]: cannot assign to `p` because it is borrowed
@@ -12,7 +12,7 @@
    |
 LL |     let q = &p.y;
    |              --- borrow of `p` occurs here
-LL |     p = Point {x: 5, y: 7};//[ast]~ ERROR cannot assign to `p`
+LL |     p = Point {x: 5, y: 7};
    |     ^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `p` occurs here
 
 error[E0506]: cannot assign to `p.y` because it is borrowed
@@ -20,7 +20,7 @@
    |
 LL |     let q = &p.y;
    |              --- borrow of `p.y` occurs here
-LL |     p.y = 5; //[ast]~ ERROR cannot assign to `p.y`
+LL |     p.y = 5;
    |     ^^^^^^^ assignment to borrowed `p.y` occurs here
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/borrowck/borrowck-assign-comp.mir.stderr b/src/test/ui/borrowck/borrowck-assign-comp.mir.stderr
index c204248..53af41c 100644
--- a/src/test/ui/borrowck/borrowck-assign-comp.mir.stderr
+++ b/src/test/ui/borrowck/borrowck-assign-comp.mir.stderr
@@ -4,9 +4,9 @@
 LL |     let q = &p;
    |             -- borrow of `p.x` occurs here
 ...
-LL |     p.x = 5; //[ast]~ ERROR cannot assign to `p.x`
+LL |     p.x = 5;
    |     ^^^^^^^ assignment to borrowed `p.x` occurs here
-LL |              //[mir]~^ ERROR cannot assign to `p.x` because it is borrowed
+LL |
 LL |     q.x;
    |     --- borrow later used here
 
@@ -15,7 +15,7 @@
    |
 LL |     let q = &p.y;
    |             ---- borrow of `p` occurs here
-LL |     p = Point {x: 5, y: 7};//[ast]~ ERROR cannot assign to `p`
+LL |     p = Point {x: 5, y: 7};
    |     ^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `p` occurs here
 ...
 LL |     *q; // stretch loan
@@ -26,9 +26,9 @@
    |
 LL |     let q = &p.y;
    |             ---- borrow of `p.y` occurs here
-LL |     p.y = 5; //[ast]~ ERROR cannot assign to `p.y`
+LL |     p.y = 5;
    |     ^^^^^^^ assignment to borrowed `p.y` occurs here
-LL |              //[mir]~^ ERROR cannot assign to `p.y` because it is borrowed
+LL |
 LL |     *q;
    |     -- borrow later used here
 
diff --git a/src/test/ui/borrowck/borrowck-assign-to-constants.ast.nll.stderr b/src/test/ui/borrowck/borrowck-assign-to-constants.ast.nll.stderr
index 0a30a49..626e1ef 100644
--- a/src/test/ui/borrowck/borrowck-assign-to-constants.ast.nll.stderr
+++ b/src/test/ui/borrowck/borrowck-assign-to-constants.ast.nll.stderr
@@ -1,7 +1,7 @@
 error[E0594]: cannot assign to immutable static item `foo`
   --> $DIR/borrowck-assign-to-constants.rs:8:5
    |
-LL |     foo = 6; //[ast]~ ERROR cannot assign to immutable static item
+LL |     foo = 6;
    |     ^^^^^^^ cannot assign
 
 error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-assign-to-constants.ast.stderr b/src/test/ui/borrowck/borrowck-assign-to-constants.ast.stderr
index 4111f55..e755785 100644
--- a/src/test/ui/borrowck/borrowck-assign-to-constants.ast.stderr
+++ b/src/test/ui/borrowck/borrowck-assign-to-constants.ast.stderr
@@ -1,7 +1,7 @@
 error[E0594]: cannot assign to immutable static item
   --> $DIR/borrowck-assign-to-constants.rs:8:5
    |
-LL |     foo = 6; //[ast]~ ERROR cannot assign to immutable static item
+LL |     foo = 6;
    |     ^^^^^^^
 
 error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-assign-to-constants.mir.stderr b/src/test/ui/borrowck/borrowck-assign-to-constants.mir.stderr
index 0a30a49..626e1ef 100644
--- a/src/test/ui/borrowck/borrowck-assign-to-constants.mir.stderr
+++ b/src/test/ui/borrowck/borrowck-assign-to-constants.mir.stderr
@@ -1,7 +1,7 @@
 error[E0594]: cannot assign to immutable static item `foo`
   --> $DIR/borrowck-assign-to-constants.rs:8:5
    |
-LL |     foo = 6; //[ast]~ ERROR cannot assign to immutable static item
+LL |     foo = 6;
    |     ^^^^^^^ cannot assign
 
 error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-box-insensitivity.ast.stderr b/src/test/ui/borrowck/borrowck-box-insensitivity.ast.stderr
index 236064d..60c8b33 100644
--- a/src/test/ui/borrowck/borrowck-box-insensitivity.ast.stderr
+++ b/src/test/ui/borrowck/borrowck-box-insensitivity.ast.stderr
@@ -3,8 +3,8 @@
    |
 LL |     let _x = a.x;
    |         -- value moved here
-LL |     //[ast]~^ value moved here
-LL |     let _y = a.y; //[ast]~ ERROR use of moved
+LL |
+LL |     let _y = a.y;
    |         ^^ value used here after move
    |
    = note: move occurs because `a.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
@@ -14,8 +14,8 @@
    |
 LL |     let _x = a.x;
    |         -- value moved here
-LL |     //[ast]~^ value moved here
-LL |     let _y = a.y; //[ast]~ ERROR use of moved
+LL |
+LL |     let _y = a.y;
    |         ^^ value used here after move
    |
    = note: move occurs because `a.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
@@ -25,8 +25,8 @@
    |
 LL |     let _x = a.x;
    |         -- value moved here
-LL |     //[ast]~^ value moved here
-LL |     let _y = &a.y; //[ast]~ ERROR use of moved
+LL |
+LL |     let _y = &a.y;
    |               ^^^ value used here after move
    |
    = note: move occurs because `a.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
@@ -44,7 +44,7 @@
    |
 LL |     let _x = &mut a.x;
    |                   --- borrow of `a.x` occurs here
-LL |     let _y = a.y; //[ast]~ ERROR cannot use
+LL |     let _y = a.y;
    |         ^^ use of borrowed `a.x`
 
 error[E0505]: cannot move out of `a.y` because it is borrowed
@@ -60,7 +60,7 @@
    |
 LL |     let _x = &mut a.x;
    |                   --- mutable borrow occurs here (via `a.x`)
-LL |     let _y = &a.y; //[ast]~ ERROR cannot borrow
+LL |     let _y = &a.y;
    |               ^^^ immutable borrow of `a.y` -- which overlaps with `a.x` -- occurs here
 ...
 LL | }
@@ -71,7 +71,7 @@
    |
 LL |     let _x = &a.x;
    |               --- immutable borrow occurs here (via `a.x`)
-LL |     let _y = &mut a.y; //[ast]~ ERROR cannot borrow
+LL |     let _y = &mut a.y;
    |                   ^^^ mutable borrow of `a.y` -- which overlaps with `a.x` -- occurs here
 ...
 LL | }
@@ -82,8 +82,8 @@
    |
 LL |     let _x = a.x.x;
    |         -- value moved here
-LL |     //[ast]~^ value moved here
-LL |     let _y = a.y; //[ast]~ ERROR use of collaterally moved
+LL |
+LL |     let _y = a.y;
    |         ^^ value used here after move
    |
    = note: move occurs because `a.x.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
@@ -93,8 +93,8 @@
    |
 LL |     let _x = a.x.x;
    |         -- value moved here
-LL |     //[ast]~^ value moved here
-LL |     let _y = a.y; //[ast]~ ERROR use of collaterally moved
+LL |
+LL |     let _y = a.y;
    |         ^^ value used here after move
    |
    = note: move occurs because `a.x.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
@@ -104,8 +104,8 @@
    |
 LL |     let _x = a.x.x;
    |         -- value moved here
-LL |     //[ast]~^ value moved here
-LL |     let _y = &a.y; //[ast]~ ERROR use of collaterally moved
+LL |
+LL |     let _y = &a.y;
    |               ^^^ value used here after move
    |
    = note: move occurs because `a.x.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
@@ -115,7 +115,7 @@
    |
 LL |     let _x = &a.x.x;
    |               ----- borrow of `a.x.x` occurs here
-LL |     //[ast]~^ borrow of `a.x.x` occurs here
+LL |
 LL |     let _y = a.y;
    |         ^^ move out of `a.y` occurs here
 
@@ -124,7 +124,7 @@
    |
 LL |     let _x = &mut a.x.x;
    |                   ----- borrow of `a.x.x` occurs here
-LL |     let _y = a.y; //[ast]~ ERROR cannot use
+LL |     let _y = a.y;
    |         ^^ use of borrowed `a.x.x`
 
 error[E0505]: cannot move out of `a.y` because it is borrowed
@@ -140,8 +140,8 @@
    |
 LL |     let _x = &mut a.x.x;
    |                   ----- mutable borrow occurs here
-LL |     //[ast]~^ mutable borrow occurs here
-LL |     let _y = &a.y; //[ast]~ ERROR cannot borrow
+LL |
+LL |     let _y = &a.y;
    |               ^^^ immutable borrow occurs here
 ...
 LL | }
@@ -152,8 +152,8 @@
    |
 LL |     let _x = &a.x.x;
    |               ----- immutable borrow occurs here
-LL |     //[ast]~^ immutable borrow occurs here
-LL |     let _y = &mut a.y; //[ast]~ ERROR cannot borrow
+LL |
+LL |     let _y = &mut a.y;
    |                   ^^^ mutable borrow occurs here
 ...
 LL | }
diff --git a/src/test/ui/borrowck/borrowck-box-insensitivity.mir.stderr b/src/test/ui/borrowck/borrowck-box-insensitivity.mir.stderr
index 171e992..0e380e9 100644
--- a/src/test/ui/borrowck/borrowck-box-insensitivity.mir.stderr
+++ b/src/test/ui/borrowck/borrowck-box-insensitivity.mir.stderr
@@ -1,7 +1,7 @@
 error: compilation successful
   --> $DIR/borrowck-box-insensitivity.rs:160:1
    |
-LL | / fn main() { //[mir]~ ERROR compilation successful
+LL | / fn main() {
 LL | |     copy_after_move();
 LL | |     move_after_move();
 LL | |     borrow_after_move();
diff --git a/src/test/ui/borrowck/borrowck-closures-mut-and-imm.ast.nll.stderr b/src/test/ui/borrowck/borrowck-closures-mut-and-imm.ast.nll.stderr
index ed3d1ff..aac5fdf6 100644
--- a/src/test/ui/borrowck/borrowck-closures-mut-and-imm.ast.nll.stderr
+++ b/src/test/ui/borrowck/borrowck-closures-mut-and-imm.ast.nll.stderr
@@ -5,11 +5,11 @@
    |              -- - first borrow occurs due to use of `x` in closure
    |              |
    |              mutable borrow occurs here
-LL |     let c2 = || x * 5; //[ast]~ ERROR cannot borrow `x`
+LL |     let c2 = || x * 5;
    |              ^^ - second borrow occurs due to use of `x` in closure
    |              |
    |              immutable borrow occurs here
-LL |     //[mir]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
+LL |
 LL |     drop(c1);
    |          -- mutable borrow later used here
 
@@ -20,11 +20,11 @@
    |              --          - first borrow occurs due to use of `x` in closure
    |              |
    |              mutable borrow occurs here
-LL |     let c2 = || get(&x); //[ast]~ ERROR cannot borrow `x`
+LL |     let c2 = || get(&x);
    |              ^^      - second borrow occurs due to use of `x` in closure
    |              |
    |              immutable borrow occurs here
-LL |                          //[mir]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
+LL |
 LL |     drop(c1);
    |          -- mutable borrow later used here
 
@@ -35,11 +35,11 @@
    |              --          - first borrow occurs due to use of `x` in closure
    |              |
    |              mutable borrow occurs here
-LL |     let c2 = || x * 5; //[ast]~ ERROR cannot borrow `x`
+LL |     let c2 = || x * 5;
    |              ^^ - second borrow occurs due to use of `x` in closure
    |              |
    |              immutable borrow occurs here
-LL |                        //[mir]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
+LL |
 LL |     drop(c1);
    |          -- mutable borrow later used here
 
@@ -50,9 +50,9 @@
    |              -- - borrow occurs due to use in closure
    |              |
    |              borrow of `x` occurs here
-LL |     x = 5; //[ast]~ ERROR cannot assign
+LL |     x = 5;
    |     ^^^^^ assignment to borrowed `x` occurs here
-LL |            //[mir]~^ ERROR cannot assign to `x` because it is borrowed
+LL |
 LL |     drop(c2);
    |          -- borrow later used here
 
@@ -63,9 +63,9 @@
    |              --      - borrow occurs due to use in closure
    |              |
    |              borrow of `x` occurs here
-LL |     x = 5; //[ast]~ ERROR cannot assign
+LL |     x = 5;
    |     ^^^^^ assignment to borrowed `x` occurs here
-LL |            //[mir]~^ ERROR cannot assign to `x` because it is borrowed
+LL |
 LL |     drop(c1);
    |          -- borrow later used here
 
@@ -76,9 +76,9 @@
    |              --       - borrow occurs due to use in closure
    |              |
    |              borrow of `*x` occurs here
-LL |     *x = 5; //[ast]~ ERROR cannot assign to `*x`
+LL |     *x = 5;
    |     ^^^^^^ assignment to borrowed `*x` occurs here
-LL |             //[mir]~^ ERROR cannot assign to `*x` because it is borrowed
+LL |
 LL |     drop(c1);
    |          -- borrow later used here
 
@@ -89,9 +89,9 @@
    |              --       - borrow occurs due to use in closure
    |              |
    |              borrow of `*x.f` occurs here
-LL |     *x.f = 5; //[ast]~ ERROR cannot assign to `*x.f`
+LL |     *x.f = 5;
    |     ^^^^^^^^ assignment to borrowed `*x.f` occurs here
-LL |               //[mir]~^ ERROR cannot assign to `*x.f` because it is borrowed
+LL |
 LL |     drop(c1);
    |          -- borrow later used here
 
@@ -102,11 +102,11 @@
    |              --       - first borrow occurs due to use of `x` in closure
    |              |
    |              immutable borrow occurs here
-LL |     let c2 = || *x.f = 5; //[ast]~ ERROR cannot borrow `x` as mutable
+LL |     let c2 = || *x.f = 5;
    |              ^^  - second borrow occurs due to use of `x` in closure
    |              |
    |              mutable borrow occurs here
-LL |                           //[mir]~^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable
+LL |
 LL |     drop(c1);
    |          -- immutable borrow later used here
 
diff --git a/src/test/ui/borrowck/borrowck-closures-mut-and-imm.ast.stderr b/src/test/ui/borrowck/borrowck-closures-mut-and-imm.ast.stderr
index 363889c..d672d0c 100644
--- a/src/test/ui/borrowck/borrowck-closures-mut-and-imm.ast.stderr
+++ b/src/test/ui/borrowck/borrowck-closures-mut-and-imm.ast.stderr
@@ -5,7 +5,7 @@
    |              -- - previous borrow occurs due to use of `x` in closure
    |              |
    |              mutable borrow occurs here
-LL |     let c2 = || x * 5; //[ast]~ ERROR cannot borrow `x`
+LL |     let c2 = || x * 5;
    |              ^^ - borrow occurs due to use of `x` in closure
    |              |
    |              immutable borrow occurs here
@@ -20,7 +20,7 @@
    |              --          - previous borrow occurs due to use of `x` in closure
    |              |
    |              mutable borrow occurs here
-LL |     let c2 = || get(&x); //[ast]~ ERROR cannot borrow `x`
+LL |     let c2 = || get(&x);
    |              ^^      - borrow occurs due to use of `x` in closure
    |              |
    |              immutable borrow occurs here
@@ -35,7 +35,7 @@
    |              --          - previous borrow occurs due to use of `x` in closure
    |              |
    |              mutable borrow occurs here
-LL |     let c2 = || x * 5; //[ast]~ ERROR cannot borrow `x`
+LL |     let c2 = || x * 5;
    |              ^^ - borrow occurs due to use of `x` in closure
    |              |
    |              immutable borrow occurs here
@@ -48,7 +48,7 @@
    |
 LL |     let c2 = || x * 5;
    |              -- borrow of `x` occurs here
-LL |     x = 5; //[ast]~ ERROR cannot assign
+LL |     x = 5;
    |     ^^^^^ assignment to borrowed `x` occurs here
 
 error[E0506]: cannot assign to `x` because it is borrowed
@@ -56,7 +56,7 @@
    |
 LL |     let c1 = || get(&x);
    |              -- borrow of `x` occurs here
-LL |     x = 5; //[ast]~ ERROR cannot assign
+LL |     x = 5;
    |     ^^^^^ assignment to borrowed `x` occurs here
 
 error[E0506]: cannot assign to `*x` because it is borrowed
@@ -64,7 +64,7 @@
    |
 LL |     let c1 = || get(&*x);
    |              -- borrow of `*x` occurs here
-LL |     *x = 5; //[ast]~ ERROR cannot assign to `*x`
+LL |     *x = 5;
    |     ^^^^^^ assignment to borrowed `*x` occurs here
 
 error[E0506]: cannot assign to `*x.f` because it is borrowed
@@ -72,7 +72,7 @@
    |
 LL |     let c1 = || get(&*x.f);
    |              -- borrow of `*x.f` occurs here
-LL |     *x.f = 5; //[ast]~ ERROR cannot assign to `*x.f`
+LL |     *x.f = 5;
    |     ^^^^^^^^ assignment to borrowed `*x.f` occurs here
 
 error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
@@ -82,7 +82,7 @@
    |              --       - previous borrow occurs due to use of `x` in closure
    |              |
    |              immutable borrow occurs here
-LL |     let c2 = || *x.f = 5; //[ast]~ ERROR cannot borrow `x` as mutable
+LL |     let c2 = || *x.f = 5;
    |              ^^  - borrow occurs due to use of `x` in closure
    |              |
    |              mutable borrow occurs here
diff --git a/src/test/ui/borrowck/borrowck-closures-mut-and-imm.mir.stderr b/src/test/ui/borrowck/borrowck-closures-mut-and-imm.mir.stderr
index ed3d1ff..aac5fdf6 100644
--- a/src/test/ui/borrowck/borrowck-closures-mut-and-imm.mir.stderr
+++ b/src/test/ui/borrowck/borrowck-closures-mut-and-imm.mir.stderr
@@ -5,11 +5,11 @@
    |              -- - first borrow occurs due to use of `x` in closure
    |              |
    |              mutable borrow occurs here
-LL |     let c2 = || x * 5; //[ast]~ ERROR cannot borrow `x`
+LL |     let c2 = || x * 5;
    |              ^^ - second borrow occurs due to use of `x` in closure
    |              |
    |              immutable borrow occurs here
-LL |     //[mir]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
+LL |
 LL |     drop(c1);
    |          -- mutable borrow later used here
 
@@ -20,11 +20,11 @@
    |              --          - first borrow occurs due to use of `x` in closure
    |              |
    |              mutable borrow occurs here
-LL |     let c2 = || get(&x); //[ast]~ ERROR cannot borrow `x`
+LL |     let c2 = || get(&x);
    |              ^^      - second borrow occurs due to use of `x` in closure
    |              |
    |              immutable borrow occurs here
-LL |                          //[mir]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
+LL |
 LL |     drop(c1);
    |          -- mutable borrow later used here
 
@@ -35,11 +35,11 @@
    |              --          - first borrow occurs due to use of `x` in closure
    |              |
    |              mutable borrow occurs here
-LL |     let c2 = || x * 5; //[ast]~ ERROR cannot borrow `x`
+LL |     let c2 = || x * 5;
    |              ^^ - second borrow occurs due to use of `x` in closure
    |              |
    |              immutable borrow occurs here
-LL |                        //[mir]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
+LL |
 LL |     drop(c1);
    |          -- mutable borrow later used here
 
@@ -50,9 +50,9 @@
    |              -- - borrow occurs due to use in closure
    |              |
    |              borrow of `x` occurs here
-LL |     x = 5; //[ast]~ ERROR cannot assign
+LL |     x = 5;
    |     ^^^^^ assignment to borrowed `x` occurs here
-LL |            //[mir]~^ ERROR cannot assign to `x` because it is borrowed
+LL |
 LL |     drop(c2);
    |          -- borrow later used here
 
@@ -63,9 +63,9 @@
    |              --      - borrow occurs due to use in closure
    |              |
    |              borrow of `x` occurs here
-LL |     x = 5; //[ast]~ ERROR cannot assign
+LL |     x = 5;
    |     ^^^^^ assignment to borrowed `x` occurs here
-LL |            //[mir]~^ ERROR cannot assign to `x` because it is borrowed
+LL |
 LL |     drop(c1);
    |          -- borrow later used here
 
@@ -76,9 +76,9 @@
    |              --       - borrow occurs due to use in closure
    |              |
    |              borrow of `*x` occurs here
-LL |     *x = 5; //[ast]~ ERROR cannot assign to `*x`
+LL |     *x = 5;
    |     ^^^^^^ assignment to borrowed `*x` occurs here
-LL |             //[mir]~^ ERROR cannot assign to `*x` because it is borrowed
+LL |
 LL |     drop(c1);
    |          -- borrow later used here
 
@@ -89,9 +89,9 @@
    |              --       - borrow occurs due to use in closure
    |              |
    |              borrow of `*x.f` occurs here
-LL |     *x.f = 5; //[ast]~ ERROR cannot assign to `*x.f`
+LL |     *x.f = 5;
    |     ^^^^^^^^ assignment to borrowed `*x.f` occurs here
-LL |               //[mir]~^ ERROR cannot assign to `*x.f` because it is borrowed
+LL |
 LL |     drop(c1);
    |          -- borrow later used here
 
@@ -102,11 +102,11 @@
    |              --       - first borrow occurs due to use of `x` in closure
    |              |
    |              immutable borrow occurs here
-LL |     let c2 = || *x.f = 5; //[ast]~ ERROR cannot borrow `x` as mutable
+LL |     let c2 = || *x.f = 5;
    |              ^^  - second borrow occurs due to use of `x` in closure
    |              |
    |              mutable borrow occurs here
-LL |                           //[mir]~^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable
+LL |
 LL |     drop(c1);
    |          -- immutable borrow later used here
 
diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.ast.nll.stderr b/src/test/ui/borrowck/borrowck-describe-lvalue.ast.nll.stderr
index 24467fa..c614469 100644
--- a/src/test/ui/borrowck/borrowck-describe-lvalue.ast.nll.stderr
+++ b/src/test/ui/borrowck/borrowck-describe-lvalue.ast.nll.stderr
@@ -3,9 +3,9 @@
    |
 LL |             let y = &mut x;
    |                     ------ first mutable borrow occurs here
-LL |             &mut x; //[ast]~ ERROR cannot borrow `**x` as mutable more than once at a time
+LL |             &mut x;
    |             ^^^^^^ second mutable borrow occurs here
-LL |                     //[mir]~^ ERROR cannot borrow `x` as mutable more than once at a time
+LL |
 LL |             *y = 1;
    |             ------ first borrow later used here
 
@@ -14,9 +14,9 @@
    |
 LL |                    let y = &mut x;
    |                            ------ first mutable borrow occurs here
-LL |                    &mut x; //[ast]~ ERROR cannot borrow `**x` as mutable more than once at a time
+LL |                    &mut x;
    |                    ^^^^^^ second mutable borrow occurs here
-LL |                    //[mir]~^ ERROR cannot borrow `x` as mutable more than once at a time
+LL |
 LL |                    *y = 1;
    |                    ------ first borrow later used here
 
@@ -25,10 +25,10 @@
    |
 LL |              || {
    |               - inferred to be a `FnMut` closure
-LL | /                || { //[mir]~ ERROR captured variable cannot escape `FnMut` closure body
+LL | /                || {
 LL | |                    let y = &mut x;
-LL | |                    &mut x; //[ast]~ ERROR cannot borrow `**x` as mutable more than once at a time
-LL | |                    //[mir]~^ ERROR cannot borrow `x` as mutable more than once at a time
+LL | |                    &mut x;
+LL | |
 LL | |                    *y = 1;
 LL | |                    drop(y);
 LL | |                 }
@@ -42,9 +42,9 @@
    |
 LL |         let x = f.x();
    |                 - borrow of `f` occurs here
-LL |         f.x; //[ast]~ ERROR cannot use `f.x` because it was mutably borrowed
+LL |         f.x;
    |         ^^^ use of borrowed `f`
-LL |         //[mir]~^ ERROR cannot use `f.x` because it was mutably borrowed
+LL |
 LL |         drop(x);
    |              - borrow later used here
 
@@ -53,9 +53,9 @@
    |
 LL |         let x = g.x();
    |                 - borrow of `g` occurs here
-LL |         g.0; //[ast]~ ERROR cannot use `g.0` because it was mutably borrowed
+LL |         g.0;
    |         ^^^ use of borrowed `g`
-LL |              //[mir]~^ ERROR cannot use `g.0` because it was mutably borrowed
+LL |
 LL |         drop(x);
    |              - borrow later used here
 
@@ -64,9 +64,9 @@
    |
 LL |         let x = &mut h.0;
    |                 -------- borrow of `h.0` occurs here
-LL |         h.0; //[ast]~ ERROR cannot use `h.0` because it was mutably borrowed
+LL |         h.0;
    |         ^^^ use of borrowed `h.0`
-LL |              //[mir]~^ ERROR cannot use `h.0` because it was mutably borrowed
+LL |
 LL |         drop(x);
    |              - borrow later used here
 
@@ -87,9 +87,9 @@
    |
 LL |         let x = &mut u.a;
    |                 -------- borrow of `u.a` occurs here
-LL |         u.a; //[ast]~ ERROR cannot use `u.a` because it was mutably borrowed
+LL |         u.a;
    |         ^^^ use of borrowed `u.a`
-LL |              //[mir]~^ ERROR cannot use `u.a` because it was mutably borrowed
+LL |
 LL |         drop(x);
    |              - borrow later used here
 
@@ -98,9 +98,9 @@
    |
 LL |         let x = f.x();
    |                 - borrow of `*f` occurs here
-LL |         f.x; //[ast]~ ERROR cannot use `f.x` because it was mutably borrowed
+LL |         f.x;
    |         ^^^ use of borrowed `*f`
-LL |              //[mir]~^ ERROR cannot use `f.x` because it was mutably borrowed
+LL |
 LL |         drop(x);
    |              - borrow later used here
 
@@ -109,9 +109,9 @@
    |
 LL |         let x = g.x();
    |                 - borrow of `*g` occurs here
-LL |         g.0; //[ast]~ ERROR cannot use `g.0` because it was mutably borrowed
+LL |         g.0;
    |         ^^^ use of borrowed `*g`
-LL |              //[mir]~^ ERROR cannot use `g.0` because it was mutably borrowed
+LL |
 LL |         drop(x);
    |              - borrow later used here
 
@@ -120,9 +120,9 @@
    |
 LL |         let x = &mut h.0;
    |                 -------- borrow of `h.0` occurs here
-LL |         h.0; //[ast]~ ERROR cannot use `h.0` because it was mutably borrowed
+LL |         h.0;
    |         ^^^ use of borrowed `h.0`
-LL |              //[mir]~^ ERROR cannot use `h.0` because it was mutably borrowed
+LL |
 LL |         drop(x);
    |              - borrow later used here
 
@@ -143,9 +143,9 @@
    |
 LL |         let x = &mut u.a;
    |                 -------- borrow of `u.a` occurs here
-LL |         u.a; //[ast]~ ERROR cannot use `u.a` because it was mutably borrowed
+LL |         u.a;
    |         ^^^ use of borrowed `u.a`
-LL |              //[mir]~^ ERROR cannot use `u.a` because it was mutably borrowed
+LL |
 LL |         drop(x);
    |              - borrow later used here
 
@@ -372,7 +372,7 @@
    |
 LL |                 drop(x);
    |                      - value moved here
-LL |                 drop(x); //[ast]~ ERROR use of moved value: `x`
+LL |                 drop(x);
    |                      ^ value used here after move
    |
    = note: move occurs because `x` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.ast.stderr b/src/test/ui/borrowck/borrowck-describe-lvalue.ast.stderr
index 278929e..d892db8 100644
--- a/src/test/ui/borrowck/borrowck-describe-lvalue.ast.stderr
+++ b/src/test/ui/borrowck/borrowck-describe-lvalue.ast.stderr
@@ -3,7 +3,7 @@
    |
 LL |         let x = f.x();
    |                 - borrow of `f` occurs here
-LL |         f.x; //[ast]~ ERROR cannot use `f.x` because it was mutably borrowed
+LL |         f.x;
    |         ^^^ use of borrowed `f`
 
 error[E0503]: cannot use `g.0` because it was mutably borrowed
@@ -11,7 +11,7 @@
    |
 LL |         let x = g.x();
    |                 - borrow of `g` occurs here
-LL |         g.0; //[ast]~ ERROR cannot use `g.0` because it was mutably borrowed
+LL |         g.0;
    |         ^^^ use of borrowed `g`
 
 error[E0503]: cannot use `h.0` because it was mutably borrowed
@@ -19,7 +19,7 @@
    |
 LL |         let x = &mut h.0;
    |                      --- borrow of `h.0` occurs here
-LL |         h.0; //[ast]~ ERROR cannot use `h.0` because it was mutably borrowed
+LL |         h.0;
    |         ^^^ use of borrowed `h.0`
 
 error[E0503]: cannot use `e.0` because it was mutably borrowed
@@ -36,7 +36,7 @@
    |
 LL |         let x = &mut u.a;
    |                      --- borrow of `u.a` occurs here
-LL |         u.a; //[ast]~ ERROR cannot use `u.a` because it was mutably borrowed
+LL |         u.a;
    |         ^^^ use of borrowed `u.a`
 
 error[E0503]: cannot use `f.x` because it was mutably borrowed
@@ -44,7 +44,7 @@
    |
 LL |         let x = f.x();
    |                 - borrow of `*f` occurs here
-LL |         f.x; //[ast]~ ERROR cannot use `f.x` because it was mutably borrowed
+LL |         f.x;
    |         ^^^ use of borrowed `*f`
 
 error[E0503]: cannot use `g.0` because it was mutably borrowed
@@ -52,7 +52,7 @@
    |
 LL |         let x = g.x();
    |                 - borrow of `*g` occurs here
-LL |         g.0; //[ast]~ ERROR cannot use `g.0` because it was mutably borrowed
+LL |         g.0;
    |         ^^^ use of borrowed `*g`
 
 error[E0503]: cannot use `h.0` because it was mutably borrowed
@@ -60,7 +60,7 @@
    |
 LL |         let x = &mut h.0;
    |                      --- borrow of `h.0` occurs here
-LL |         h.0; //[ast]~ ERROR cannot use `h.0` because it was mutably borrowed
+LL |         h.0;
    |         ^^^ use of borrowed `h.0`
 
 error[E0503]: cannot use `e.0` because it was mutably borrowed
@@ -77,7 +77,7 @@
    |
 LL |         let x = &mut u.a;
    |                      --- borrow of `u.a` occurs here
-LL |         u.a; //[ast]~ ERROR cannot use `u.a` because it was mutably borrowed
+LL |         u.a;
    |         ^^^ use of borrowed `u.a`
 
 error[E0503]: cannot use `v[..]` because it was mutably borrowed
@@ -213,7 +213,7 @@
    |
 LL |             let y = &mut x;
    |                          - first mutable borrow occurs here
-LL |             &mut x; //[ast]~ ERROR cannot borrow `**x` as mutable more than once at a time
+LL |             &mut x;
    |                  ^ second mutable borrow occurs here
 ...
 LL |         };
@@ -224,7 +224,7 @@
    |
 LL |                    let y = &mut x;
    |                                 - first mutable borrow occurs here
-LL |                    &mut x; //[ast]~ ERROR cannot borrow `**x` as mutable more than once at a time
+LL |                    &mut x;
    |                         ^ second mutable borrow occurs here
 ...
 LL |                 }
@@ -235,7 +235,7 @@
    |
 LL |                 drop(x);
    |                      - value moved here
-LL |                 drop(x); //[ast]~ ERROR use of moved value: `x`
+LL |                 drop(x);
    |                      ^ value used here after move
    |
    = note: move occurs because `x` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.mir.stderr b/src/test/ui/borrowck/borrowck-describe-lvalue.mir.stderr
index 279548f..af78340 100644
--- a/src/test/ui/borrowck/borrowck-describe-lvalue.mir.stderr
+++ b/src/test/ui/borrowck/borrowck-describe-lvalue.mir.stderr
@@ -3,9 +3,9 @@
    |
 LL |             let y = &mut x;
    |                     ------ first mutable borrow occurs here
-LL |             &mut x; //[ast]~ ERROR cannot borrow `**x` as mutable more than once at a time
+LL |             &mut x;
    |             ^^^^^^ second mutable borrow occurs here
-LL |                     //[mir]~^ ERROR cannot borrow `x` as mutable more than once at a time
+LL |
 LL |             *y = 1;
    |             ------ first borrow later used here
 
@@ -14,9 +14,9 @@
    |
 LL |                    let y = &mut x;
    |                            ------ first mutable borrow occurs here
-LL |                    &mut x; //[ast]~ ERROR cannot borrow `**x` as mutable more than once at a time
+LL |                    &mut x;
    |                    ^^^^^^ second mutable borrow occurs here
-LL |                    //[mir]~^ ERROR cannot borrow `x` as mutable more than once at a time
+LL |
 LL |                    *y = 1;
    |                    ------ first borrow later used here
 
@@ -25,10 +25,10 @@
    |
 LL |              || {
    |               - inferred to be a `FnMut` closure
-LL | /                || { //[mir]~ ERROR captured variable cannot escape `FnMut` closure body
+LL | /                || {
 LL | |                    let y = &mut x;
-LL | |                    &mut x; //[ast]~ ERROR cannot borrow `**x` as mutable more than once at a time
-LL | |                    //[mir]~^ ERROR cannot borrow `x` as mutable more than once at a time
+LL | |                    &mut x;
+LL | |
 LL | |                    *y = 1;
 LL | |                    drop(y);
 LL | |                 }
@@ -42,9 +42,9 @@
    |
 LL |         let x = f.x();
    |                 - borrow of `f` occurs here
-LL |         f.x; //[ast]~ ERROR cannot use `f.x` because it was mutably borrowed
+LL |         f.x;
    |         ^^^ use of borrowed `f`
-LL |         //[mir]~^ ERROR cannot use `f.x` because it was mutably borrowed
+LL |
 LL |         drop(x);
    |              - borrow later used here
 
@@ -53,9 +53,9 @@
    |
 LL |         let x = g.x();
    |                 - borrow of `g` occurs here
-LL |         g.0; //[ast]~ ERROR cannot use `g.0` because it was mutably borrowed
+LL |         g.0;
    |         ^^^ use of borrowed `g`
-LL |              //[mir]~^ ERROR cannot use `g.0` because it was mutably borrowed
+LL |
 LL |         drop(x);
    |              - borrow later used here
 
@@ -64,9 +64,9 @@
    |
 LL |         let x = &mut h.0;
    |                 -------- borrow of `h.0` occurs here
-LL |         h.0; //[ast]~ ERROR cannot use `h.0` because it was mutably borrowed
+LL |         h.0;
    |         ^^^ use of borrowed `h.0`
-LL |              //[mir]~^ ERROR cannot use `h.0` because it was mutably borrowed
+LL |
 LL |         drop(x);
    |              - borrow later used here
 
@@ -87,9 +87,9 @@
    |
 LL |         let x = &mut u.a;
    |                 -------- borrow of `u.a` occurs here
-LL |         u.a; //[ast]~ ERROR cannot use `u.a` because it was mutably borrowed
+LL |         u.a;
    |         ^^^ use of borrowed `u.a`
-LL |              //[mir]~^ ERROR cannot use `u.a` because it was mutably borrowed
+LL |
 LL |         drop(x);
    |              - borrow later used here
 
@@ -98,9 +98,9 @@
    |
 LL |         let x = f.x();
    |                 - borrow of `*f` occurs here
-LL |         f.x; //[ast]~ ERROR cannot use `f.x` because it was mutably borrowed
+LL |         f.x;
    |         ^^^ use of borrowed `*f`
-LL |              //[mir]~^ ERROR cannot use `f.x` because it was mutably borrowed
+LL |
 LL |         drop(x);
    |              - borrow later used here
 
@@ -109,9 +109,9 @@
    |
 LL |         let x = g.x();
    |                 - borrow of `*g` occurs here
-LL |         g.0; //[ast]~ ERROR cannot use `g.0` because it was mutably borrowed
+LL |         g.0;
    |         ^^^ use of borrowed `*g`
-LL |              //[mir]~^ ERROR cannot use `g.0` because it was mutably borrowed
+LL |
 LL |         drop(x);
    |              - borrow later used here
 
@@ -120,9 +120,9 @@
    |
 LL |         let x = &mut h.0;
    |                 -------- borrow of `h.0` occurs here
-LL |         h.0; //[ast]~ ERROR cannot use `h.0` because it was mutably borrowed
+LL |         h.0;
    |         ^^^ use of borrowed `h.0`
-LL |              //[mir]~^ ERROR cannot use `h.0` because it was mutably borrowed
+LL |
 LL |         drop(x);
    |              - borrow later used here
 
@@ -143,9 +143,9 @@
    |
 LL |         let x = &mut u.a;
    |                 -------- borrow of `u.a` occurs here
-LL |         u.a; //[ast]~ ERROR cannot use `u.a` because it was mutably borrowed
+LL |         u.a;
    |         ^^^ use of borrowed `u.a`
-LL |              //[mir]~^ ERROR cannot use `u.a` because it was mutably borrowed
+LL |
 LL |         drop(x);
    |              - borrow later used here
 
@@ -366,7 +366,7 @@
    |
 LL |                 drop(x);
    |                      - value moved here
-LL |                 drop(x); //[ast]~ ERROR use of moved value: `x`
+LL |                 drop(x);
    |                      ^ value used here after move
    |
    = note: move occurs because `x` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
diff --git a/src/test/ui/borrowck/borrowck-fn-in-const-a.ast.stderr b/src/test/ui/borrowck/borrowck-fn-in-const-a.ast.stderr
index 6a5c504..16c62fc 100644
--- a/src/test/ui/borrowck/borrowck-fn-in-const-a.ast.stderr
+++ b/src/test/ui/borrowck/borrowck-fn-in-const-a.ast.stderr
@@ -1,7 +1,7 @@
 error[E0507]: cannot move out of borrowed content
   --> $DIR/borrowck-fn-in-const-a.rs:9:16
    |
-LL |         return *x //[ast]~ ERROR cannot move out of borrowed content [E0507]
+LL |         return *x
    |                ^^ cannot move out of borrowed content
 
 error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-fn-in-const-a.mir.stderr b/src/test/ui/borrowck/borrowck-fn-in-const-a.mir.stderr
index 6a5c504..16c62fc 100644
--- a/src/test/ui/borrowck/borrowck-fn-in-const-a.mir.stderr
+++ b/src/test/ui/borrowck/borrowck-fn-in-const-a.mir.stderr
@@ -1,7 +1,7 @@
 error[E0507]: cannot move out of borrowed content
   --> $DIR/borrowck-fn-in-const-a.rs:9:16
    |
-LL |         return *x //[ast]~ ERROR cannot move out of borrowed content [E0507]
+LL |         return *x
    |                ^^ cannot move out of borrowed content
 
 error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.ast.nll.stderr b/src/test/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.ast.nll.stderr
index d3708b5..88b43c1 100644
--- a/src/test/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.ast.nll.stderr
+++ b/src/test/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.ast.nll.stderr
@@ -4,7 +4,7 @@
 LL |     let b = &mut _a;
    |             ------- borrow of `_a` occurs here
 ...
-LL |         _a = 4; //[ast]~ ERROR cannot assign to `_a`
+LL |         _a = 4;
    |         ^^^^^^ assignment to borrowed `_a` occurs here
 ...
 LL |     drop(b);
diff --git a/src/test/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.ast.stderr b/src/test/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.ast.stderr
index 618edf5..43c3c33 100644
--- a/src/test/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.ast.stderr
+++ b/src/test/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.ast.stderr
@@ -4,7 +4,7 @@
 LL |     let b = &mut _a;
    |                  -- borrow of `_a` occurs here
 ...
-LL |         _a = 4; //[ast]~ ERROR cannot assign to `_a`
+LL |         _a = 4;
    |         ^^^^^^ assignment to borrowed `_a` occurs here
 
 error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.mir.stderr b/src/test/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.mir.stderr
index d3708b5..88b43c1 100644
--- a/src/test/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.mir.stderr
+++ b/src/test/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.mir.stderr
@@ -4,7 +4,7 @@
 LL |     let b = &mut _a;
    |             ------- borrow of `_a` occurs here
 ...
-LL |         _a = 4; //[ast]~ ERROR cannot assign to `_a`
+LL |         _a = 4;
    |         ^^^^^^ assignment to borrowed `_a` occurs here
 ...
 LL |     drop(b);
diff --git a/src/test/ui/borrowck/borrowck-issue-14498.ast.nll.stderr b/src/test/ui/borrowck/borrowck-issue-14498.ast.nll.stderr
index 8161053..b53cfdd 100644
--- a/src/test/ui/borrowck/borrowck-issue-14498.ast.nll.stderr
+++ b/src/test/ui/borrowck/borrowck-issue-14498.ast.nll.stderr
@@ -3,7 +3,7 @@
    |
 LL |     let p = &y;
    |             -- help: consider changing this to be a mutable reference: `&mut y`
-LL |     ***p = 2; //[ast]~ ERROR cannot assign to data in a `&` reference
+LL |     ***p = 2;
    |     ^^^^^^^^ `p` is a `&` reference, so the data it refers to cannot be written
 
 error[E0506]: cannot assign to `**y` because it is borrowed
@@ -12,9 +12,9 @@
 LL |     let p = &y;
    |             -- borrow of `**y` occurs here
 LL |     let q = &***p;
-LL |     **y = 2; //[ast]~ ERROR cannot assign to `**y` because it is borrowed
+LL |     **y = 2;
    |     ^^^^^^^ assignment to borrowed `**y` occurs here
-LL |              //[mir]~^ ERROR cannot assign to `**y` because it is borrowed
+LL |
 LL |     drop(p);
    |          - borrow later used here
 
@@ -24,9 +24,9 @@
 LL |     let p = &y;
    |             -- borrow of `**y` occurs here
 LL |     let q = &***p;
-LL |     **y = 2; //[ast]~ ERROR cannot assign to `**y` because it is borrowed
+LL |     **y = 2;
    |     ^^^^^^^ assignment to borrowed `**y` occurs here
-LL |              //[mir]~^ ERROR cannot assign to `**y` because it is borrowed
+LL |
 LL |     drop(p);
    |          - borrow later used here
 
@@ -36,9 +36,9 @@
 LL |     let p = &y;
    |             -- borrow of `**y` occurs here
 LL |     let q = &***p;
-LL |     **y = 2; //[ast]~ ERROR cannot assign to `**y` because it is borrowed
+LL |     **y = 2;
    |     ^^^^^^^ assignment to borrowed `**y` occurs here
-LL |              //[mir]~^ ERROR cannot assign to `**y` because it is borrowed
+LL |
 LL |     drop(p);
    |          - borrow later used here
 
@@ -48,9 +48,9 @@
 LL |     let p = &y;
    |             -- borrow of `**y` occurs here
 LL |     let q = &***p;
-LL |     **y = 2; //[ast]~ ERROR cannot assign to `**y` because it is borrowed
+LL |     **y = 2;
    |     ^^^^^^^ assignment to borrowed `**y` occurs here
-LL |              //[mir]~^ ERROR cannot assign to `**y` because it is borrowed
+LL |
 LL |     drop(p);
    |          - borrow later used here
 
@@ -60,9 +60,9 @@
 LL |     let p = &y.a;
    |             ---- borrow of `**y.a` occurs here
 LL |     let q = &***p;
-LL |     **y.a = 2; //[ast]~ ERROR cannot assign to `**y.a` because it is borrowed
+LL |     **y.a = 2;
    |     ^^^^^^^^^ assignment to borrowed `**y.a` occurs here
-LL |                //[mir]~^ ERROR cannot assign to `**y.a` because it is borrowed
+LL |
 LL |     drop(p);
    |          - borrow later used here
 
@@ -72,9 +72,9 @@
 LL |     let p = &y.a;
    |             ---- borrow of `**y.a` occurs here
 LL |     let q = &***p;
-LL |     **y.a = 2; //[ast]~ ERROR cannot assign to `**y.a` because it is borrowed
+LL |     **y.a = 2;
    |     ^^^^^^^^^ assignment to borrowed `**y.a` occurs here
-LL |                //[mir]~^ ERROR cannot assign to `**y.a` because it is borrowed
+LL |
 LL |     drop(p);
    |          - borrow later used here
 
@@ -84,9 +84,9 @@
 LL |     let p = &y.a;
    |             ---- borrow of `**y.a` occurs here
 LL |     let q = &***p;
-LL |     **y.a = 2; //[ast]~ ERROR cannot assign to `**y.a` because it is borrowed
+LL |     **y.a = 2;
    |     ^^^^^^^^^ assignment to borrowed `**y.a` occurs here
-LL |                //[mir]~^ ERROR cannot assign to `**y.a` because it is borrowed
+LL |
 LL |     drop(p);
    |          - borrow later used here
 
@@ -96,9 +96,9 @@
 LL |     let p = &y.a;
    |             ---- borrow of `**y.a` occurs here
 LL |     let q = &***p;
-LL |     **y.a = 2; //[ast]~ ERROR cannot assign to `**y.a` because it is borrowed
+LL |     **y.a = 2;
    |     ^^^^^^^^^ assignment to borrowed `**y.a` occurs here
-LL |                //[mir]~^ ERROR cannot assign to `**y.a` because it is borrowed
+LL |
 LL |     drop(p);
    |          - borrow later used here
 
diff --git a/src/test/ui/borrowck/borrowck-issue-14498.ast.stderr b/src/test/ui/borrowck/borrowck-issue-14498.ast.stderr
index 59249da..b002ee7 100644
--- a/src/test/ui/borrowck/borrowck-issue-14498.ast.stderr
+++ b/src/test/ui/borrowck/borrowck-issue-14498.ast.stderr
@@ -1,7 +1,7 @@
 error[E0389]: cannot assign to data in a `&` reference
   --> $DIR/borrowck-issue-14498.rs:19:5
    |
-LL |     ***p = 2; //[ast]~ ERROR cannot assign to data in a `&` reference
+LL |     ***p = 2;
    |     ^^^^^^^^ assignment into an immutable reference
 
 error[E0506]: cannot assign to `**y` because it is borrowed
@@ -10,7 +10,7 @@
 LL |     let p = &y;
    |              - borrow of `**y` occurs here
 LL |     let q = &***p;
-LL |     **y = 2; //[ast]~ ERROR cannot assign to `**y` because it is borrowed
+LL |     **y = 2;
    |     ^^^^^^^ assignment to borrowed `**y` occurs here
 
 error[E0506]: cannot assign to `**y` because it is borrowed
@@ -19,7 +19,7 @@
 LL |     let p = &y;
    |              - borrow of `**y` occurs here
 LL |     let q = &***p;
-LL |     **y = 2; //[ast]~ ERROR cannot assign to `**y` because it is borrowed
+LL |     **y = 2;
    |     ^^^^^^^ assignment to borrowed `**y` occurs here
 
 error[E0506]: cannot assign to `**y` because it is borrowed
@@ -28,7 +28,7 @@
 LL |     let p = &y;
    |              - borrow of `**y` occurs here
 LL |     let q = &***p;
-LL |     **y = 2; //[ast]~ ERROR cannot assign to `**y` because it is borrowed
+LL |     **y = 2;
    |     ^^^^^^^ assignment to borrowed `**y` occurs here
 
 error[E0506]: cannot assign to `**y` because it is borrowed
@@ -37,7 +37,7 @@
 LL |     let p = &y;
    |              - borrow of `**y` occurs here
 LL |     let q = &***p;
-LL |     **y = 2; //[ast]~ ERROR cannot assign to `**y` because it is borrowed
+LL |     **y = 2;
    |     ^^^^^^^ assignment to borrowed `**y` occurs here
 
 error[E0506]: cannot assign to `**y.a` because it is borrowed
@@ -46,7 +46,7 @@
 LL |     let p = &y.a;
    |              --- borrow of `**y.a` occurs here
 LL |     let q = &***p;
-LL |     **y.a = 2; //[ast]~ ERROR cannot assign to `**y.a` because it is borrowed
+LL |     **y.a = 2;
    |     ^^^^^^^^^ assignment to borrowed `**y.a` occurs here
 
 error[E0506]: cannot assign to `**y.a` because it is borrowed
@@ -55,7 +55,7 @@
 LL |     let p = &y.a;
    |              --- borrow of `**y.a` occurs here
 LL |     let q = &***p;
-LL |     **y.a = 2; //[ast]~ ERROR cannot assign to `**y.a` because it is borrowed
+LL |     **y.a = 2;
    |     ^^^^^^^^^ assignment to borrowed `**y.a` occurs here
 
 error[E0506]: cannot assign to `**y.a` because it is borrowed
@@ -64,7 +64,7 @@
 LL |     let p = &y.a;
    |              --- borrow of `**y.a` occurs here
 LL |     let q = &***p;
-LL |     **y.a = 2; //[ast]~ ERROR cannot assign to `**y.a` because it is borrowed
+LL |     **y.a = 2;
    |     ^^^^^^^^^ assignment to borrowed `**y.a` occurs here
 
 error[E0506]: cannot assign to `**y.a` because it is borrowed
@@ -73,7 +73,7 @@
 LL |     let p = &y.a;
    |              --- borrow of `**y.a` occurs here
 LL |     let q = &***p;
-LL |     **y.a = 2; //[ast]~ ERROR cannot assign to `**y.a` because it is borrowed
+LL |     **y.a = 2;
    |     ^^^^^^^^^ assignment to borrowed `**y.a` occurs here
 
 error: aborting due to 9 previous errors
diff --git a/src/test/ui/borrowck/borrowck-issue-14498.mir.stderr b/src/test/ui/borrowck/borrowck-issue-14498.mir.stderr
index 8161053..b53cfdd 100644
--- a/src/test/ui/borrowck/borrowck-issue-14498.mir.stderr
+++ b/src/test/ui/borrowck/borrowck-issue-14498.mir.stderr
@@ -3,7 +3,7 @@
    |
 LL |     let p = &y;
    |             -- help: consider changing this to be a mutable reference: `&mut y`
-LL |     ***p = 2; //[ast]~ ERROR cannot assign to data in a `&` reference
+LL |     ***p = 2;
    |     ^^^^^^^^ `p` is a `&` reference, so the data it refers to cannot be written
 
 error[E0506]: cannot assign to `**y` because it is borrowed
@@ -12,9 +12,9 @@
 LL |     let p = &y;
    |             -- borrow of `**y` occurs here
 LL |     let q = &***p;
-LL |     **y = 2; //[ast]~ ERROR cannot assign to `**y` because it is borrowed
+LL |     **y = 2;
    |     ^^^^^^^ assignment to borrowed `**y` occurs here
-LL |              //[mir]~^ ERROR cannot assign to `**y` because it is borrowed
+LL |
 LL |     drop(p);
    |          - borrow later used here
 
@@ -24,9 +24,9 @@
 LL |     let p = &y;
    |             -- borrow of `**y` occurs here
 LL |     let q = &***p;
-LL |     **y = 2; //[ast]~ ERROR cannot assign to `**y` because it is borrowed
+LL |     **y = 2;
    |     ^^^^^^^ assignment to borrowed `**y` occurs here
-LL |              //[mir]~^ ERROR cannot assign to `**y` because it is borrowed
+LL |
 LL |     drop(p);
    |          - borrow later used here
 
@@ -36,9 +36,9 @@
 LL |     let p = &y;
    |             -- borrow of `**y` occurs here
 LL |     let q = &***p;
-LL |     **y = 2; //[ast]~ ERROR cannot assign to `**y` because it is borrowed
+LL |     **y = 2;
    |     ^^^^^^^ assignment to borrowed `**y` occurs here
-LL |              //[mir]~^ ERROR cannot assign to `**y` because it is borrowed
+LL |
 LL |     drop(p);
    |          - borrow later used here
 
@@ -48,9 +48,9 @@
 LL |     let p = &y;
    |             -- borrow of `**y` occurs here
 LL |     let q = &***p;
-LL |     **y = 2; //[ast]~ ERROR cannot assign to `**y` because it is borrowed
+LL |     **y = 2;
    |     ^^^^^^^ assignment to borrowed `**y` occurs here
-LL |              //[mir]~^ ERROR cannot assign to `**y` because it is borrowed
+LL |
 LL |     drop(p);
    |          - borrow later used here
 
@@ -60,9 +60,9 @@
 LL |     let p = &y.a;
    |             ---- borrow of `**y.a` occurs here
 LL |     let q = &***p;
-LL |     **y.a = 2; //[ast]~ ERROR cannot assign to `**y.a` because it is borrowed
+LL |     **y.a = 2;
    |     ^^^^^^^^^ assignment to borrowed `**y.a` occurs here
-LL |                //[mir]~^ ERROR cannot assign to `**y.a` because it is borrowed
+LL |
 LL |     drop(p);
    |          - borrow later used here
 
@@ -72,9 +72,9 @@
 LL |     let p = &y.a;
    |             ---- borrow of `**y.a` occurs here
 LL |     let q = &***p;
-LL |     **y.a = 2; //[ast]~ ERROR cannot assign to `**y.a` because it is borrowed
+LL |     **y.a = 2;
    |     ^^^^^^^^^ assignment to borrowed `**y.a` occurs here
-LL |                //[mir]~^ ERROR cannot assign to `**y.a` because it is borrowed
+LL |
 LL |     drop(p);
    |          - borrow later used here
 
@@ -84,9 +84,9 @@
 LL |     let p = &y.a;
    |             ---- borrow of `**y.a` occurs here
 LL |     let q = &***p;
-LL |     **y.a = 2; //[ast]~ ERROR cannot assign to `**y.a` because it is borrowed
+LL |     **y.a = 2;
    |     ^^^^^^^^^ assignment to borrowed `**y.a` occurs here
-LL |                //[mir]~^ ERROR cannot assign to `**y.a` because it is borrowed
+LL |
 LL |     drop(p);
    |          - borrow later used here
 
@@ -96,9 +96,9 @@
 LL |     let p = &y.a;
    |             ---- borrow of `**y.a` occurs here
 LL |     let q = &***p;
-LL |     **y.a = 2; //[ast]~ ERROR cannot assign to `**y.a` because it is borrowed
+LL |     **y.a = 2;
    |     ^^^^^^^^^ assignment to borrowed `**y.a` occurs here
-LL |                //[mir]~^ ERROR cannot assign to `**y.a` because it is borrowed
+LL |
 LL |     drop(p);
    |          - borrow later used here
 
diff --git a/src/test/ui/borrowck/borrowck-lend-flow-loop.ast.stderr b/src/test/ui/borrowck/borrowck-lend-flow-loop.ast.stderr
index 1844d82..ab10caa 100644
--- a/src/test/ui/borrowck/borrowck-lend-flow-loop.ast.stderr
+++ b/src/test/ui/borrowck/borrowck-lend-flow-loop.ast.stderr
@@ -4,7 +4,7 @@
 LL |     let mut x = &mut v;
    |                      - mutable borrow occurs here
 ...
-LL |         borrow(&*v); //[ast]~ ERROR cannot borrow
+LL |         borrow(&*v);
    |                 ^^ immutable borrow occurs here
 LL |     }
 LL | }
@@ -16,7 +16,7 @@
 LL |     let mut x = &mut v;
    |                      - mutable borrow occurs here
 LL |     for _ in 0..3 {
-LL |         borrow(&*v); //[ast]~ ERROR cannot borrow
+LL |         borrow(&*v);
    |                 ^^ immutable borrow occurs here
 ...
 LL | }
@@ -25,7 +25,7 @@
 error[E0502]: cannot borrow `*v` as mutable because `v` is also borrowed as immutable
   --> $DIR/borrowck-lend-flow-loop.rs:57:25
    |
-LL |         borrow_mut(&mut *v); //[ast]~ ERROR cannot borrow
+LL |         borrow_mut(&mut *v);
    |                         ^^ mutable borrow occurs here
 LL |         _x = &v;
    |               - immutable borrow occurs here
@@ -36,7 +36,7 @@
 error[E0502]: cannot borrow `*v` as mutable because `v` is also borrowed as immutable
   --> $DIR/borrowck-lend-flow-loop.rs:69:25
    |
-LL |         borrow_mut(&mut *v); //[ast]~ ERROR cannot borrow
+LL |         borrow_mut(&mut *v);
    |                         ^^ mutable borrow occurs here
 LL |         _x = &v;
    |               - immutable borrow occurs here
@@ -50,7 +50,7 @@
 LL |         _x = &v;
    |               - immutable borrow occurs here
 ...
-LL |     borrow_mut(&mut *v); //[ast]~ ERROR cannot borrow
+LL |     borrow_mut(&mut *v);
    |                     ^^ mutable borrow occurs here
 LL | }
    | - immutable borrow ends here
@@ -61,7 +61,7 @@
 LL |         _x = &v;
    |               - immutable borrow occurs here
 ...
-LL |     borrow_mut(&mut *v); //[ast]~ ERROR cannot borrow
+LL |     borrow_mut(&mut *v);
    |                     ^^ mutable borrow occurs here
 LL | }
    | - immutable borrow ends here
@@ -69,10 +69,10 @@
 error[E0502]: cannot borrow `*v` as immutable because `v` is also borrowed as mutable
   --> $DIR/borrowck-lend-flow-loop.rs:109:17
    |
-LL |         borrow(&*v); //[ast]~ ERROR cannot borrow
+LL |         borrow(&*v);
    |                 ^^ immutable borrow occurs here
 ...
-LL |             x = &mut v; //[ast]~ ERROR cannot borrow
+LL |             x = &mut v;
    |                      - mutable borrow occurs here
 ...
 LL | }
@@ -81,7 +81,7 @@
 error[E0499]: cannot borrow `v` as mutable more than once at a time
   --> $DIR/borrowck-lend-flow-loop.rs:112:22
    |
-LL |             x = &mut v; //[ast]~ ERROR cannot borrow
+LL |             x = &mut v;
    |                      ^ mutable borrow starts here in previous iteration of loop
 ...
 LL | }
diff --git a/src/test/ui/borrowck/borrowck-lend-flow-loop.nll.stderr b/src/test/ui/borrowck/borrowck-lend-flow-loop.nll.stderr
index 396fd6f..6dd6c1f 100644
--- a/src/test/ui/borrowck/borrowck-lend-flow-loop.nll.stderr
+++ b/src/test/ui/borrowck/borrowck-lend-flow-loop.nll.stderr
@@ -4,7 +4,7 @@
 LL |     let mut x = &mut v;
    |                 ------ mutable borrow occurs here
 LL |     for _ in 0..3 {
-LL |         borrow(&*v); //[ast]~ ERROR cannot borrow
+LL |         borrow(&*v);
    |                ^^^ immutable borrow occurs here
 ...
 LL |     *x = box 5;
@@ -15,10 +15,10 @@
    |
 LL |         **x += 1;
    |         -------- mutable borrow later used here
-LL |         borrow(&*v); //[ast]~ ERROR cannot borrow
+LL |         borrow(&*v);
    |                ^^^ immutable borrow occurs here
 ...
-LL |             x = &mut v; //[ast]~ ERROR cannot borrow
+LL |             x = &mut v;
    |                 ------ mutable borrow occurs here
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/borrowck/borrowck-lend-flow-match.ast.nll.stderr b/src/test/ui/borrowck/borrowck-lend-flow-match.ast.nll.stderr
index 02289e0..734f965 100644
--- a/src/test/ui/borrowck/borrowck-lend-flow-match.ast.nll.stderr
+++ b/src/test/ui/borrowck/borrowck-lend-flow-match.ast.nll.stderr
@@ -3,9 +3,9 @@
    |
 LL |         Some(ref r) => {
    |              ----- borrow of `x` occurs here
-LL |             x = Some(1); //[ast]~ ERROR cannot assign
+LL |             x = Some(1);
    |             ^^^^^^^^^^^ assignment to borrowed `x` occurs here
-LL |             //[mir]~^ ERROR cannot assign to `x` because it is borrowed
+LL |
 LL |             drop(r);
    |                  - borrow later used here
 
diff --git a/src/test/ui/borrowck/borrowck-lend-flow-match.ast.stderr b/src/test/ui/borrowck/borrowck-lend-flow-match.ast.stderr
index 23eb814..236bc11 100644
--- a/src/test/ui/borrowck/borrowck-lend-flow-match.ast.stderr
+++ b/src/test/ui/borrowck/borrowck-lend-flow-match.ast.stderr
@@ -3,7 +3,7 @@
    |
 LL |         Some(ref r) => {
    |              ----- borrow of `x` occurs here
-LL |             x = Some(1); //[ast]~ ERROR cannot assign
+LL |             x = Some(1);
    |             ^^^^^^^^^^^ assignment to borrowed `x` occurs here
 
 error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-lend-flow-match.mir.stderr b/src/test/ui/borrowck/borrowck-lend-flow-match.mir.stderr
index 02289e0..734f965 100644
--- a/src/test/ui/borrowck/borrowck-lend-flow-match.mir.stderr
+++ b/src/test/ui/borrowck/borrowck-lend-flow-match.mir.stderr
@@ -3,9 +3,9 @@
    |
 LL |         Some(ref r) => {
    |              ----- borrow of `x` occurs here
-LL |             x = Some(1); //[ast]~ ERROR cannot assign
+LL |             x = Some(1);
    |             ^^^^^^^^^^^ assignment to borrowed `x` occurs here
-LL |             //[mir]~^ ERROR cannot assign to `x` because it is borrowed
+LL |
 LL |             drop(r);
    |                  - borrow later used here
 
diff --git a/src/test/ui/borrowck/borrowck-match-already-borrowed.ast.nll.stderr b/src/test/ui/borrowck/borrowck-match-already-borrowed.ast.nll.stderr
index b2b82fb..ecbfeec 100644
--- a/src/test/ui/borrowck/borrowck-match-already-borrowed.ast.nll.stderr
+++ b/src/test/ui/borrowck/borrowck-match-already-borrowed.ast.nll.stderr
@@ -4,7 +4,7 @@
 LL |     let p = &mut foo;
    |             -------- borrow of `foo` occurs here
 LL |     let _ = match foo {
-LL |         Foo::B => 1, //[mir]~ ERROR [E0503]
+LL |         Foo::B => 1,
    |         ^^^^^^ use of borrowed `foo`
 ...
 LL |     drop(p);
@@ -16,7 +16,7 @@
 LL |     let p = &mut foo;
    |             -------- borrow of `foo` occurs here
 ...
-LL |         Foo::A(x) => x //[ast]~ ERROR [E0503]
+LL |         Foo::A(x) => x
    |                ^ use of borrowed `foo`
 ...
 LL |     drop(p);
@@ -28,7 +28,7 @@
 LL |     let r = &mut x;
    |             ------ borrow of `x` occurs here
 LL |     let _ = match x {
-LL |         x => x + 1, //[ast]~ ERROR [E0503]
+LL |         x => x + 1,
    |         ^ use of borrowed `x`
 ...
 LL |     drop(r);
@@ -40,7 +40,7 @@
 LL |     let r = &mut x;
    |             ------ borrow of `x` occurs here
 ...
-LL |         y => y + 2, //[ast]~ ERROR [E0503]
+LL |         y => y + 2,
    |         ^ use of borrowed `x`
 ...
 LL |     drop(r);
diff --git a/src/test/ui/borrowck/borrowck-match-already-borrowed.ast.stderr b/src/test/ui/borrowck/borrowck-match-already-borrowed.ast.stderr
index cfbbef9..a5da1fc 100644
--- a/src/test/ui/borrowck/borrowck-match-already-borrowed.ast.stderr
+++ b/src/test/ui/borrowck/borrowck-match-already-borrowed.ast.stderr
@@ -4,7 +4,7 @@
 LL |     let p = &mut foo;
    |                  --- borrow of `foo` occurs here
 ...
-LL |         Foo::A(x) => x //[ast]~ ERROR [E0503]
+LL |         Foo::A(x) => x
    |                ^ use of borrowed `foo`
 
 error[E0503]: cannot use `x` because it was mutably borrowed
@@ -13,7 +13,7 @@
 LL |     let r = &mut x;
    |                  - borrow of `x` occurs here
 LL |     let _ = match x {
-LL |         x => x + 1, //[ast]~ ERROR [E0503]
+LL |         x => x + 1,
    |         ^ use of borrowed `x`
 
 error[E0503]: cannot use `x` because it was mutably borrowed
@@ -22,7 +22,7 @@
 LL |     let r = &mut x;
    |                  - borrow of `x` occurs here
 ...
-LL |         y => y + 2, //[ast]~ ERROR [E0503]
+LL |         y => y + 2,
    |         ^ use of borrowed `x`
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/borrowck/borrowck-match-already-borrowed.mir.stderr b/src/test/ui/borrowck/borrowck-match-already-borrowed.mir.stderr
index b2b82fb..ecbfeec 100644
--- a/src/test/ui/borrowck/borrowck-match-already-borrowed.mir.stderr
+++ b/src/test/ui/borrowck/borrowck-match-already-borrowed.mir.stderr
@@ -4,7 +4,7 @@
 LL |     let p = &mut foo;
    |             -------- borrow of `foo` occurs here
 LL |     let _ = match foo {
-LL |         Foo::B => 1, //[mir]~ ERROR [E0503]
+LL |         Foo::B => 1,
    |         ^^^^^^ use of borrowed `foo`
 ...
 LL |     drop(p);
@@ -16,7 +16,7 @@
 LL |     let p = &mut foo;
    |             -------- borrow of `foo` occurs here
 ...
-LL |         Foo::A(x) => x //[ast]~ ERROR [E0503]
+LL |         Foo::A(x) => x
    |                ^ use of borrowed `foo`
 ...
 LL |     drop(p);
@@ -28,7 +28,7 @@
 LL |     let r = &mut x;
    |             ------ borrow of `x` occurs here
 LL |     let _ = match x {
-LL |         x => x + 1, //[ast]~ ERROR [E0503]
+LL |         x => x + 1,
    |         ^ use of borrowed `x`
 ...
 LL |     drop(r);
@@ -40,7 +40,7 @@
 LL |     let r = &mut x;
    |             ------ borrow of `x` occurs here
 ...
-LL |         y => y + 2, //[ast]~ ERROR [E0503]
+LL |         y => y + 2,
    |         ^ use of borrowed `x`
 ...
 LL |     drop(r);
diff --git a/src/test/ui/borrowck/borrowck-match-binding-is-assignment.ast.nll.stderr b/src/test/ui/borrowck/borrowck-match-binding-is-assignment.ast.nll.stderr
index cd88d69..2ac0539 100644
--- a/src/test/ui/borrowck/borrowck-match-binding-is-assignment.ast.nll.stderr
+++ b/src/test/ui/borrowck/borrowck-match-binding-is-assignment.ast.nll.stderr
@@ -6,7 +6,7 @@
    |         |
    |         first assignment to `x`
    |         help: make this binding mutable: `mut x`
-LL |             x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x`
+LL |             x += 1;
    |             ^^^^^^ cannot assign twice to immutable variable
 
 error[E0384]: cannot assign twice to immutable variable `x`
@@ -17,7 +17,7 @@
    |                |
    |                first assignment to `x`
    |                help: make this binding mutable: `mut x`
-LL |             x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x`
+LL |             x += 1;
    |             ^^^^^^ cannot assign twice to immutable variable
 
 error[E0384]: cannot assign twice to immutable variable `x`
@@ -28,7 +28,7 @@
    |                  |
    |                  first assignment to `x`
    |                  help: make this binding mutable: `mut x`
-LL |             x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x`
+LL |             x += 1;
    |             ^^^^^^ cannot assign twice to immutable variable
 
 error[E0384]: cannot assign twice to immutable variable `x`
@@ -39,7 +39,7 @@
    |          |
    |          first assignment to `x`
    |          help: make this binding mutable: `mut x`
-LL |             x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x`
+LL |             x += 1;
    |             ^^^^^^ cannot assign twice to immutable variable
 
 error[E0384]: cannot assign twice to immutable variable `x`
@@ -50,7 +50,7 @@
    |          |
    |          first assignment to `x`
    |          help: make this binding mutable: `mut x`
-LL |             x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x`
+LL |             x += 1;
    |             ^^^^^^ cannot assign twice to immutable variable
 
 error: aborting due to 5 previous errors
diff --git a/src/test/ui/borrowck/borrowck-match-binding-is-assignment.ast.stderr b/src/test/ui/borrowck/borrowck-match-binding-is-assignment.ast.stderr
index e7bd9df..5f43302 100644
--- a/src/test/ui/borrowck/borrowck-match-binding-is-assignment.ast.stderr
+++ b/src/test/ui/borrowck/borrowck-match-binding-is-assignment.ast.stderr
@@ -3,7 +3,7 @@
    |
 LL |         x => {
    |         - first assignment to `x`
-LL |             x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x`
+LL |             x += 1;
    |             ^^^^^^ cannot assign twice to immutable variable
 
 error[E0384]: cannot assign twice to immutable variable `x`
@@ -11,7 +11,7 @@
    |
 LL |         E::Foo(x) => {
    |                - first assignment to `x`
-LL |             x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x`
+LL |             x += 1;
    |             ^^^^^^ cannot assign twice to immutable variable
 
 error[E0384]: cannot assign twice to immutable variable `x`
@@ -19,7 +19,7 @@
    |
 LL |         S { bar: x } => {
    |                  - first assignment to `x`
-LL |             x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x`
+LL |             x += 1;
    |             ^^^^^^ cannot assign twice to immutable variable
 
 error[E0384]: cannot assign twice to immutable variable `x`
@@ -27,7 +27,7 @@
    |
 LL |         (x,) => {
    |          - first assignment to `x`
-LL |             x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x`
+LL |             x += 1;
    |             ^^^^^^ cannot assign twice to immutable variable
 
 error[E0384]: cannot assign twice to immutable variable `x`
@@ -35,7 +35,7 @@
    |
 LL |         [x,_,_] => {
    |          - first assignment to `x`
-LL |             x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x`
+LL |             x += 1;
    |             ^^^^^^ cannot assign twice to immutable variable
 
 error: aborting due to 5 previous errors
diff --git a/src/test/ui/borrowck/borrowck-match-binding-is-assignment.mir.stderr b/src/test/ui/borrowck/borrowck-match-binding-is-assignment.mir.stderr
index cd88d69..2ac0539 100644
--- a/src/test/ui/borrowck/borrowck-match-binding-is-assignment.mir.stderr
+++ b/src/test/ui/borrowck/borrowck-match-binding-is-assignment.mir.stderr
@@ -6,7 +6,7 @@
    |         |
    |         first assignment to `x`
    |         help: make this binding mutable: `mut x`
-LL |             x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x`
+LL |             x += 1;
    |             ^^^^^^ cannot assign twice to immutable variable
 
 error[E0384]: cannot assign twice to immutable variable `x`
@@ -17,7 +17,7 @@
    |                |
    |                first assignment to `x`
    |                help: make this binding mutable: `mut x`
-LL |             x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x`
+LL |             x += 1;
    |             ^^^^^^ cannot assign twice to immutable variable
 
 error[E0384]: cannot assign twice to immutable variable `x`
@@ -28,7 +28,7 @@
    |                  |
    |                  first assignment to `x`
    |                  help: make this binding mutable: `mut x`
-LL |             x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x`
+LL |             x += 1;
    |             ^^^^^^ cannot assign twice to immutable variable
 
 error[E0384]: cannot assign twice to immutable variable `x`
@@ -39,7 +39,7 @@
    |          |
    |          first assignment to `x`
    |          help: make this binding mutable: `mut x`
-LL |             x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x`
+LL |             x += 1;
    |             ^^^^^^ cannot assign twice to immutable variable
 
 error[E0384]: cannot assign twice to immutable variable `x`
@@ -50,7 +50,7 @@
    |          |
    |          first assignment to `x`
    |          help: make this binding mutable: `mut x`
-LL |             x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x`
+LL |             x += 1;
    |             ^^^^^^ cannot assign twice to immutable variable
 
 error: aborting due to 5 previous errors
diff --git a/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.ast.nll.stderr b/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.ast.nll.stderr
index 0789926..874c38c 100644
--- a/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.ast.nll.stderr
+++ b/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.ast.nll.stderr
@@ -8,7 +8,7 @@
    |            ------    - variable moved due to use in closure
    |            |
    |            value moved into closure here
-LL |     call_f(move|| { *t + 1 }); //[ast]~ ERROR capture of moved value
+LL |     call_f(move|| { *t + 1 });
    |            ^^^^^^    - use occurs due to use in closure
    |            |
    |            value used here after move
diff --git a/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.ast.stderr b/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.ast.stderr
index 308dac8..48651ee 100644
--- a/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.ast.stderr
+++ b/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.ast.stderr
@@ -3,7 +3,7 @@
    |
 LL |     call_f(move|| { *t + 1 });
    |            ------ value moved (into closure) here
-LL |     call_f(move|| { *t + 1 }); //[ast]~ ERROR capture of moved value
+LL |     call_f(move|| { *t + 1 });
    |                      ^ value captured here after move
    |
    = note: move occurs because `t` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
diff --git a/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.mir.stderr b/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.mir.stderr
index 0789926..874c38c 100644
--- a/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.mir.stderr
+++ b/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.mir.stderr
@@ -8,7 +8,7 @@
    |            ------    - variable moved due to use in closure
    |            |
    |            value moved into closure here
-LL |     call_f(move|| { *t + 1 }); //[ast]~ ERROR capture of moved value
+LL |     call_f(move|| { *t + 1 });
    |            ^^^^^^    - use occurs due to use in closure
    |            |
    |            value used here after move
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array.ast.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array.ast.stderr
index f866ff9..88a1ab2 100644
--- a/src/test/ui/borrowck/borrowck-move-out-from-array.ast.stderr
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array.ast.stderr
@@ -3,7 +3,7 @@
    |
 LL |     let [_, _x] = a;
    |             -- value moved here
-LL |     let [.., _y] = a; //[ast]~ ERROR [E0382]
+LL |     let [.., _y] = a;
    |              ^^ value used here after move
    |
    = note: move occurs because `a[..]` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
@@ -13,7 +13,7 @@
    |
 LL |     let [_x, _] = a;
    |          -- value moved here
-LL |     let [_y..] = a; //[ast]~ ERROR [E0382]
+LL |     let [_y..] = a;
    |          ^^ value used here after move
    |
    = note: move occurs because `a[..]` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array.mir.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array.mir.stderr
index f866ff9..88a1ab2 100644
--- a/src/test/ui/borrowck/borrowck-move-out-from-array.mir.stderr
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array.mir.stderr
@@ -3,7 +3,7 @@
    |
 LL |     let [_, _x] = a;
    |             -- value moved here
-LL |     let [.., _y] = a; //[ast]~ ERROR [E0382]
+LL |     let [.., _y] = a;
    |              ^^ value used here after move
    |
    = note: move occurs because `a[..]` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
@@ -13,7 +13,7 @@
    |
 LL |     let [_x, _] = a;
    |          -- value moved here
-LL |     let [_y..] = a; //[ast]~ ERROR [E0382]
+LL |     let [_y..] = a;
    |          ^^ value used here after move
    |
    = note: move occurs because `a[..]` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-static-item.ast.stderr b/src/test/ui/borrowck/borrowck-move-out-of-static-item.ast.stderr
index 752d533..26d06c0 100644
--- a/src/test/ui/borrowck/borrowck-move-out-of-static-item.ast.stderr
+++ b/src/test/ui/borrowck/borrowck-move-out-of-static-item.ast.stderr
@@ -1,7 +1,7 @@
 error[E0507]: cannot move out of static item
   --> $DIR/borrowck-move-out-of-static-item.rs:18:10
    |
-LL |     test(BAR); //[ast]~ ERROR cannot move out of static item [E0507]
+LL |     test(BAR);
    |          ^^^ cannot move out of static item
 
 error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-static-item.mir.stderr b/src/test/ui/borrowck/borrowck-move-out-of-static-item.mir.stderr
index 752d533..26d06c0 100644
--- a/src/test/ui/borrowck/borrowck-move-out-of-static-item.mir.stderr
+++ b/src/test/ui/borrowck/borrowck-move-out-of-static-item.mir.stderr
@@ -1,7 +1,7 @@
 error[E0507]: cannot move out of static item
   --> $DIR/borrowck-move-out-of-static-item.rs:18:10
    |
-LL |     test(BAR); //[ast]~ ERROR cannot move out of static item [E0507]
+LL |     test(BAR);
    |          ^^^ cannot move out of static item
 
 error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.ast.nll.stderr b/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.ast.nll.stderr
index 7025ce0..c1c04ca 100644
--- a/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.ast.nll.stderr
+++ b/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.ast.nll.stderr
@@ -3,7 +3,7 @@
    |
 LL |     match (S {f:"foo".to_string()}) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
-LL |         //[mir]~^ ERROR [E0509]
+LL |
 LL |         S {f:_s} => {}
    |              -- data moved here
    |
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.mir.stderr b/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.mir.stderr
index 7025ce0..c1c04ca 100644
--- a/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.mir.stderr
+++ b/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.mir.stderr
@@ -3,7 +3,7 @@
    |
 LL |     match (S {f:"foo".to_string()}) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
-LL |         //[mir]~^ ERROR [E0509]
+LL |
 LL |         S {f:_s} => {}
    |              -- data moved here
    |
diff --git a/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.ast.nll.stderr b/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.ast.nll.stderr
index 0f07776..a6e7d74 100644
--- a/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.ast.nll.stderr
+++ b/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.ast.nll.stderr
@@ -1,30 +1,30 @@
 error[E0499]: cannot borrow `x` as mutable more than once at a time
   --> $DIR/borrowck-mut-borrow-linear-errors.rs:13:30
    |
-LL |             1 => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
+LL |             1 => { addr.push(&mut x); }
    |                    ----      ^^^^^^ second mutable borrow occurs here
    |                    |
    |                    first borrow later used here
 ...
-LL |             _ => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
+LL |             _ => { addr.push(&mut x); }
    |                              ------ first mutable borrow occurs here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time
   --> $DIR/borrowck-mut-borrow-linear-errors.rs:15:30
    |
-LL |             1 => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
+LL |             1 => { addr.push(&mut x); }
    |                    ---- first borrow later used here
-LL |             //[mir]~^ ERROR [E0499]
-LL |             2 => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
+LL |
+LL |             2 => { addr.push(&mut x); }
    |                              ^^^^^^ second mutable borrow occurs here
-LL |             //[mir]~^ ERROR [E0499]
-LL |             _ => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
+LL |
+LL |             _ => { addr.push(&mut x); }
    |                              ------ first mutable borrow occurs here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time
   --> $DIR/borrowck-mut-borrow-linear-errors.rs:17:30
    |
-LL |             _ => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
+LL |             _ => { addr.push(&mut x); }
    |                              ^^^^^^ mutable borrow starts here in previous iteration of loop
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.ast.stderr b/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.ast.stderr
index dafb60c..cee61db 100644
--- a/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.ast.stderr
+++ b/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.ast.stderr
@@ -1,7 +1,7 @@
 error[E0499]: cannot borrow `x` as mutable more than once at a time
   --> $DIR/borrowck-mut-borrow-linear-errors.rs:13:35
    |
-LL |             1 => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
+LL |             1 => { addr.push(&mut x); }
    |                                   ^ mutable borrow starts here in previous iteration of loop
 ...
 LL | }
@@ -10,10 +10,10 @@
 error[E0499]: cannot borrow `x` as mutable more than once at a time
   --> $DIR/borrowck-mut-borrow-linear-errors.rs:15:35
    |
-LL |             1 => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
+LL |             1 => { addr.push(&mut x); }
    |                                   - first mutable borrow occurs here
-LL |             //[mir]~^ ERROR [E0499]
-LL |             2 => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
+LL |
+LL |             2 => { addr.push(&mut x); }
    |                                   ^ second mutable borrow occurs here
 ...
 LL | }
@@ -22,10 +22,10 @@
 error[E0499]: cannot borrow `x` as mutable more than once at a time
   --> $DIR/borrowck-mut-borrow-linear-errors.rs:17:35
    |
-LL |             1 => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
+LL |             1 => { addr.push(&mut x); }
    |                                   - first mutable borrow occurs here
 ...
-LL |             _ => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
+LL |             _ => { addr.push(&mut x); }
    |                                   ^ second mutable borrow occurs here
 ...
 LL | }
diff --git a/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.mir.stderr b/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.mir.stderr
index 0f07776..a6e7d74 100644
--- a/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.mir.stderr
+++ b/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.mir.stderr
@@ -1,30 +1,30 @@
 error[E0499]: cannot borrow `x` as mutable more than once at a time
   --> $DIR/borrowck-mut-borrow-linear-errors.rs:13:30
    |
-LL |             1 => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
+LL |             1 => { addr.push(&mut x); }
    |                    ----      ^^^^^^ second mutable borrow occurs here
    |                    |
    |                    first borrow later used here
 ...
-LL |             _ => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
+LL |             _ => { addr.push(&mut x); }
    |                              ------ first mutable borrow occurs here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time
   --> $DIR/borrowck-mut-borrow-linear-errors.rs:15:30
    |
-LL |             1 => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
+LL |             1 => { addr.push(&mut x); }
    |                    ---- first borrow later used here
-LL |             //[mir]~^ ERROR [E0499]
-LL |             2 => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
+LL |
+LL |             2 => { addr.push(&mut x); }
    |                              ^^^^^^ second mutable borrow occurs here
-LL |             //[mir]~^ ERROR [E0499]
-LL |             _ => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
+LL |
+LL |             _ => { addr.push(&mut x); }
    |                              ------ first mutable borrow occurs here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time
   --> $DIR/borrowck-mut-borrow-linear-errors.rs:17:30
    |
-LL |             _ => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
+LL |             _ => { addr.push(&mut x); }
    |                              ^^^^^^ mutable borrow starts here in previous iteration of loop
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/borrowck/borrowck-pat-reassign-binding.ast.nll.stderr b/src/test/ui/borrowck/borrowck-pat-reassign-binding.ast.nll.stderr
index d65ba12..f0e1683 100644
--- a/src/test/ui/borrowck/borrowck-pat-reassign-binding.ast.nll.stderr
+++ b/src/test/ui/borrowck/borrowck-pat-reassign-binding.ast.nll.stderr
@@ -4,9 +4,9 @@
 LL |       Some(ref i) => {
    |            ----- borrow of `x` occurs here
 LL |           // But on this branch, `i` is an outstanding borrow
-LL |           x = Some(*i+1); //[ast]~ ERROR cannot assign to `x`
+LL |           x = Some(*i+1);
    |           ^^^^^^^^^^^^^^ assignment to borrowed `x` occurs here
-LL |           //[mir]~^ ERROR cannot assign to `x` because it is borrowed
+LL |
 LL |           drop(i);
    |                - borrow later used here
 
diff --git a/src/test/ui/borrowck/borrowck-pat-reassign-binding.ast.stderr b/src/test/ui/borrowck/borrowck-pat-reassign-binding.ast.stderr
index 207f971..d7bce40 100644
--- a/src/test/ui/borrowck/borrowck-pat-reassign-binding.ast.stderr
+++ b/src/test/ui/borrowck/borrowck-pat-reassign-binding.ast.stderr
@@ -4,7 +4,7 @@
 LL |       Some(ref i) => {
    |            ----- borrow of `x` occurs here
 LL |           // But on this branch, `i` is an outstanding borrow
-LL |           x = Some(*i+1); //[ast]~ ERROR cannot assign to `x`
+LL |           x = Some(*i+1);
    |           ^^^^^^^^^^^^^^ assignment to borrowed `x` occurs here
 
 error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-pat-reassign-binding.mir.stderr b/src/test/ui/borrowck/borrowck-pat-reassign-binding.mir.stderr
index d65ba12..f0e1683 100644
--- a/src/test/ui/borrowck/borrowck-pat-reassign-binding.mir.stderr
+++ b/src/test/ui/borrowck/borrowck-pat-reassign-binding.mir.stderr
@@ -4,9 +4,9 @@
 LL |       Some(ref i) => {
    |            ----- borrow of `x` occurs here
 LL |           // But on this branch, `i` is an outstanding borrow
-LL |           x = Some(*i+1); //[ast]~ ERROR cannot assign to `x`
+LL |           x = Some(*i+1);
    |           ^^^^^^^^^^^^^^ assignment to borrowed `x` occurs here
-LL |           //[mir]~^ ERROR cannot assign to `x` because it is borrowed
+LL |
 LL |           drop(i);
    |                - borrow later used here
 
diff --git a/src/test/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.ast.nll.stderr b/src/test/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.ast.nll.stderr
index 34d08a0..d2b6e06 100644
--- a/src/test/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.ast.nll.stderr
+++ b/src/test/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.ast.nll.stderr
@@ -1,9 +1,9 @@
 error[E0712]: thread-local variable borrowed past end of function
   --> $DIR/borrowck-thread-local-static-borrow-outlives-fn.rs:11:20
    |
-LL |      assert_static(&FOO); //[ast]~ ERROR [E0597]
+LL |      assert_static(&FOO);
    |                    ^^^^ thread-local variables cannot be borrowed beyond the end of the function
-LL |                           //[mir]~^ ERROR [E0712]
+LL |
 LL | }
    | - end of enclosing function is here
 
diff --git a/src/test/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.ast.stderr b/src/test/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.ast.stderr
index 4724f17..ce7b5e6 100644
--- a/src/test/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.ast.stderr
+++ b/src/test/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.ast.stderr
@@ -1,7 +1,7 @@
 error[E0597]: borrowed value does not live long enough
   --> $DIR/borrowck-thread-local-static-borrow-outlives-fn.rs:11:21
    |
-LL |      assert_static(&FOO); //[ast]~ ERROR [E0597]
+LL |      assert_static(&FOO);
    |                     ^^^ - borrowed value only lives until here
    |                     |
    |                     borrowed value does not live long enough
diff --git a/src/test/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.mir.stderr b/src/test/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.mir.stderr
index 34d08a0..d2b6e06 100644
--- a/src/test/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.mir.stderr
+++ b/src/test/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.mir.stderr
@@ -1,9 +1,9 @@
 error[E0712]: thread-local variable borrowed past end of function
   --> $DIR/borrowck-thread-local-static-borrow-outlives-fn.rs:11:20
    |
-LL |      assert_static(&FOO); //[ast]~ ERROR [E0597]
+LL |      assert_static(&FOO);
    |                    ^^^^ thread-local variables cannot be borrowed beyond the end of the function
-LL |                           //[mir]~^ ERROR [E0712]
+LL |
 LL | }
    | - end of enclosing function is here
 
diff --git a/src/test/ui/borrowck/borrowck-unary-move.ast.nll.stderr b/src/test/ui/borrowck/borrowck-unary-move.ast.nll.stderr
index 53dc6a7..c29ff53 100644
--- a/src/test/ui/borrowck/borrowck-unary-move.ast.nll.stderr
+++ b/src/test/ui/borrowck/borrowck-unary-move.ast.nll.stderr
@@ -3,9 +3,9 @@
    |
 LL |     let y = &*x;
    |             --- borrow of `*x` occurs here
-LL |     free(x); //[ast]~ ERROR cannot move out of `x` because it is borrowed
+LL |     free(x);
    |          ^ move out of `x` occurs here
-LL |     //[mir]~^ ERROR cannot move out of `x` because it is borrowed
+LL |
 LL |     *y
    |     -- borrow later used here
 
diff --git a/src/test/ui/borrowck/borrowck-unary-move.ast.stderr b/src/test/ui/borrowck/borrowck-unary-move.ast.stderr
index 9383298..e05b110 100644
--- a/src/test/ui/borrowck/borrowck-unary-move.ast.stderr
+++ b/src/test/ui/borrowck/borrowck-unary-move.ast.stderr
@@ -3,7 +3,7 @@
    |
 LL |     let y = &*x;
    |              -- borrow of `*x` occurs here
-LL |     free(x); //[ast]~ ERROR cannot move out of `x` because it is borrowed
+LL |     free(x);
    |          ^ move out of `x` occurs here
 
 error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-unary-move.mir.stderr b/src/test/ui/borrowck/borrowck-unary-move.mir.stderr
index 53dc6a7..c29ff53 100644
--- a/src/test/ui/borrowck/borrowck-unary-move.mir.stderr
+++ b/src/test/ui/borrowck/borrowck-unary-move.mir.stderr
@@ -3,9 +3,9 @@
    |
 LL |     let y = &*x;
    |             --- borrow of `*x` occurs here
-LL |     free(x); //[ast]~ ERROR cannot move out of `x` because it is borrowed
+LL |     free(x);
    |          ^ move out of `x` occurs here
-LL |     //[mir]~^ ERROR cannot move out of `x` because it is borrowed
+LL |
 LL |     *y
    |     -- borrow later used here
 
diff --git a/src/test/ui/borrowck/borrowck-uninit-field-access.ast.nll.stderr b/src/test/ui/borrowck/borrowck-uninit-field-access.ast.nll.stderr
index 99cbf64..a6e5f0b 100644
--- a/src/test/ui/borrowck/borrowck-uninit-field-access.ast.nll.stderr
+++ b/src/test/ui/borrowck/borrowck-uninit-field-access.ast.nll.stderr
@@ -1,7 +1,7 @@
 error[E0381]: use of possibly uninitialized variable: `a`
   --> $DIR/borrowck-uninit-field-access.rs:24:13
    |
-LL |     let _ = a.x + 1; //[ast]~ ERROR use of possibly uninitialized variable: `a.x`
+LL |     let _ = a.x + 1;
    |             ^^^ use of possibly uninitialized `a.x`
 
 error[E0382]: use of moved value: `line1.origin`
@@ -9,7 +9,7 @@
    |
 LL |     let _moved = line1.origin;
    |                  ------------ value moved here
-LL |     let _ = line1.origin.x + 1; //[ast]~ ERROR use of moved value: `line1.origin.x`
+LL |     let _ = line1.origin.x + 1;
    |             ^^^^^^^^^^^^^^ value used here after move
    |
    = note: move occurs because `line1.origin` has type `Point`, which does not implement the `Copy` trait
@@ -19,7 +19,7 @@
    |
 LL |     let _moved = (line2.origin, line2.middle);
    |                                 ------------ value moved here
-LL |     line2.consume(); //[ast]~ ERROR use of partially moved value: `line2` [E0382]
+LL |     line2.consume();
    |     ^^^^^ value used here after partial move
    |
    = note: move occurs because `line2.middle` has type `Point`, which does not implement the `Copy` trait
diff --git a/src/test/ui/borrowck/borrowck-uninit-field-access.ast.stderr b/src/test/ui/borrowck/borrowck-uninit-field-access.ast.stderr
index 8c05272..58fc1d4 100644
--- a/src/test/ui/borrowck/borrowck-uninit-field-access.ast.stderr
+++ b/src/test/ui/borrowck/borrowck-uninit-field-access.ast.stderr
@@ -1,7 +1,7 @@
 error[E0381]: use of possibly uninitialized variable: `a.x`
   --> $DIR/borrowck-uninit-field-access.rs:24:13
    |
-LL |     let _ = a.x + 1; //[ast]~ ERROR use of possibly uninitialized variable: `a.x`
+LL |     let _ = a.x + 1;
    |             ^^^ use of possibly uninitialized `a.x`
 
 error[E0382]: use of moved value: `line1.origin.x`
@@ -9,7 +9,7 @@
    |
 LL |     let _moved = line1.origin;
    |         ------ value moved here
-LL |     let _ = line1.origin.x + 1; //[ast]~ ERROR use of moved value: `line1.origin.x`
+LL |     let _ = line1.origin.x + 1;
    |             ^^^^^^^^^^^^^^ value used here after move
    |
    = note: move occurs because `line1.origin` has type `Point`, which does not implement the `Copy` trait
@@ -19,7 +19,7 @@
    |
 LL |     let _moved = (line2.origin, line2.middle);
    |                   ------------ value moved here
-LL |     line2.consume(); //[ast]~ ERROR use of partially moved value: `line2` [E0382]
+LL |     line2.consume();
    |     ^^^^^ value used here after move
    |
    = note: move occurs because `line2.origin` has type `Point`, which does not implement the `Copy` trait
diff --git a/src/test/ui/borrowck/borrowck-uninit-field-access.mir.stderr b/src/test/ui/borrowck/borrowck-uninit-field-access.mir.stderr
index 99cbf64..a6e5f0b 100644
--- a/src/test/ui/borrowck/borrowck-uninit-field-access.mir.stderr
+++ b/src/test/ui/borrowck/borrowck-uninit-field-access.mir.stderr
@@ -1,7 +1,7 @@
 error[E0381]: use of possibly uninitialized variable: `a`
   --> $DIR/borrowck-uninit-field-access.rs:24:13
    |
-LL |     let _ = a.x + 1; //[ast]~ ERROR use of possibly uninitialized variable: `a.x`
+LL |     let _ = a.x + 1;
    |             ^^^ use of possibly uninitialized `a.x`
 
 error[E0382]: use of moved value: `line1.origin`
@@ -9,7 +9,7 @@
    |
 LL |     let _moved = line1.origin;
    |                  ------------ value moved here
-LL |     let _ = line1.origin.x + 1; //[ast]~ ERROR use of moved value: `line1.origin.x`
+LL |     let _ = line1.origin.x + 1;
    |             ^^^^^^^^^^^^^^ value used here after move
    |
    = note: move occurs because `line1.origin` has type `Point`, which does not implement the `Copy` trait
@@ -19,7 +19,7 @@
    |
 LL |     let _moved = (line2.origin, line2.middle);
    |                                 ------------ value moved here
-LL |     line2.consume(); //[ast]~ ERROR use of partially moved value: `line2` [E0382]
+LL |     line2.consume();
    |     ^^^^^ value used here after partial move
    |
    = note: move occurs because `line2.middle` has type `Point`, which does not implement the `Copy` trait
diff --git a/src/test/ui/borrowck/borrowck-uninit-ref-chain.ast.nll.stderr b/src/test/ui/borrowck/borrowck-uninit-ref-chain.ast.nll.stderr
index 7687176..a5cf59c 100644
--- a/src/test/ui/borrowck/borrowck-uninit-ref-chain.ast.nll.stderr
+++ b/src/test/ui/borrowck/borrowck-uninit-ref-chain.ast.nll.stderr
@@ -1,43 +1,43 @@
 error[E0381]: borrow of possibly uninitialized variable: `x`
   --> $DIR/borrowck-uninit-ref-chain.rs:11:14
    |
-LL |     let _y = &**x; //[ast]~ ERROR use of possibly uninitialized variable: `**x` [E0381]
+LL |     let _y = &**x;
    |              ^^^^ use of possibly uninitialized `**x`
 
 error[E0381]: borrow of possibly uninitialized variable: `x`
   --> $DIR/borrowck-uninit-ref-chain.rs:15:14
    |
-LL |     let _y = &**x; //[ast]~ ERROR use of possibly uninitialized variable: `**x` [E0381]
+LL |     let _y = &**x;
    |              ^^^^ use of possibly uninitialized `**x`
 
 error[E0381]: borrow of possibly uninitialized variable: `x`
   --> $DIR/borrowck-uninit-ref-chain.rs:19:14
    |
-LL |     let _y = &**x; //[ast]~ ERROR use of possibly uninitialized variable: `**x` [E0381]
+LL |     let _y = &**x;
    |              ^^^^ use of possibly uninitialized `**x`
 
 error[E0381]: assign to part of possibly uninitialized variable: `a`
   --> $DIR/borrowck-uninit-ref-chain.rs:24:5
    |
-LL |     a.x = 0;       //[mir]~ ERROR assign to part of possibly uninitialized variable: `a` [E0381]
+LL |     a.x = 0;
    |     ^^^^^^^ use of possibly uninitialized `a`
 
 error[E0381]: assign to part of possibly uninitialized variable: `a`
   --> $DIR/borrowck-uninit-ref-chain.rs:29:5
    |
-LL |     a.x = &&0;       //[mir]~ ERROR assign to part of possibly uninitialized variable: `a` [E0381]
+LL |     a.x = &&0;
    |     ^^^^^^^^^ use of possibly uninitialized `a`
 
 error[E0381]: assign to part of possibly uninitialized variable: `a`
   --> $DIR/borrowck-uninit-ref-chain.rs:35:5
    |
-LL |     a.x = 0;       //[mir]~ ERROR assign to part of possibly uninitialized variable: `a` [E0381]
+LL |     a.x = 0;
    |     ^^^^^^^ use of possibly uninitialized `a`
 
 error[E0381]: assign to part of possibly uninitialized variable: `a`
   --> $DIR/borrowck-uninit-ref-chain.rs:40:5
    |
-LL |     a.x = &&0;       //[mir]~ assign to part of possibly uninitialized variable: `a` [E0381]
+LL |     a.x = &&0;
    |     ^^^^^^^^^ use of possibly uninitialized `a`
 
 error: aborting due to 7 previous errors
diff --git a/src/test/ui/borrowck/borrowck-uninit-ref-chain.ast.stderr b/src/test/ui/borrowck/borrowck-uninit-ref-chain.ast.stderr
index e8ebf8c..8cb3f3b 100644
--- a/src/test/ui/borrowck/borrowck-uninit-ref-chain.ast.stderr
+++ b/src/test/ui/borrowck/borrowck-uninit-ref-chain.ast.stderr
@@ -1,43 +1,43 @@
 error[E0381]: use of possibly uninitialized variable: `**x`
   --> $DIR/borrowck-uninit-ref-chain.rs:11:15
    |
-LL |     let _y = &**x; //[ast]~ ERROR use of possibly uninitialized variable: `**x` [E0381]
+LL |     let _y = &**x;
    |               ^^^ use of possibly uninitialized `**x`
 
 error[E0381]: use of possibly uninitialized variable: `**x`
   --> $DIR/borrowck-uninit-ref-chain.rs:15:15
    |
-LL |     let _y = &**x; //[ast]~ ERROR use of possibly uninitialized variable: `**x` [E0381]
+LL |     let _y = &**x;
    |               ^^^ use of possibly uninitialized `**x`
 
 error[E0381]: use of possibly uninitialized variable: `**x`
   --> $DIR/borrowck-uninit-ref-chain.rs:19:15
    |
-LL |     let _y = &**x; //[ast]~ ERROR use of possibly uninitialized variable: `**x` [E0381]
+LL |     let _y = &**x;
    |               ^^^ use of possibly uninitialized `**x`
 
 error[E0381]: use of possibly uninitialized variable: `a.x`
   --> $DIR/borrowck-uninit-ref-chain.rs:25:15
    |
-LL |     let _b = &a.x; //[ast]~ ERROR use of possibly uninitialized variable: `a.x` [E0381]
+LL |     let _b = &a.x;
    |               ^^^ use of possibly uninitialized `a.x`
 
 error[E0381]: use of possibly uninitialized variable: `**a.x`
   --> $DIR/borrowck-uninit-ref-chain.rs:30:15
    |
-LL |     let _b = &**a.x; //[ast]~ ERROR use of possibly uninitialized variable: `**a.x` [E0381]
+LL |     let _b = &**a.x;
    |               ^^^^^ use of possibly uninitialized `**a.x`
 
 error[E0381]: use of possibly uninitialized variable: `a.y`
   --> $DIR/borrowck-uninit-ref-chain.rs:36:15
    |
-LL |     let _b = &a.y; //[ast]~ ERROR use of possibly uninitialized variable: `a.y` [E0381]
+LL |     let _b = &a.y;
    |               ^^^ use of possibly uninitialized `a.y`
 
 error[E0381]: use of possibly uninitialized variable: `**a.y`
   --> $DIR/borrowck-uninit-ref-chain.rs:41:15
    |
-LL |     let _b = &**a.y; //[ast]~ ERROR use of possibly uninitialized variable: `**a.y` [E0381]
+LL |     let _b = &**a.y;
    |               ^^^^^ use of possibly uninitialized `**a.y`
 
 error: aborting due to 7 previous errors
diff --git a/src/test/ui/borrowck/borrowck-uninit-ref-chain.mir.stderr b/src/test/ui/borrowck/borrowck-uninit-ref-chain.mir.stderr
index 7687176..a5cf59c 100644
--- a/src/test/ui/borrowck/borrowck-uninit-ref-chain.mir.stderr
+++ b/src/test/ui/borrowck/borrowck-uninit-ref-chain.mir.stderr
@@ -1,43 +1,43 @@
 error[E0381]: borrow of possibly uninitialized variable: `x`
   --> $DIR/borrowck-uninit-ref-chain.rs:11:14
    |
-LL |     let _y = &**x; //[ast]~ ERROR use of possibly uninitialized variable: `**x` [E0381]
+LL |     let _y = &**x;
    |              ^^^^ use of possibly uninitialized `**x`
 
 error[E0381]: borrow of possibly uninitialized variable: `x`
   --> $DIR/borrowck-uninit-ref-chain.rs:15:14
    |
-LL |     let _y = &**x; //[ast]~ ERROR use of possibly uninitialized variable: `**x` [E0381]
+LL |     let _y = &**x;
    |              ^^^^ use of possibly uninitialized `**x`
 
 error[E0381]: borrow of possibly uninitialized variable: `x`
   --> $DIR/borrowck-uninit-ref-chain.rs:19:14
    |
-LL |     let _y = &**x; //[ast]~ ERROR use of possibly uninitialized variable: `**x` [E0381]
+LL |     let _y = &**x;
    |              ^^^^ use of possibly uninitialized `**x`
 
 error[E0381]: assign to part of possibly uninitialized variable: `a`
   --> $DIR/borrowck-uninit-ref-chain.rs:24:5
    |
-LL |     a.x = 0;       //[mir]~ ERROR assign to part of possibly uninitialized variable: `a` [E0381]
+LL |     a.x = 0;
    |     ^^^^^^^ use of possibly uninitialized `a`
 
 error[E0381]: assign to part of possibly uninitialized variable: `a`
   --> $DIR/borrowck-uninit-ref-chain.rs:29:5
    |
-LL |     a.x = &&0;       //[mir]~ ERROR assign to part of possibly uninitialized variable: `a` [E0381]
+LL |     a.x = &&0;
    |     ^^^^^^^^^ use of possibly uninitialized `a`
 
 error[E0381]: assign to part of possibly uninitialized variable: `a`
   --> $DIR/borrowck-uninit-ref-chain.rs:35:5
    |
-LL |     a.x = 0;       //[mir]~ ERROR assign to part of possibly uninitialized variable: `a` [E0381]
+LL |     a.x = 0;
    |     ^^^^^^^ use of possibly uninitialized `a`
 
 error[E0381]: assign to part of possibly uninitialized variable: `a`
   --> $DIR/borrowck-uninit-ref-chain.rs:40:5
    |
-LL |     a.x = &&0;       //[mir]~ assign to part of possibly uninitialized variable: `a` [E0381]
+LL |     a.x = &&0;
    |     ^^^^^^^^^ use of possibly uninitialized `a`
 
 error: aborting due to 7 previous errors
diff --git a/src/test/ui/borrowck/borrowck-union-borrow.mir.stderr b/src/test/ui/borrowck/borrowck-union-borrow.mir.stderr
deleted file mode 100644
index 1a2433c..0000000
--- a/src/test/ui/borrowck/borrowck-union-borrow.mir.stderr
+++ /dev/null
@@ -1,136 +0,0 @@
-error[E0502]: cannot borrow `u.a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-union-borrow.rs:27:23
-   |
-LL |             let ra = &u.a;
-   |                      ---- immutable borrow occurs here
-LL |             let rma = &mut u.a; //[ast]~ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable
-   |                       ^^^^^^^^ mutable borrow occurs here
-LL |                                 //[mir]~^ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable
-LL |             drop(ra);
-   |                  -- immutable borrow later used here
-
-error[E0506]: cannot assign to `u.a` because it is borrowed
-  --> $DIR/borrowck-union-borrow.rs:33:13
-   |
-LL |             let ra = &u.a;
-   |                      ---- borrow of `u.a` occurs here
-LL |             u.a = 1; //[ast]~ ERROR cannot assign to `u.a` because it is borrowed
-   |             ^^^^^^^ assignment to borrowed `u.a` occurs here
-LL |                      //[mir]~^ ERROR cannot assign to `u.a` because it is borrowed
-LL |             drop(ra);
-   |                  -- borrow later used here
-
-error[E0502]: cannot borrow `u.b` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-union-borrow.rs:50:23
-   |
-LL |             let ra = &u.a;
-   |                      ---- immutable borrow occurs here
-LL |             let rmb = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`)
-   |                       ^^^^^^^^ mutable borrow occurs here
-LL |                                 //[mir]~^ ERROR cannot borrow `u.b` as mutable because it is also borrowed as immutable
-LL |             drop(ra);
-   |                  -- immutable borrow later used here
-
-error[E0506]: cannot assign to `u.b` because it is borrowed
-  --> $DIR/borrowck-union-borrow.rs:56:13
-   |
-LL |             let ra = &u.a;
-   |                      ---- borrow of `u.b` occurs here
-LL |             u.b = 1; //[ast]~ ERROR cannot assign to `u.b` because it is borrowed
-   |             ^^^^^^^ assignment to borrowed `u.b` occurs here
-LL |                      //[mir]~^ ERROR cannot assign to `u.b` because it is borrowed
-LL |             drop(ra);
-   |                  -- borrow later used here
-
-error[E0502]: cannot borrow `u.a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-union-borrow.rs:63:22
-   |
-LL |             let rma = &mut u.a;
-   |                       -------- mutable borrow occurs here
-LL |             let ra = &u.a; //[ast]~ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable
-   |                      ^^^^ immutable borrow occurs here
-LL |                          //[mir]~^ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable
-LL |             drop(rma);
-   |                  --- mutable borrow later used here
-
-error[E0503]: cannot use `u.a` because it was mutably borrowed
-  --> $DIR/borrowck-union-borrow.rs:69:21
-   |
-LL |             let ra = &mut u.a;
-   |                      -------- borrow of `u.a` occurs here
-LL |             let a = u.a; //[ast]~ ERROR cannot use `u.a` because it was mutably borrowed
-   |                     ^^^ use of borrowed `u.a`
-LL |                          //[mir]~^ ERROR cannot use `u.a` because it was mutably borrowed
-LL |             drop(ra);
-   |                  -- borrow later used here
-
-error[E0499]: cannot borrow `u.a` as mutable more than once at a time
-  --> $DIR/borrowck-union-borrow.rs:75:24
-   |
-LL |             let rma = &mut u.a;
-   |                       -------- first mutable borrow occurs here
-LL |             let rma2 = &mut u.a; //[ast]~ ERROR cannot borrow `u.a` as mutable more than once at a time
-   |                        ^^^^^^^^ second mutable borrow occurs here
-LL |                                  //[mir]~^ ERROR cannot borrow `u.a` as mutable more than once at a time
-LL |             drop(rma);
-   |                  --- first borrow later used here
-
-error[E0506]: cannot assign to `u.a` because it is borrowed
-  --> $DIR/borrowck-union-borrow.rs:81:13
-   |
-LL |             let rma = &mut u.a;
-   |                       -------- borrow of `u.a` occurs here
-LL |             u.a = 1; //[ast]~ ERROR cannot assign to `u.a` because it is borrowed
-   |             ^^^^^^^ assignment to borrowed `u.a` occurs here
-LL |                      //[mir]~^ ERROR cannot assign to `u.a` because it is borrowed
-LL |             drop(rma);
-   |                  --- borrow later used here
-
-error[E0502]: cannot borrow `u.b` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-union-borrow.rs:88:22
-   |
-LL |             let rma = &mut u.a;
-   |                       -------- mutable borrow occurs here
-LL |             let rb = &u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`)
-   |                      ^^^^ immutable borrow occurs here
-LL |                            //[mir]~^ ERROR cannot borrow `u.b` as immutable because it is also borrowed as mutable
-LL |             drop(rma);
-   |                  --- mutable borrow later used here
-
-error[E0503]: cannot use `u.b` because it was mutably borrowed
-  --> $DIR/borrowck-union-borrow.rs:94:21
-   |
-LL |             let ra = &mut u.a;
-   |                      -------- borrow of `u.a` occurs here
-LL |             let b = u.b; //[ast]~ ERROR cannot use `u.b` because it was mutably borrowed
-   |                     ^^^ use of borrowed `u.a`
-...
-LL |             drop(ra);
-   |                  -- borrow later used here
-
-error[E0499]: cannot borrow `u.b` as mutable more than once at a time
-  --> $DIR/borrowck-union-borrow.rs:101:24
-   |
-LL |             let rma = &mut u.a;
-   |                       -------- first mutable borrow occurs here
-LL |             let rmb2 = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as mutable more than once at a time
-   |                        ^^^^^^^^ second mutable borrow occurs here
-LL |                                  //[mir]~^ ERROR cannot borrow `u.b` as mutable more than once at a time
-LL |             drop(rma);
-   |                  --- first borrow later used here
-
-error[E0506]: cannot assign to `u.b` because it is borrowed
-  --> $DIR/borrowck-union-borrow.rs:107:13
-   |
-LL |             let rma = &mut u.a;
-   |                       -------- borrow of `u.b` occurs here
-LL |             u.b = 1; //[ast]~ ERROR cannot assign to `u.b` because it is borrowed
-   |             ^^^^^^^ assignment to borrowed `u.b` occurs here
-LL |                      //[mir]~^ ERROR cannot assign to `u.b` because it is borrowed
-LL |             drop(rma);
-   |                  --- borrow later used here
-
-error: aborting due to 12 previous errors
-
-Some errors occurred: E0499, E0502, E0503, E0506.
-For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-use-in-index-lvalue.ast.nll.stderr b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.ast.nll.stderr
index 1819123..c5e4f89 100644
--- a/src/test/ui/borrowck/borrowck-use-in-index-lvalue.ast.nll.stderr
+++ b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.ast.nll.stderr
@@ -1,13 +1,13 @@
 error[E0381]: use of possibly uninitialized variable: `w`
   --> $DIR/borrowck-use-in-index-lvalue.rs:6:5
    |
-LL |     w[5] = 0; //[ast]~ ERROR use of possibly uninitialized variable: `*w` [E0381]
+LL |     w[5] = 0;
    |     ^^^^ use of possibly uninitialized `*w`
 
 error[E0381]: use of possibly uninitialized variable: `w`
   --> $DIR/borrowck-use-in-index-lvalue.rs:10:5
    |
-LL |     w[5] = 0; //[ast]~ ERROR use of possibly uninitialized variable: `*w` [E0381]
+LL |     w[5] = 0;
    |     ^^^^ use of possibly uninitialized `*w`
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/borrowck/borrowck-use-in-index-lvalue.ast.stderr b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.ast.stderr
index abe5157..e235bdf 100644
--- a/src/test/ui/borrowck/borrowck-use-in-index-lvalue.ast.stderr
+++ b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.ast.stderr
@@ -1,13 +1,13 @@
 error[E0381]: use of possibly uninitialized variable: `*w`
   --> $DIR/borrowck-use-in-index-lvalue.rs:6:5
    |
-LL |     w[5] = 0; //[ast]~ ERROR use of possibly uninitialized variable: `*w` [E0381]
+LL |     w[5] = 0;
    |     ^^^^^^^^ use of possibly uninitialized `*w`
 
 error[E0381]: use of possibly uninitialized variable: `*w`
   --> $DIR/borrowck-use-in-index-lvalue.rs:10:5
    |
-LL |     w[5] = 0; //[ast]~ ERROR use of possibly uninitialized variable: `*w` [E0381]
+LL |     w[5] = 0;
    |     ^^^^^^^^ use of possibly uninitialized `*w`
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/borrowck/borrowck-use-in-index-lvalue.mir.stderr b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.mir.stderr
index 1819123..c5e4f89 100644
--- a/src/test/ui/borrowck/borrowck-use-in-index-lvalue.mir.stderr
+++ b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.mir.stderr
@@ -1,13 +1,13 @@
 error[E0381]: use of possibly uninitialized variable: `w`
   --> $DIR/borrowck-use-in-index-lvalue.rs:6:5
    |
-LL |     w[5] = 0; //[ast]~ ERROR use of possibly uninitialized variable: `*w` [E0381]
+LL |     w[5] = 0;
    |     ^^^^ use of possibly uninitialized `*w`
 
 error[E0381]: use of possibly uninitialized variable: `w`
   --> $DIR/borrowck-use-in-index-lvalue.rs:10:5
    |
-LL |     w[5] = 0; //[ast]~ ERROR use of possibly uninitialized variable: `*w` [E0381]
+LL |     w[5] = 0;
    |     ^^^^ use of possibly uninitialized `*w`
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.ast.nll.stderr b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.ast.nll.stderr
index 8f4b02a..a208dc4 100644
--- a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.ast.nll.stderr
+++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.ast.nll.stderr
@@ -1,7 +1,7 @@
 error[E0381]: borrow of possibly uninitialized variable: `x`
   --> $DIR/borrowck-use-uninitialized-in-cast-trait.rs:12:13
    |
-LL |     let y = x as *const Foo; //[ast]~ ERROR use of possibly uninitialized variable: `*x`
+LL |     let y = x as *const Foo;
    |             ^ use of possibly uninitialized `*x`
 
 error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.ast.stderr b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.ast.stderr
index ecb8922..49a4300 100644
--- a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.ast.stderr
+++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.ast.stderr
@@ -1,7 +1,7 @@
 error[E0381]: use of possibly uninitialized variable: `*x`
   --> $DIR/borrowck-use-uninitialized-in-cast-trait.rs:12:13
    |
-LL |     let y = x as *const Foo; //[ast]~ ERROR use of possibly uninitialized variable: `*x`
+LL |     let y = x as *const Foo;
    |             ^ use of possibly uninitialized `*x`
 
 error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.mir.stderr b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.mir.stderr
index 8f4b02a..a208dc4 100644
--- a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.mir.stderr
+++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.mir.stderr
@@ -1,7 +1,7 @@
 error[E0381]: borrow of possibly uninitialized variable: `x`
   --> $DIR/borrowck-use-uninitialized-in-cast-trait.rs:12:13
    |
-LL |     let y = x as *const Foo; //[ast]~ ERROR use of possibly uninitialized variable: `*x`
+LL |     let y = x as *const Foo;
    |             ^ use of possibly uninitialized `*x`
 
 error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.ast.nll.stderr b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.ast.nll.stderr
index dd0a750..0f62c3a 100644
--- a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.ast.nll.stderr
+++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.ast.nll.stderr
@@ -1,7 +1,7 @@
 error[E0381]: borrow of possibly uninitialized variable: `x`
   --> $DIR/borrowck-use-uninitialized-in-cast.rs:10:13
    |
-LL |     let y = x as *const i32; //[ast]~ ERROR use of possibly uninitialized variable: `*x` [E0381]
+LL |     let y = x as *const i32;
    |             ^ use of possibly uninitialized `*x`
 
 error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.ast.stderr b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.ast.stderr
index d3ddf24..d813738 100644
--- a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.ast.stderr
+++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.ast.stderr
@@ -1,7 +1,7 @@
 error[E0381]: use of possibly uninitialized variable: `*x`
   --> $DIR/borrowck-use-uninitialized-in-cast.rs:10:13
    |
-LL |     let y = x as *const i32; //[ast]~ ERROR use of possibly uninitialized variable: `*x` [E0381]
+LL |     let y = x as *const i32;
    |             ^ use of possibly uninitialized `*x`
 
 error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.mir.stderr b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.mir.stderr
index dd0a750..0f62c3a 100644
--- a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.mir.stderr
+++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.mir.stderr
@@ -1,7 +1,7 @@
 error[E0381]: borrow of possibly uninitialized variable: `x`
   --> $DIR/borrowck-use-uninitialized-in-cast.rs:10:13
    |
-LL |     let y = x as *const i32; //[ast]~ ERROR use of possibly uninitialized variable: `*x` [E0381]
+LL |     let y = x as *const i32;
    |             ^ use of possibly uninitialized `*x`
 
 error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.ast.nll.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.ast.nll.stderr
index 6dc2778..7d0d888 100644
--- a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.ast.nll.stderr
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.ast.nll.stderr
@@ -4,7 +4,7 @@
 LL |         [1, 2, ref tail..] => tail,
    |                -------- borrow of `a[_]` occurs here
 ...
-LL |     a[2] = 0; //[ast]~ ERROR cannot assign to `a[..]` because it is borrowed
+LL |     a[2] = 0;
    |     ^^^^^^^^ assignment to borrowed `a[_]` occurs here
 ...
 LL |     println!("t[0]: {}", t[0]);
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.ast.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.ast.stderr
index c456dac..1207d4a 100644
--- a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.ast.stderr
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.ast.stderr
@@ -4,7 +4,7 @@
 LL |         [1, 2, ref tail..] => tail,
    |                -------- borrow of `a[..]` occurs here
 ...
-LL |     a[2] = 0; //[ast]~ ERROR cannot assign to `a[..]` because it is borrowed
+LL |     a[2] = 0;
    |     ^^^^^^^^ assignment to borrowed `a[..]` occurs here
 
 error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.cmp.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.cmp.stderr
index 6eb9eac..f764d5f 100644
--- a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.cmp.stderr
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.cmp.stderr
@@ -4,7 +4,7 @@
 LL |         [1, 2, ref tail..] => tail,
    |                -------- borrow of `a[..]` occurs here
 ...
-LL |     a[2] = 0; //[ast]~ ERROR cannot assign to `a[..]` because it is borrowed
+LL |     a[2] = 0;
    |     ^^^^^^^^ assignment to borrowed `a[..]` occurs here
 
 error[E0506]: cannot assign to `a[_]` because it is borrowed (Mir)
@@ -13,7 +13,7 @@
 LL |         [1, 2, ref tail..] => tail,
    |                -------- borrow of `a[_]` occurs here
 ...
-LL |     a[2] = 0; //[ast]~ ERROR cannot assign to `a[..]` because it is borrowed
+LL |     a[2] = 0;
    |     ^^^^^^^^ assignment to borrowed `a[_]` occurs here
 ...
 LL |     println!("t[0]: {}", t[0]);
diff --git a/src/test/ui/borrowck/move-in-static-initializer-issue-38520.ast.stderr b/src/test/ui/borrowck/move-in-static-initializer-issue-38520.ast.stderr
index 6793e1a..14078b7 100644
--- a/src/test/ui/borrowck/move-in-static-initializer-issue-38520.ast.stderr
+++ b/src/test/ui/borrowck/move-in-static-initializer-issue-38520.ast.stderr
@@ -1,13 +1,13 @@
 error[E0507]: cannot move out of borrowed content
   --> $DIR/move-in-static-initializer-issue-38520.rs:15:23
    |
-LL | static Y: usize = get(*&X); //[ast]~ ERROR E0507
+LL | static Y: usize = get(*&X);
    |                       ^^^ cannot move out of borrowed content
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/move-in-static-initializer-issue-38520.rs:17:22
    |
-LL | const Z: usize = get(*&X); //[ast]~ ERROR E0507
+LL | const Z: usize = get(*&X);
    |                      ^^^ cannot move out of borrowed content
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/borrowck/move-in-static-initializer-issue-38520.mir.stderr b/src/test/ui/borrowck/move-in-static-initializer-issue-38520.mir.stderr
index 6793e1a..14078b7 100644
--- a/src/test/ui/borrowck/move-in-static-initializer-issue-38520.mir.stderr
+++ b/src/test/ui/borrowck/move-in-static-initializer-issue-38520.mir.stderr
@@ -1,13 +1,13 @@
 error[E0507]: cannot move out of borrowed content
   --> $DIR/move-in-static-initializer-issue-38520.rs:15:23
    |
-LL | static Y: usize = get(*&X); //[ast]~ ERROR E0507
+LL | static Y: usize = get(*&X);
    |                       ^^^ cannot move out of borrowed content
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/move-in-static-initializer-issue-38520.rs:17:22
    |
-LL | const Z: usize = get(*&X); //[ast]~ ERROR E0507
+LL | const Z: usize = get(*&X);
    |                      ^^^ cannot move out of borrowed content
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/borrowck/two-phase-activation-sharing-interference.nll_target.stderr b/src/test/ui/borrowck/two-phase-activation-sharing-interference.nll_target.stderr
index 7bae1438..8370aad 100644
--- a/src/test/ui/borrowck/two-phase-activation-sharing-interference.nll_target.stderr
+++ b/src/test/ui/borrowck/two-phase-activation-sharing-interference.nll_target.stderr
@@ -5,7 +5,7 @@
    |             ------ mutable borrow occurs here
 LL |     { let z = &x; read(z); }
    |               ^^ immutable borrow occurs here
-LL |     //[nll_target]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
+LL |
 LL |     *y += 1;
    |     ------- mutable borrow later used here
 
@@ -16,7 +16,7 @@
    |             ------ mutable borrow occurs here
 LL |     let z = &x;
    |             ^^ immutable borrow occurs here
-LL |     //[nll_target]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
+LL |
 LL |     *y += 1;
    |     ------- mutable borrow later used here
 
@@ -38,7 +38,7 @@
    |             ------ mutable borrow occurs here
 LL |     let _z = &x;
    |              ^^ immutable borrow occurs here
-LL |     //[nll_target]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
+LL |
 LL |     *y += 1;
    |     ------- mutable borrow later used here
 
diff --git a/src/test/ui/borrowck/two-phase-allow-access-during-reservation.nll_target.stderr b/src/test/ui/borrowck/two-phase-allow-access-during-reservation.nll_target.stderr
index 232876e..9f31c3f 100644
--- a/src/test/ui/borrowck/two-phase-allow-access-during-reservation.nll_target.stderr
+++ b/src/test/ui/borrowck/two-phase-allow-access-during-reservation.nll_target.stderr
@@ -16,7 +16,7 @@
 LL |     /*1*/ let p = &mut i; // (reservation of `i` starts here)
    |                   ------ borrow of `i` occurs here
 ...
-LL |     /*4*/ let k = i;      //[nll_beyond]~  ERROR cannot use `i` because it was mutably borrowed [E0503]
+LL |     /*4*/ let k = i;
    |                   ^ use of borrowed `i`
 ...
 LL |     /*5*/ *p += 1;
diff --git a/src/test/ui/confuse-field-and-method/issue-2392.stderr b/src/test/ui/confuse-field-and-method/issue-2392.stderr
index 7cd1941d..456a4c1 100644
--- a/src/test/ui/confuse-field-and-method/issue-2392.stderr
+++ b/src/test/ui/confuse-field-and-method/issue-2392.stderr
@@ -75,7 +75,7 @@
    |
    = help: did you mean to write `w.wrap.not_closure` instead of `w.wrap.not_closure(...)`?
 
-error[E0599]: no method named `closure` found for type `Obj<std::boxed::Box<(dyn std::boxed::FnBox<(), Output=u32> + 'static)>>` in the current scope
+error[E0599]: no method named `closure` found for type `Obj<std::boxed::Box<(dyn std::boxed::FnBox<(), Output = u32> + 'static)>>` in the current scope
   --> $DIR/issue-2392.rs:62:24
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
diff --git a/src/test/ui/consts/const-size_of-cycle.stderr b/src/test/ui/consts/const-size_of-cycle.stderr
index 8f8eb38..3762f5e 100644
--- a/src/test/ui/consts/const-size_of-cycle.stderr
+++ b/src/test/ui/consts/const-size_of-cycle.stderr
@@ -1,22 +1,22 @@
-error[E0391]: cycle detected when const-evaluating + checking `Foo::bytes::{{constant}}`
+error[E0391]: cycle detected when const-evaluating + checking `Foo::bytes::{{constant}}#0`
   --> $DIR/const-size_of-cycle.rs:6:17
    |
 LL |     bytes: [u8; std::mem::size_of::<Foo>()]
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-note: ...which requires const-evaluating `Foo::bytes::{{constant}}`...
+note: ...which requires const-evaluating `Foo::bytes::{{constant}}#0`...
   --> $SRC_DIR/libcore/mem.rs:LL:COL
    |
 LL |     intrinsics::size_of::<T>()
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    = 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 requires const-evaluating + checking `Foo::bytes::{{constant}}`...
+note: ...which requires const-evaluating + checking `Foo::bytes::{{constant}}#0`...
   --> $DIR/const-size_of-cycle.rs:6:17
    |
 LL |     bytes: [u8; std::mem::size_of::<Foo>()]
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which again requires const-evaluating + checking `Foo::bytes::{{constant}}`, completing the cycle
+   = note: ...which again requires const-evaluating + checking `Foo::bytes::{{constant}}#0`, completing the cycle
 note: cycle used when processing `Foo`
   --> $DIR/const-size_of-cycle.rs:5:1
    |
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 1fe3d33..7ede44c 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,7 +4,7 @@
 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
+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();
diff --git a/src/test/ui/consts/union_constant.rs b/src/test/ui/consts/union_constant.rs
new file mode 100644
index 0000000..0740149
--- /dev/null
+++ b/src/test/ui/consts/union_constant.rs
@@ -0,0 +1,11 @@
+// compile-pass
+
+union Uninit {
+    _never_use: *const u8,
+    uninit: (),
+}
+
+const UNINIT: Uninit = Uninit { uninit: () };
+
+fn main() {}
+
diff --git a/src/test/ui/dep-graph/dep-graph-struct-signature.rs b/src/test/ui/dep-graph/dep-graph-struct-signature.rs
index 3d660aa..bd6d3a7 100644
--- a/src/test/ui/dep-graph/dep-graph-struct-signature.rs
+++ b/src/test/ui/dep-graph/dep-graph-struct-signature.rs
@@ -24,7 +24,7 @@
 mod signatures {
     use WillChange;
 
-    #[rustc_then_this_would_need(TypeOfItem)] //~ ERROR no path
+    #[rustc_then_this_would_need(type_of)] //~ ERROR no path
     #[rustc_then_this_would_need(AssociatedItems)] //~ ERROR no path
     #[rustc_then_this_would_need(TraitDefOfItem)] //~ ERROR no path
     trait Bar {
@@ -42,14 +42,14 @@
         WillChange { x: x, y: y }
     }
 
-    #[rustc_then_this_would_need(TypeOfItem)] //~ ERROR OK
+    #[rustc_then_this_would_need(type_of)] //~ ERROR OK
     impl WillChange {
         #[rustc_then_this_would_need(FnSignature)] //~ ERROR OK
         #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK
         fn new(x: u32, y: u32) -> WillChange { loop { } }
     }
 
-    #[rustc_then_this_would_need(TypeOfItem)] //~ ERROR OK
+    #[rustc_then_this_would_need(type_of)] //~ ERROR OK
     impl WillChange {
         #[rustc_then_this_would_need(FnSignature)] //~ ERROR OK
         #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK
@@ -57,21 +57,21 @@
     }
 
     struct WillChanges {
-        #[rustc_then_this_would_need(TypeOfItem)] //~ ERROR OK
+        #[rustc_then_this_would_need(type_of)] //~ ERROR OK
         x: WillChange,
-        #[rustc_then_this_would_need(TypeOfItem)] //~ ERROR OK
+        #[rustc_then_this_would_need(type_of)] //~ ERROR OK
         y: WillChange
     }
 
     // The fields change, not the type itself.
-    #[rustc_then_this_would_need(TypeOfItem)] //~ ERROR no path
+    #[rustc_then_this_would_need(type_of)] //~ ERROR no path
     fn indirect(x: WillChanges) { }
 }
 
 mod invalid_signatures {
     use WontChange;
 
-    #[rustc_then_this_would_need(TypeOfItem)] //~ ERROR no path
+    #[rustc_then_this_would_need(type_of)] //~ ERROR no path
     trait A {
         #[rustc_then_this_would_need(FnSignature)] //~ ERROR no path
         fn do_something_else_twice(x: WontChange);
diff --git a/src/test/ui/dep-graph/dep-graph-struct-signature.stderr b/src/test/ui/dep-graph/dep-graph-struct-signature.stderr
index 8736d15..7aa4251 100644
--- a/src/test/ui/dep-graph/dep-graph-struct-signature.stderr
+++ b/src/test/ui/dep-graph/dep-graph-struct-signature.stderr
@@ -1,8 +1,8 @@
-error: no path from `WillChange` to `TypeOfItem`
+error: no path from `WillChange` to `type_of`
   --> $DIR/dep-graph-struct-signature.rs:27:5
    |
-LL |     #[rustc_then_this_would_need(TypeOfItem)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[rustc_then_this_would_need(type_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: no path from `WillChange` to `AssociatedItems`
   --> $DIR/dep-graph-struct-signature.rs:28:5
@@ -43,38 +43,38 @@
 error: OK
   --> $DIR/dep-graph-struct-signature.rs:45:5
    |
-LL |     #[rustc_then_this_would_need(TypeOfItem)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[rustc_then_this_would_need(type_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: OK
   --> $DIR/dep-graph-struct-signature.rs:52:5
    |
-LL |     #[rustc_then_this_would_need(TypeOfItem)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[rustc_then_this_would_need(type_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: OK
   --> $DIR/dep-graph-struct-signature.rs:60:9
    |
-LL |         #[rustc_then_this_would_need(TypeOfItem)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         #[rustc_then_this_would_need(type_of)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: OK
   --> $DIR/dep-graph-struct-signature.rs:62:9
    |
-LL |         #[rustc_then_this_would_need(TypeOfItem)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         #[rustc_then_this_would_need(type_of)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: no path from `WillChange` to `TypeOfItem`
+error: no path from `WillChange` to `type_of`
   --> $DIR/dep-graph-struct-signature.rs:67:5
    |
-LL |     #[rustc_then_this_would_need(TypeOfItem)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[rustc_then_this_would_need(type_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: no path from `WillChange` to `TypeOfItem`
+error: no path from `WillChange` to `type_of`
   --> $DIR/dep-graph-struct-signature.rs:74:5
    |
-LL |     #[rustc_then_this_would_need(TypeOfItem)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[rustc_then_this_would_need(type_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: no path from `WillChange` to `FnSignature`
   --> $DIR/dep-graph-struct-signature.rs:80:5
diff --git a/src/test/ui/dep-graph/dep-graph-type-alias.rs b/src/test/ui/dep-graph/dep-graph-type-alias.rs
index 0f703ae..5621284 100644
--- a/src/test/ui/dep-graph/dep-graph-type-alias.rs
+++ b/src/test/ui/dep-graph/dep-graph-type-alias.rs
@@ -14,23 +14,23 @@
 
 // The type alias directly affects the type of the field,
 // not the enclosing struct:
-#[rustc_then_this_would_need(TypeOfItem)] //~ ERROR no path
+#[rustc_then_this_would_need(type_of)] //~ ERROR no path
 struct Struct {
-    #[rustc_then_this_would_need(TypeOfItem)] //~ ERROR OK
+    #[rustc_then_this_would_need(type_of)] //~ ERROR OK
     x: TypeAlias,
     y: u32
 }
 
-#[rustc_then_this_would_need(TypeOfItem)] //~ ERROR no path
+#[rustc_then_this_would_need(type_of)] //~ ERROR no path
 enum Enum {
     Variant1 {
-        #[rustc_then_this_would_need(TypeOfItem)] //~ ERROR OK
+        #[rustc_then_this_would_need(type_of)] //~ ERROR OK
         t: TypeAlias
     },
     Variant2(i32)
 }
 
-#[rustc_then_this_would_need(TypeOfItem)] //~ ERROR no path
+#[rustc_then_this_would_need(type_of)] //~ ERROR no path
 trait Trait {
     #[rustc_then_this_would_need(FnSignature)] //~ ERROR OK
     fn method(&self, _: TypeAlias);
@@ -38,14 +38,14 @@
 
 struct SomeType;
 
-#[rustc_then_this_would_need(TypeOfItem)] //~ ERROR no path
+#[rustc_then_this_would_need(type_of)] //~ ERROR no path
 impl SomeType {
     #[rustc_then_this_would_need(FnSignature)] //~ ERROR OK
     #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK
     fn method(&self, _: TypeAlias) {}
 }
 
-#[rustc_then_this_would_need(TypeOfItem)] //~ ERROR OK
+#[rustc_then_this_would_need(type_of)] //~ ERROR OK
 type TypeAlias2 = TypeAlias;
 
 #[rustc_then_this_would_need(FnSignature)] //~ ERROR OK
diff --git a/src/test/ui/dep-graph/dep-graph-type-alias.stderr b/src/test/ui/dep-graph/dep-graph-type-alias.stderr
index f54e511..520c2a5 100644
--- a/src/test/ui/dep-graph/dep-graph-type-alias.stderr
+++ b/src/test/ui/dep-graph/dep-graph-type-alias.stderr
@@ -1,44 +1,44 @@
-error: no path from `TypeAlias` to `TypeOfItem`
+error: no path from `TypeAlias` to `type_of`
   --> $DIR/dep-graph-type-alias.rs:17:1
    |
-LL | #[rustc_then_this_would_need(TypeOfItem)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[rustc_then_this_would_need(type_of)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: OK
   --> $DIR/dep-graph-type-alias.rs:19:5
    |
-LL |     #[rustc_then_this_would_need(TypeOfItem)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[rustc_then_this_would_need(type_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: no path from `TypeAlias` to `TypeOfItem`
+error: no path from `TypeAlias` to `type_of`
   --> $DIR/dep-graph-type-alias.rs:24:1
    |
-LL | #[rustc_then_this_would_need(TypeOfItem)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[rustc_then_this_would_need(type_of)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: OK
   --> $DIR/dep-graph-type-alias.rs:27:9
    |
-LL |         #[rustc_then_this_would_need(TypeOfItem)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         #[rustc_then_this_would_need(type_of)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: no path from `TypeAlias` to `TypeOfItem`
+error: no path from `TypeAlias` to `type_of`
   --> $DIR/dep-graph-type-alias.rs:33:1
    |
-LL | #[rustc_then_this_would_need(TypeOfItem)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[rustc_then_this_would_need(type_of)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: no path from `TypeAlias` to `TypeOfItem`
+error: no path from `TypeAlias` to `type_of`
   --> $DIR/dep-graph-type-alias.rs:41:1
    |
-LL | #[rustc_then_this_would_need(TypeOfItem)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[rustc_then_this_would_need(type_of)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: OK
   --> $DIR/dep-graph-type-alias.rs:48:1
    |
-LL | #[rustc_then_this_would_need(TypeOfItem)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[rustc_then_this_would_need(type_of)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: OK
   --> $DIR/dep-graph-type-alias.rs:51:1
diff --git a/src/test/ui/deprecation/deprecation-lint.rs b/src/test/ui/deprecation/deprecation-lint.rs
index 033d6ee..2627139 100644
--- a/src/test/ui/deprecation/deprecation-lint.rs
+++ b/src/test/ui/deprecation/deprecation-lint.rs
@@ -314,7 +314,7 @@
         let _ = || {
             #[deprecated]
             fn bar() { }
-            bar(); //~ ERROR use of deprecated item 'this_crate::test_fn_closure_body::{{closure}}::bar'
+            bar(); //~ ERROR use of deprecated item 'this_crate::test_fn_closure_body::{{closure}}#0::bar'
         };
     }
 
diff --git a/src/test/ui/deprecation/deprecation-lint.stderr b/src/test/ui/deprecation/deprecation-lint.stderr
index 50cbe38..ffbcb25 100644
--- a/src/test/ui/deprecation/deprecation-lint.stderr
+++ b/src/test/ui/deprecation/deprecation-lint.stderr
@@ -298,7 +298,7 @@
 LL |         <Foo as Trait>::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::test_fn_closure_body::{{closure}}::bar'
+error: use of deprecated item 'this_crate::test_fn_closure_body::{{closure}}#0::bar'
   --> $DIR/deprecation-lint.rs:317:13
    |
 LL |             bar();
diff --git a/src/test/ui/deprecation/derive_on_deprecated.rs b/src/test/ui/deprecation/derive_on_deprecated.rs
new file mode 100644
index 0000000..4980a7f
--- /dev/null
+++ b/src/test/ui/deprecation/derive_on_deprecated.rs
@@ -0,0 +1,9 @@
+// compile-pass
+
+#![deny(deprecated)]
+
+#[deprecated = "oh no"]
+#[derive(Default)]
+struct X;
+
+fn main() {}
diff --git a/src/test/ui/deprecation/derive_on_deprecated_forbidden.rs b/src/test/ui/deprecation/derive_on_deprecated_forbidden.rs
new file mode 100644
index 0000000..235146b
--- /dev/null
+++ b/src/test/ui/deprecation/derive_on_deprecated_forbidden.rs
@@ -0,0 +1,9 @@
+// compile-pass
+
+#![forbid(deprecated)]
+
+#[deprecated = "oh no"]
+#[derive(Default)]
+struct X;
+
+fn main() {}
diff --git a/src/test/ui/feature-gate/allow-features-empty.rs b/src/test/ui/feature-gate/allow-features-empty.rs
new file mode 100644
index 0000000..8325005
--- /dev/null
+++ b/src/test/ui/feature-gate/allow-features-empty.rs
@@ -0,0 +1,10 @@
+// compile-flags: -Z allow_features=
+// Note: This test uses rustc internal flags because they will never stabilize.
+
+#![feature(rustc_diagnostic_macros)] //~ ERROR
+
+#![feature(rustc_const_unstable)] //~ ERROR
+
+#![feature(lang_items)] //~ ERROR
+
+fn main() {}
diff --git a/src/test/ui/feature-gate/allow-features-empty.stderr b/src/test/ui/feature-gate/allow-features-empty.stderr
new file mode 100644
index 0000000..cce2c40
--- /dev/null
+++ b/src/test/ui/feature-gate/allow-features-empty.stderr
@@ -0,0 +1,21 @@
+error[E0725]: the feature `rustc_diagnostic_macros` is not in the list of allowed features
+  --> $DIR/allow-features-empty.rs:4:12
+   |
+LL | #![feature(rustc_diagnostic_macros)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0725]: the feature `rustc_const_unstable` is not in the list of allowed features
+  --> $DIR/allow-features-empty.rs:6:12
+   |
+LL | #![feature(rustc_const_unstable)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+
+error[E0725]: the feature `lang_items` is not in the list of allowed features
+  --> $DIR/allow-features-empty.rs:8:12
+   |
+LL | #![feature(lang_items)]
+   |            ^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0725`.
diff --git a/src/test/ui/feature-gate/allow-features.rs b/src/test/ui/feature-gate/allow-features.rs
new file mode 100644
index 0000000..1cebc8f
--- /dev/null
+++ b/src/test/ui/feature-gate/allow-features.rs
@@ -0,0 +1,10 @@
+// compile-flags: -Z allow_features=rustc_diagnostic_macros,lang_items
+// Note: This test uses rustc internal flags because they will never stabilize.
+
+#![feature(rustc_diagnostic_macros)]
+
+#![feature(rustc_const_unstable)] //~ ERROR
+
+#![feature(lang_items)]
+
+fn main() {}
diff --git a/src/test/ui/feature-gate/allow-features.stderr b/src/test/ui/feature-gate/allow-features.stderr
new file mode 100644
index 0000000..b13560f
--- /dev/null
+++ b/src/test/ui/feature-gate/allow-features.stderr
@@ -0,0 +1,9 @@
+error[E0725]: the feature `rustc_const_unstable` is not in the list of allowed features
+  --> $DIR/allow-features.rs:6:12
+   |
+LL | #![feature(rustc_const_unstable)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0725`.
diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr
index 5fcb63e..9ec36f4 100644
--- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr
+++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr
@@ -2,11 +2,11 @@
   --> $DIR/hr-subtype.rs:100:1
    |
 LL | / fn main() {
-LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful
-LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful
-LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful
-LL | | //[bound_co_a_vs_bound_co_b]~^^^^ ERROR compilation successful
-LL | | //[free_x_vs_free_x]~^^^^^ ERROR compilation successful
+LL | |
+LL | |
+LL | |
+LL | |
+LL | |
 LL | | }
    | |_^
 
diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr
index 5fcb63e..9ec36f4 100644
--- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr
+++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr
@@ -2,11 +2,11 @@
   --> $DIR/hr-subtype.rs:100:1
    |
 LL | / fn main() {
-LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful
-LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful
-LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful
-LL | | //[bound_co_a_vs_bound_co_b]~^^^^ ERROR compilation successful
-LL | | //[free_x_vs_free_x]~^^^^^ ERROR compilation successful
+LL | |
+LL | |
+LL | |
+LL | |
+LL | |
 LL | | }
    | |_^
 
diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr
index 5fcb63e..9ec36f4 100644
--- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr
+++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr
@@ -2,11 +2,11 @@
   --> $DIR/hr-subtype.rs:100:1
    |
 LL | / fn main() {
-LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful
-LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful
-LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful
-LL | | //[bound_co_a_vs_bound_co_b]~^^^^ ERROR compilation successful
-LL | | //[free_x_vs_free_x]~^^^^^ ERROR compilation successful
+LL | |
+LL | |
+LL | |
+LL | |
+LL | |
 LL | | }
    | |_^
 
diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr
index 5fcb63e..9ec36f4 100644
--- a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr
+++ b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr
@@ -2,11 +2,11 @@
   --> $DIR/hr-subtype.rs:100:1
    |
 LL | / fn main() {
-LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful
-LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful
-LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful
-LL | | //[bound_co_a_vs_bound_co_b]~^^^^ ERROR compilation successful
-LL | | //[free_x_vs_free_x]~^^^^^ ERROR compilation successful
+LL | |
+LL | |
+LL | |
+LL | |
+LL | |
 LL | | }
    | |_^
 
diff --git a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr
index 5fcb63e..9ec36f4 100644
--- a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr
+++ b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr
@@ -2,11 +2,11 @@
   --> $DIR/hr-subtype.rs:100:1
    |
 LL | / fn main() {
-LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful
-LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful
-LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful
-LL | | //[bound_co_a_vs_bound_co_b]~^^^^ ERROR compilation successful
-LL | | //[free_x_vs_free_x]~^^^^^ ERROR compilation successful
+LL | |
+LL | |
+LL | |
+LL | |
+LL | |
 LL | | }
    | |_^
 
diff --git a/src/test/ui/hrtb/hrtb-identity-fn-borrows.ast.nll.stderr b/src/test/ui/hrtb/hrtb-identity-fn-borrows.ast.nll.stderr
index bbb95e8..2b69b3f 100644
--- a/src/test/ui/hrtb/hrtb-identity-fn-borrows.ast.nll.stderr
+++ b/src/test/ui/hrtb/hrtb-identity-fn-borrows.ast.nll.stderr
@@ -3,7 +3,7 @@
    |
 LL |     let y = f.call(&x);
    |                    -- borrow of `x` occurs here
-LL |     x = 5; //[ast]~ ERROR cannot assign
+LL |     x = 5;
    |     ^^^^^ assignment to borrowed `x` occurs here
 ...
 LL |     drop(y);
diff --git a/src/test/ui/hrtb/hrtb-identity-fn-borrows.ast.stderr b/src/test/ui/hrtb/hrtb-identity-fn-borrows.ast.stderr
index f6f9200..6f055aa 100644
--- a/src/test/ui/hrtb/hrtb-identity-fn-borrows.ast.stderr
+++ b/src/test/ui/hrtb/hrtb-identity-fn-borrows.ast.stderr
@@ -3,7 +3,7 @@
    |
 LL |     let y = f.call(&x);
    |                     - borrow of `x` occurs here
-LL |     x = 5; //[ast]~ ERROR cannot assign
+LL |     x = 5;
    |     ^^^^^ assignment to borrowed `x` occurs here
 
 error: aborting due to previous error
diff --git a/src/test/ui/hrtb/hrtb-identity-fn-borrows.mir.stderr b/src/test/ui/hrtb/hrtb-identity-fn-borrows.mir.stderr
index bbb95e8..2b69b3f 100644
--- a/src/test/ui/hrtb/hrtb-identity-fn-borrows.mir.stderr
+++ b/src/test/ui/hrtb/hrtb-identity-fn-borrows.mir.stderr
@@ -3,7 +3,7 @@
    |
 LL |     let y = f.call(&x);
    |                    -- borrow of `x` occurs here
-LL |     x = 5; //[ast]~ ERROR cannot assign
+LL |     x = 5;
    |     ^^^^^ assignment to borrowed `x` occurs here
 ...
 LL |     drop(y);
diff --git a/src/test/ui/if/if-without-else-as-fn-expr.rs b/src/test/ui/if/if-without-else-as-fn-expr.rs
new file mode 100644
index 0000000..67e4445
--- /dev/null
+++ b/src/test/ui/if/if-without-else-as-fn-expr.rs
@@ -0,0 +1,25 @@
+fn foo(bar: usize) -> usize {
+    if bar % 5 == 0 {
+        return 3;
+    }
+    //~^^^ ERROR if may be missing an else clause
+}
+
+fn foo2(bar: usize) -> usize {
+    let x: usize = if bar % 5 == 0 {
+        return 3;
+    };
+    //~^^^ ERROR if may be missing an else clause
+    x
+}
+
+fn foo3(bar: usize) -> usize {
+    if bar % 5 == 0 {
+        3
+    }
+    //~^^^ ERROR if may be missing an else clause
+}
+
+fn main() {
+    let _ = foo(1);
+}
diff --git a/src/test/ui/if/if-without-else-as-fn-expr.stderr b/src/test/ui/if/if-without-else-as-fn-expr.stderr
new file mode 100644
index 0000000..0ba7272
--- /dev/null
+++ b/src/test/ui/if/if-without-else-as-fn-expr.stderr
@@ -0,0 +1,49 @@
+error[E0317]: if may be missing an else clause
+  --> $DIR/if-without-else-as-fn-expr.rs:2:5
+   |
+LL |   fn foo(bar: usize) -> usize {
+   |                         ----- expected `usize` because of this return type
+LL | /     if bar % 5 == 0 {
+LL | |         return 3;
+LL | |     }
+   | |_____^ expected usize, found ()
+   |
+   = note: expected type `usize`
+              found type `()`
+   = note: `if` expressions without `else` evaluate to `()`
+   = help: consider adding an `else` block that evaluates to the expected type
+
+error[E0317]: if may be missing an else clause
+  --> $DIR/if-without-else-as-fn-expr.rs:9:20
+   |
+LL |       let x: usize = if bar % 5 == 0 {
+   |  _________-__________^
+   | |         |
+   | |         expected because of this assignment
+LL | |         return 3;
+LL | |     };
+   | |_____^ expected usize, found ()
+   |
+   = note: expected type `usize`
+              found type `()`
+   = note: `if` expressions without `else` evaluate to `()`
+   = help: consider adding an `else` block that evaluates to the expected type
+
+error[E0317]: if may be missing an else clause
+  --> $DIR/if-without-else-as-fn-expr.rs:17:5
+   |
+LL |   fn foo3(bar: usize) -> usize {
+   |                          ----- expected `usize` because of this return type
+LL | /     if bar % 5 == 0 {
+LL | |         3
+LL | |     }
+   | |_____^ expected usize, found ()
+   |
+   = note: expected type `usize`
+              found type `()`
+   = note: `if` expressions without `else` evaluate to `()`
+   = help: consider adding an `else` block that evaluates to the expected type
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0317`.
diff --git a/src/test/ui/if/if-without-else-result.stderr b/src/test/ui/if/if-without-else-result.stderr
index 2134781..ddb013a 100644
--- a/src/test/ui/if/if-without-else-result.stderr
+++ b/src/test/ui/if/if-without-else-result.stderr
@@ -2,10 +2,15 @@
   --> $DIR/if-without-else-result.rs:2:13
    |
 LL |     let a = if true { true };
-   |             ^^^^^^^^^^^^^^^^ expected (), found bool
+   |             ^^^^^^^^^^----^^
+   |             |         |
+   |             |         found here
+   |             expected (), found bool
    |
    = note: expected type `()`
               found type `bool`
+   = note: `if` expressions without `else` evaluate to `()`
+   = help: consider adding an `else` block that evaluates to the expected type
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/immut-function-arguments.ast.nll.stderr b/src/test/ui/immut-function-arguments.ast.nll.stderr
index f016339..5085f36 100644
--- a/src/test/ui/immut-function-arguments.ast.nll.stderr
+++ b/src/test/ui/immut-function-arguments.ast.nll.stderr
@@ -3,13 +3,13 @@
    |
 LL | fn f(y: Box<isize>) {
    |      - help: consider changing this to be mutable: `mut y`
-LL |     *y = 5; //[ast]~ ERROR cannot assign
+LL |     *y = 5;
    |     ^^^^^^ cannot assign
 
 error[E0594]: cannot assign to `*q`, as `q` is not declared as mutable
   --> $DIR/immut-function-arguments.rs:10:35
    |
-LL |     let _frob = |q: Box<isize>| { *q = 2; }; //[ast]~ ERROR cannot assign
+LL |     let _frob = |q: Box<isize>| { *q = 2; };
    |                  -                ^^^^^^ cannot assign
    |                  |
    |                  help: consider changing this to be mutable: `mut q`
diff --git a/src/test/ui/immut-function-arguments.ast.stderr b/src/test/ui/immut-function-arguments.ast.stderr
index 1ffe569..f371a13 100644
--- a/src/test/ui/immut-function-arguments.ast.stderr
+++ b/src/test/ui/immut-function-arguments.ast.stderr
@@ -3,13 +3,13 @@
    |
 LL | fn f(y: Box<isize>) {
    |      - help: make this binding mutable: `mut y`
-LL |     *y = 5; //[ast]~ ERROR cannot assign
+LL |     *y = 5;
    |     ^^^^^^ cannot borrow as mutable
 
 error[E0594]: cannot assign to immutable `Box` content `*q`
   --> $DIR/immut-function-arguments.rs:10:35
    |
-LL |     let _frob = |q: Box<isize>| { *q = 2; }; //[ast]~ ERROR cannot assign
+LL |     let _frob = |q: Box<isize>| { *q = 2; };
    |                  -                ^^^^^^ cannot borrow as mutable
    |                  |
    |                  help: make this binding mutable: `mut q`
diff --git a/src/test/ui/immut-function-arguments.mir.stderr b/src/test/ui/immut-function-arguments.mir.stderr
index f016339..5085f36 100644
--- a/src/test/ui/immut-function-arguments.mir.stderr
+++ b/src/test/ui/immut-function-arguments.mir.stderr
@@ -3,13 +3,13 @@
    |
 LL | fn f(y: Box<isize>) {
    |      - help: consider changing this to be mutable: `mut y`
-LL |     *y = 5; //[ast]~ ERROR cannot assign
+LL |     *y = 5;
    |     ^^^^^^ cannot assign
 
 error[E0594]: cannot assign to `*q`, as `q` is not declared as mutable
   --> $DIR/immut-function-arguments.rs:10:35
    |
-LL |     let _frob = |q: Box<isize>| { *q = 2; }; //[ast]~ ERROR cannot assign
+LL |     let _frob = |q: Box<isize>| { *q = 2; };
    |                  -                ^^^^^^ cannot assign
    |                  |
    |                  help: consider changing this to be mutable: `mut q`
diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr
index b936fed..4e79dfc 100644
--- a/src/test/ui/impl-trait/auto-trait-leak.stderr
+++ b/src/test/ui/impl-trait/auto-trait-leak.stderr
@@ -1,4 +1,4 @@
-error[E0391]: cycle detected when processing `cycle1::{{impl-Trait}}`
+error[E0391]: cycle detected when processing `cycle1::{{opaque}}#0`
   --> $DIR/auto-trait-leak.rs:14:16
    |
 LL | fn cycle1() -> impl Clone {
@@ -10,7 +10,7 @@
 LL | fn cycle1() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
-note: ...which requires processing `cycle2::{{impl-Trait}}`...
+note: ...which requires processing `cycle2::{{opaque}}#0`...
   --> $DIR/auto-trait-leak.rs:23:16
    |
 LL | fn cycle2() -> impl Clone {
@@ -21,7 +21,7 @@
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
-   = note: ...which again requires processing `cycle1::{{impl-Trait}}`, completing the cycle
+   = note: ...which again requires processing `cycle1::{{opaque}}#0`, completing the cycle
 note: cycle used when checking item types in top-level module
   --> $DIR/auto-trait-leak.rs:3:1
    |
@@ -34,7 +34,7 @@
 LL | | }
    | |_^
 
-error[E0391]: cycle detected when processing `cycle1::{{impl-Trait}}`
+error[E0391]: cycle detected when processing `cycle1::{{opaque}}#0`
   --> $DIR/auto-trait-leak.rs:14:16
    |
 LL | fn cycle1() -> impl Clone {
@@ -46,7 +46,7 @@
 LL | fn cycle1() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
-note: ...which requires processing `cycle2::{{impl-Trait}}`...
+note: ...which requires processing `cycle2::{{opaque}}#0`...
   --> $DIR/auto-trait-leak.rs:23:16
    |
 LL | fn cycle2() -> impl Clone {
@@ -56,7 +56,7 @@
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which again requires processing `cycle1::{{impl-Trait}}`, completing the cycle
+   = note: ...which again requires processing `cycle1::{{opaque}}#0`, completing the cycle
 note: cycle used when checking item types in top-level module
   --> $DIR/auto-trait-leak.rs:3:1
    |
diff --git a/src/test/ui/issues/issue-10536.rs b/src/test/ui/issues/issue-10536.rs
index 95c8c2b..ceb44ec 100644
--- a/src/test/ui/issues/issue-10536.rs
+++ b/src/test/ui/issues/issue-10536.rs
@@ -12,7 +12,7 @@
     foo!();
 
     assert!({one! two()});
-    //~^ ERROR macros that expand to items must either be surrounded with braces or followed by a
+    //~^ ERROR macros that expand to items
     //~| ERROR cannot find macro `one!` in this scope
     //~| ERROR mismatched types
 
diff --git a/src/test/ui/issues/issue-10536.stderr b/src/test/ui/issues/issue-10536.stderr
index d5caf77..584cdf4 100644
--- a/src/test/ui/issues/issue-10536.stderr
+++ b/src/test/ui/issues/issue-10536.stderr
@@ -1,8 +1,16 @@
-error: macros that expand to items must either be surrounded with braces or followed by a semicolon
+error: macros that expand to items must be delimited with braces or followed by a semicolon
   --> $DIR/issue-10536.rs:14:22
    |
 LL |     assert!({one! two()});
    |                      ^^
+help: change the delimiters to curly braces
+   |
+LL |     assert!({one! two {}});
+   |                       ^^
+help: add a semicolon
+   |
+LL |     assert!({one! two();});
+   |                        ^
 
 error: expected `(` or `{`, found `}`
   --> $DIR/issue-10536.rs:21:22
diff --git a/src/test/ui/issues/issue-17252.stderr b/src/test/ui/issues/issue-17252.stderr
index c993588..da3e2e7 100644
--- a/src/test/ui/issues/issue-17252.stderr
+++ b/src/test/ui/issues/issue-17252.stderr
@@ -5,7 +5,7 @@
    |                    ^^^
    |
    = note: ...which again requires processing `FOO`, completing the cycle
-note: cycle used when processing `main::{{constant}}`
+note: cycle used when processing `main::{{constant}}#0`
   --> $DIR/issue-17252.rs:4:18
    |
 LL |     let _x: [u8; FOO]; // caused stack overflow prior to fix
diff --git a/src/test/ui/issues/issue-17263.nll.stderr b/src/test/ui/issues/issue-17263.nll.stderr
index cdb574b..5604037 100644
--- a/src/test/ui/issues/issue-17263.nll.stderr
+++ b/src/test/ui/issues/issue-17263.nll.stderr
@@ -1,10 +1,10 @@
 error: compilation successful
   --> $DIR/issue-17263.rs:15:1
    |
-LL | / fn main() { //[nll]~ ERROR compilation successful
+LL | / fn main() {
 LL | |     let mut x: Box<_> = box Foo { a: 1, b: 2 };
 LL | |     let (a, b) = (&mut x.a, &mut x.b);
-LL | |     //[ast]~^ ERROR cannot borrow `x` (via `x.b`) as mutable more than once at a time
+LL | |
 ...  |
 LL | |     use_mut(a);
 LL | | }
diff --git a/src/test/ui/issues/issue-17651.stderr b/src/test/ui/issues/issue-17651.stderr
index 72c40ff..ce9af15 100644
--- a/src/test/ui/issues/issue-17651.stderr
+++ b/src/test/ui/issues/issue-17651.stderr
@@ -6,7 +6,7 @@
    |
    = help: the trait `std::marker::Sized` is not implemented for `[{integer}]`
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
-   = note: required by `<std::boxed::Box<T>>::new`
+   = note: required by `std::boxed::Box::<T>::new`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-17905-2.stderr b/src/test/ui/issues/issue-17905-2.stderr
index f185f49..e3909e0 100644
--- a/src/test/ui/issues/issue-17905-2.stderr
+++ b/src/test/ui/issues/issue-17905-2.stderr
@@ -4,7 +4,7 @@
 LL |     fn say(self: &Pair<&str, isize>) {
    |                  ^^^^^^^^^^^^^^^^^^ lifetime mismatch
    |
-   = note: expected type `Pair<&'_ str, _>`
+   = note: expected type `Pair<&str, _>`
               found type `Pair<&str, _>`
 note: the anonymous lifetime #2 defined on the method body at 8:5...
   --> $DIR/issue-17905-2.rs:8:5
@@ -27,7 +27,7 @@
 LL |     fn say(self: &Pair<&str, isize>) {
    |                  ^^^^^^^^^^^^^^^^^^ lifetime mismatch
    |
-   = note: expected type `Pair<&'_ str, _>`
+   = note: expected type `Pair<&str, _>`
               found type `Pair<&str, _>`
 note: the lifetime '_ as defined on the impl at 5:5...
   --> $DIR/issue-17905-2.rs:5:5
diff --git a/src/test/ui/issues/issue-20605.stderr b/src/test/ui/issues/issue-20605.stderr
index f779fe5..89df58d 100644
--- a/src/test/ui/issues/issue-20605.stderr
+++ b/src/test/ui/issues/issue-20605.stderr
@@ -1,10 +1,10 @@
-error[E0277]: the size for values of type `dyn std::iter::Iterator<Item=&mut u8>` cannot be known at compilation time
+error[E0277]: the size for values of type `dyn std::iter::Iterator<Item = &mut u8>` cannot be known at compilation time
   --> $DIR/issue-20605.rs:2:17
    |
 LL |     for item in *things { *item = 0 }
    |                 ^^^^^^^ doesn't have a size known at compile-time
    |
-   = help: the trait `std::marker::Sized` is not implemented for `dyn std::iter::Iterator<Item=&mut u8>`
+   = help: the trait `std::marker::Sized` is not implemented for `dyn std::iter::Iterator<Item = &mut u8>`
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = note: required by `std::iter::IntoIterator::into_iter`
 
diff --git a/src/test/ui/issues/issue-20831-debruijn.stderr b/src/test/ui/issues/issue-20831-debruijn.stderr
index b2a0555..e20869a 100644
--- a/src/test/ui/issues/issue-20831-debruijn.stderr
+++ b/src/test/ui/issues/issue-20831-debruijn.stderr
@@ -11,7 +11,7 @@
    | |_____^ lifetime mismatch
    |
    = note: expected type `'a`
-              found type ``
+              found type `'_`
 note: the anonymous lifetime #2 defined on the method body at 28:5...
   --> $DIR/issue-20831-debruijn.rs:28:5
    |
@@ -42,7 +42,7 @@
    | |_____^ lifetime mismatch
    |
    = note: expected type `'a`
-              found type ``
+              found type `'_`
 note: the lifetime 'a as defined on the impl at 26:6...
   --> $DIR/issue-20831-debruijn.rs:26:6
    |
diff --git a/src/test/ui/issues/issue-22312.stderr b/src/test/ui/issues/issue-22312.stderr
index d8987a3..6a012b2 100644
--- a/src/test/ui/issues/issue-22312.stderr
+++ b/src/test/ui/issues/issue-22312.stderr
@@ -1,4 +1,4 @@
-error[E0605]: non-primitive cast: `Self` as `&dyn std::ops::Index<usize, Output=<Self as std::ops::Index<usize>>::Output>`
+error[E0605]: non-primitive cast: `Self` as `&dyn std::ops::Index<usize, Output = <Self as std::ops::Index<usize>>::Output>`
   --> $DIR/issue-22312.rs:11:24
    |
 LL |         let indexer = &(*self as &Index<usize, Output = <Self as Index<usize>>::Output>);
diff --git a/src/test/ui/issues/issue-22638.stderr b/src/test/ui/issues/issue-22638.stderr
index aff968f..b60e1c2 100644
--- a/src/test/ui/issues/issue-22638.stderr
+++ b/src/test/ui/issues/issue-22638.stderr
@@ -8,7 +8,7 @@
 LL | |     }
    | |_____^
    |
-   = note: consider adding a `#![type_length_limit="40000000"]` attribute to your crate
+   = note: consider adding a `#![type_length_limit="26214380"]` attribute to your crate
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-23302-1.stderr b/src/test/ui/issues/issue-23302-1.stderr
index 5fa82f8..43effc0 100644
--- a/src/test/ui/issues/issue-23302-1.stderr
+++ b/src/test/ui/issues/issue-23302-1.stderr
@@ -1,11 +1,11 @@
-error[E0391]: cycle detected when processing `X::A::{{constant}}`
+error[E0391]: cycle detected when processing `X::A::{{constant}}#0`
   --> $DIR/issue-23302-1.rs:4:9
    |
 LL |     A = X::A as isize,
    |         ^^^^^^^^^^^^^
    |
-   = note: ...which again requires processing `X::A::{{constant}}`, completing the cycle
-note: cycle used when const-evaluating `X::A::{{constant}}`
+   = note: ...which again requires processing `X::A::{{constant}}#0`, completing the cycle
+note: cycle used when const-evaluating `X::A::{{constant}}#0`
   --> $DIR/issue-23302-1.rs:4:9
    |
 LL |     A = X::A as isize,
diff --git a/src/test/ui/issues/issue-23302-2.stderr b/src/test/ui/issues/issue-23302-2.stderr
index 5b77bae..707d4fa 100644
--- a/src/test/ui/issues/issue-23302-2.stderr
+++ b/src/test/ui/issues/issue-23302-2.stderr
@@ -1,11 +1,11 @@
-error[E0391]: cycle detected when processing `Y::A::{{constant}}`
+error[E0391]: cycle detected when processing `Y::A::{{constant}}#0`
   --> $DIR/issue-23302-2.rs:4:9
    |
 LL |     A = Y::B as isize,
    |         ^^^^^^^^^^^^^
    |
-   = note: ...which again requires processing `Y::A::{{constant}}`, completing the cycle
-note: cycle used when const-evaluating `Y::A::{{constant}}`
+   = note: ...which again requires processing `Y::A::{{constant}}#0`, completing the cycle
+note: cycle used when const-evaluating `Y::A::{{constant}}#0`
   --> $DIR/issue-23302-2.rs:4:9
    |
 LL |     A = Y::B as isize,
diff --git a/src/test/ui/issues/issue-25579.ast.nll.stderr b/src/test/ui/issues/issue-25579.ast.nll.stderr
index b791f60..107f88b 100644
--- a/src/test/ui/issues/issue-25579.ast.nll.stderr
+++ b/src/test/ui/issues/issue-25579.ast.nll.stderr
@@ -1,7 +1,7 @@
 error: compilation successful
   --> $DIR/issue-25579.rs:21:1
    |
-LL | / fn main() { //[mir]~ ERROR compilation successful
+LL | / fn main() {
 LL | | }
    | |_^
 
diff --git a/src/test/ui/issues/issue-25579.ast.stderr b/src/test/ui/issues/issue-25579.ast.stderr
index 3de7f56..a44cc95 100644
--- a/src/test/ui/issues/issue-25579.ast.stderr
+++ b/src/test/ui/issues/issue-25579.ast.stderr
@@ -1,7 +1,7 @@
 error[E0499]: cannot borrow `l.0` as mutable more than once at a time
   --> $DIR/issue-25579.rs:14:32
    |
-LL |         &mut Sexpression::Cons(ref mut expr) => { //[ast]~ ERROR [E0499]
+LL |         &mut Sexpression::Cons(ref mut expr) => {
    |                                ^^^^^^^^^^^^ mutable borrow starts here in previous iteration of loop
 ...
 LL | }
@@ -10,9 +10,9 @@
 error[E0506]: cannot assign to `l` because it is borrowed
   --> $DIR/issue-25579.rs:15:13
    |
-LL |         &mut Sexpression::Cons(ref mut expr) => { //[ast]~ ERROR [E0499]
+LL |         &mut Sexpression::Cons(ref mut expr) => {
    |                                ------------ borrow of `l` occurs here
-LL |             l = &mut **expr; //[ast]~ ERROR [E0506]
+LL |             l = &mut **expr;
    |             ^^^^^^^^^^^^^^^ assignment to borrowed `l` occurs here
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/issues/issue-25579.mir.stderr b/src/test/ui/issues/issue-25579.mir.stderr
index b791f60..107f88b 100644
--- a/src/test/ui/issues/issue-25579.mir.stderr
+++ b/src/test/ui/issues/issue-25579.mir.stderr
@@ -1,7 +1,7 @@
 error: compilation successful
   --> $DIR/issue-25579.rs:21:1
    |
-LL | / fn main() { //[mir]~ ERROR compilation successful
+LL | / fn main() {
 LL | | }
    | |_^
 
diff --git a/src/test/ui/issues/issue-28433.rs b/src/test/ui/issues/issue-28433.rs
index a87ac63..2bbb32b 100644
--- a/src/test/ui/issues/issue-28433.rs
+++ b/src/test/ui/issues/issue-28433.rs
@@ -1,13 +1,14 @@
 // compile-flags: -Z continue-parse-after-error
 
-enum bird {
-    pub duck,
-    //~^ ERROR: expected identifier, found keyword `pub`
-    //~| ERROR: expected
-    goose
+enum Bird {
+    pub Duck,
+    //~^ ERROR unnecessary visibility qualifier
+    Goose,
+    pub(crate) Dove
+    //~^ ERROR unnecessary visibility qualifier
 }
 
 
 fn main() {
-    let y = bird::goose;
+    let y = Bird::Goose;
 }
diff --git a/src/test/ui/issues/issue-28433.stderr b/src/test/ui/issues/issue-28433.stderr
index d3cba3a..cfdbf6c 100644
--- a/src/test/ui/issues/issue-28433.stderr
+++ b/src/test/ui/issues/issue-28433.stderr
@@ -1,18 +1,14 @@
-error: expected identifier, found keyword `pub`
+error: unnecessary visibility qualifier
   --> $DIR/issue-28433.rs:4:5
    |
-LL |     pub duck,
-   |     ^^^ expected identifier, found keyword
-help: you can escape reserved keywords to use them as identifiers
-   |
-LL |     r#pub duck,
-   |     ^^^^^
+LL |     pub Duck,
+   |     ^^^ `pub` not permitted here
 
-error: expected one of `(`, `,`, `=`, `{`, or `}`, found `duck`
-  --> $DIR/issue-28433.rs:4:9
+error: unnecessary visibility qualifier
+  --> $DIR/issue-28433.rs:7:5
    |
-LL |     pub duck,
-   |         ^^^^ expected one of `(`, `,`, `=`, `{`, or `}` here
+LL |     pub(crate) Dove
+   |     ^^^^^^^^^^ `pub` not permitted here
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-36163.stderr b/src/test/ui/issues/issue-36163.stderr
index 94de4c7..4c3f726 100644
--- a/src/test/ui/issues/issue-36163.stderr
+++ b/src/test/ui/issues/issue-36163.stderr
@@ -1,4 +1,4 @@
-error[E0391]: cycle detected when processing `Foo::B::{{constant}}`
+error[E0391]: cycle detected when processing `Foo::B::{{constant}}#0`
   --> $DIR/issue-36163.rs:4:9
    |
 LL |     B = A,
@@ -9,8 +9,8 @@
    |
 LL | const A: isize = Foo::B as isize;
    |                  ^^^^^^^^^^^^^^^
-   = note: ...which again requires processing `Foo::B::{{constant}}`, completing the cycle
-note: cycle used when const-evaluating `Foo::B::{{constant}}`
+   = note: ...which again requires processing `Foo::B::{{constant}}#0`, completing the cycle
+note: cycle used when const-evaluating `Foo::B::{{constant}}#0`
   --> $DIR/issue-36163.rs:4:9
    |
 LL |     B = A,
diff --git a/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.stderr b/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.stderr
index 24b31f4..aead415 100644
--- a/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.stderr
+++ b/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.stderr
@@ -1,4 +1,4 @@
-error: reached the type-length limit while instantiating `<T as Foo><(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(), &()), &(&()...`
+error: reached the type-length limit while instantiating `<(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(...))))))))))))))) as Foo>::recurse`
   --> $DIR/issue-37311.rs:13:5
    |
 LL | /     fn recurse(&self) {
@@ -6,7 +6,7 @@
 LL | |     }
    | |_____^
    |
-   = note: consider adding a `#![type_length_limit="2097152"]` attribute to your crate
+   = note: consider adding a `#![type_length_limit="2097149"]` attribute to your crate
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-4201.stderr b/src/test/ui/issues/issue-4201.stderr
index d436c92..dd76fae 100644
--- a/src/test/ui/issues/issue-4201.stderr
+++ b/src/test/ui/issues/issue-4201.stderr
@@ -8,11 +8,14 @@
 LL | |
 LL | |
 LL | |         1
+   | |         - found here
 LL | |     };
    | |_____^ expected (), found integer
    |
    = note: expected type `()`
               found type `{integer}`
+   = note: `if` expressions without `else` evaluate to `()`
+   = help: consider adding an `else` block that evaluates to the expected type
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-44415.stderr b/src/test/ui/issues/issue-44415.stderr
index 3f377fd..df8e804 100644
--- a/src/test/ui/issues/issue-44415.stderr
+++ b/src/test/ui/issues/issue-44415.stderr
@@ -1,22 +1,22 @@
-error[E0391]: cycle detected when const-evaluating + checking `Foo::bytes::{{constant}}`
+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 `Foo::bytes::{{constant}}`...
+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 requires const-evaluating + checking `Foo::bytes::{{constant}}`...
+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 again requires const-evaluating + checking `Foo::bytes::{{constant}}`, completing the cycle
+   = 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
    |
diff --git a/src/test/ui/issues/issue-45199.ast.nll.stderr b/src/test/ui/issues/issue-45199.ast.nll.stderr
index 6d6af83..c6ae7c9 100644
--- a/src/test/ui/issues/issue-45199.ast.nll.stderr
+++ b/src/test/ui/issues/issue-45199.ast.nll.stderr
@@ -4,31 +4,31 @@
 LL |     let b: Box<isize>;
    |         - help: make this binding mutable: `mut b`
 ...
-LL |     b = Box::new(1);    //[ast]~ NOTE first assignment
+LL |     b = Box::new(1);
    |     - first assignment to `b`
-LL |                         //[mir]~^ NOTE first assignment
-LL |     b = Box::new(2);    //[ast]~ ERROR cannot assign twice to immutable variable
+LL |
+LL |     b = Box::new(2);
    |     ^ cannot assign twice to immutable variable
 
 error[E0384]: cannot assign twice to immutable variable `b`
   --> $DIR/issue-45199.rs:21:5
    |
-LL |     let b = Box::new(1);    //[ast]~ NOTE first assignment
+LL |     let b = Box::new(1);
    |         -
    |         |
    |         first assignment to `b`
    |         help: make this binding mutable: `mut b`
 ...
-LL |     b = Box::new(2);        //[ast]~ ERROR cannot assign twice to immutable variable
+LL |     b = Box::new(2);
    |     ^ cannot assign twice to immutable variable
 
 error[E0384]: cannot assign to immutable argument `b`
   --> $DIR/issue-45199.rs:30:5
    |
-LL | fn test_args(b: Box<i32>) {  //[ast]~ NOTE first assignment
+LL | fn test_args(b: Box<i32>) {
    |              - help: make this binding mutable: `mut b`
 ...
-LL |     b = Box::new(2);            //[ast]~ ERROR cannot assign twice to immutable variable
+LL |     b = Box::new(2);
    |     ^ cannot assign to immutable argument
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/issues/issue-45199.ast.stderr b/src/test/ui/issues/issue-45199.ast.stderr
index fa9d8e0..9dfd8e8 100644
--- a/src/test/ui/issues/issue-45199.ast.stderr
+++ b/src/test/ui/issues/issue-45199.ast.stderr
@@ -1,28 +1,28 @@
 error[E0384]: cannot assign twice to immutable variable `b`
   --> $DIR/issue-45199.rs:10:5
    |
-LL |     b = Box::new(1);    //[ast]~ NOTE first assignment
+LL |     b = Box::new(1);
    |     --------------- first assignment to `b`
-LL |                         //[mir]~^ NOTE first assignment
-LL |     b = Box::new(2);    //[ast]~ ERROR cannot assign twice to immutable variable
+LL |
+LL |     b = Box::new(2);
    |     ^^^^^^^^^^^^^^^ cannot assign twice to immutable variable
 
 error[E0384]: cannot assign twice to immutable variable `b`
   --> $DIR/issue-45199.rs:21:5
    |
-LL |     let b = Box::new(1);    //[ast]~ NOTE first assignment
+LL |     let b = Box::new(1);
    |         - first assignment to `b`
 ...
-LL |     b = Box::new(2);        //[ast]~ ERROR cannot assign twice to immutable variable
+LL |     b = Box::new(2);
    |     ^^^^^^^^^^^^^^^ cannot assign twice to immutable variable
 
 error[E0384]: cannot assign twice to immutable variable `b`
   --> $DIR/issue-45199.rs:30:5
    |
-LL | fn test_args(b: Box<i32>) {  //[ast]~ NOTE first assignment
+LL | fn test_args(b: Box<i32>) {
    |              - first assignment to `b`
 ...
-LL |     b = Box::new(2);            //[ast]~ ERROR cannot assign twice to immutable variable
+LL |     b = Box::new(2);
    |     ^^^^^^^^^^^^^^^ cannot assign twice to immutable variable
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/issues/issue-45199.mir.stderr b/src/test/ui/issues/issue-45199.mir.stderr
index 6d6af83..c6ae7c9 100644
--- a/src/test/ui/issues/issue-45199.mir.stderr
+++ b/src/test/ui/issues/issue-45199.mir.stderr
@@ -4,31 +4,31 @@
 LL |     let b: Box<isize>;
    |         - help: make this binding mutable: `mut b`
 ...
-LL |     b = Box::new(1);    //[ast]~ NOTE first assignment
+LL |     b = Box::new(1);
    |     - first assignment to `b`
-LL |                         //[mir]~^ NOTE first assignment
-LL |     b = Box::new(2);    //[ast]~ ERROR cannot assign twice to immutable variable
+LL |
+LL |     b = Box::new(2);
    |     ^ cannot assign twice to immutable variable
 
 error[E0384]: cannot assign twice to immutable variable `b`
   --> $DIR/issue-45199.rs:21:5
    |
-LL |     let b = Box::new(1);    //[ast]~ NOTE first assignment
+LL |     let b = Box::new(1);
    |         -
    |         |
    |         first assignment to `b`
    |         help: make this binding mutable: `mut b`
 ...
-LL |     b = Box::new(2);        //[ast]~ ERROR cannot assign twice to immutable variable
+LL |     b = Box::new(2);
    |     ^ cannot assign twice to immutable variable
 
 error[E0384]: cannot assign to immutable argument `b`
   --> $DIR/issue-45199.rs:30:5
    |
-LL | fn test_args(b: Box<i32>) {  //[ast]~ NOTE first assignment
+LL | fn test_args(b: Box<i32>) {
    |              - help: make this binding mutable: `mut b`
 ...
-LL |     b = Box::new(2);            //[ast]~ ERROR cannot assign twice to immutable variable
+LL |     b = Box::new(2);
    |     ^ cannot assign to immutable argument
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.ast.stderr b/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.ast.stderr
index 1992e32..0aaba52 100644
--- a/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.ast.stderr
+++ b/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.ast.stderr
@@ -1,8 +1,8 @@
 error: compilation successful
   --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:82:1
    |
-LL | / fn main() { //[ast]~ ERROR compilation successful
-LL | |      //[migrate]~^ ERROR compilation successful
+LL | / fn main() {
+LL | |
 LL | |     let mut x = 1;
 LL | |     {
 ...  |
diff --git a/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.migrate.stderr b/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.migrate.stderr
index 129c629..f8aab23 100644
--- a/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.migrate.stderr
+++ b/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.migrate.stderr
@@ -3,7 +3,7 @@
    |
 LL | fn scribbled<'a>(s: Scribble<'a>) -> &'a mut u32 {
    |              -- lifetime `'a` defined here
-LL |     &mut *s.0 //[nll]~ ERROR borrow may still be in use when destructor runs [E0713]
+LL |     &mut *s.0
    |     ^^^^^^^^^ returning this value requires that `*s.0` is borrowed for `'a`
 ...
 LL | }
@@ -17,7 +17,7 @@
    |
 LL | fn boxed_scribbled<'a>(s: Box<Scribble<'a>>) -> &'a mut u32 {
    |                    -- lifetime `'a` defined here
-LL |     &mut *(*s).0 //[nll]~ ERROR borrow may still be in use when destructor runs [E0713]
+LL |     &mut *(*s).0
    |     ^^^^^^^^^^^^ returning this value requires that `*s.0` is borrowed for `'a`
 ...
 LL | }
@@ -31,7 +31,7 @@
    |
 LL | fn boxed_boxed_scribbled<'a>(s: Box<Box<Scribble<'a>>>) -> &'a mut u32 {
    |                          -- lifetime `'a` defined here
-LL |     &mut *(**s).0 //[nll]~ ERROR borrow may still be in use when destructor runs [E0713]
+LL |     &mut *(**s).0
    |     ^^^^^^^^^^^^^ returning this value requires that `*s.0` is borrowed for `'a`
 ...
 LL | }
@@ -43,8 +43,8 @@
 error: compilation successful
   --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:82:1
    |
-LL | / fn main() { //[ast]~ ERROR compilation successful
-LL | |      //[migrate]~^ ERROR compilation successful
+LL | / fn main() {
+LL | |
 LL | |     let mut x = 1;
 LL | |     {
 ...  |
diff --git a/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.nll.stderr b/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.nll.stderr
index 2cb07f0..bfb5832 100644
--- a/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.nll.stderr
+++ b/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.nll.stderr
@@ -3,7 +3,7 @@
    |
 LL | fn scribbled<'a>(s: Scribble<'a>) -> &'a mut u32 {
    |              -- lifetime `'a` defined here
-LL |     &mut *s.0 //[nll]~ ERROR borrow may still be in use when destructor runs [E0713]
+LL |     &mut *s.0
    |     ^^^^^^^^^ returning this value requires that `*s.0` is borrowed for `'a`
 ...
 LL | }
@@ -14,7 +14,7 @@
    |
 LL | fn boxed_scribbled<'a>(s: Box<Scribble<'a>>) -> &'a mut u32 {
    |                    -- lifetime `'a` defined here
-LL |     &mut *(*s).0 //[nll]~ ERROR borrow may still be in use when destructor runs [E0713]
+LL |     &mut *(*s).0
    |     ^^^^^^^^^^^^ returning this value requires that `*s.0` is borrowed for `'a`
 ...
 LL | }
@@ -25,7 +25,7 @@
    |
 LL | fn boxed_boxed_scribbled<'a>(s: Box<Box<Scribble<'a>>>) -> &'a mut u32 {
    |                          -- lifetime `'a` defined here
-LL |     &mut *(**s).0 //[nll]~ ERROR borrow may still be in use when destructor runs [E0713]
+LL |     &mut *(**s).0
    |     ^^^^^^^^^^^^^ returning this value requires that `*s.0` is borrowed for `'a`
 ...
 LL | }
diff --git a/src/test/ui/issues/issue-46604.ast.nll.stderr b/src/test/ui/issues/issue-46604.ast.nll.stderr
index 4f73a0f..f43588c 100644
--- a/src/test/ui/issues/issue-46604.ast.nll.stderr
+++ b/src/test/ui/issues/issue-46604.ast.nll.stderr
@@ -1,13 +1,13 @@
 error[E0017]: references in statics may only refer to immutable values
   --> $DIR/issue-46604.rs:4:25
    |
-LL | static buf: &mut [u8] = &mut [1u8,2,3,4,5,7];   //[ast]~ ERROR E0017
+LL | static buf: &mut [u8] = &mut [1u8,2,3,4,5,7];
    |                         ^^^^^^^^^^^^^^^^^^^^ statics require immutable values
 
 error[E0594]: cannot assign to `buf[_]`, as `buf` is an immutable static item
   --> $DIR/issue-46604.rs:10:5
    |
-LL |     buf[0]=2;                                   //[ast]~ ERROR E0389
+LL |     buf[0]=2;
    |     ^^^^^^^^ cannot assign
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/issues/issue-46604.ast.stderr b/src/test/ui/issues/issue-46604.ast.stderr
index 14b9242..2ee1ac2 100644
--- a/src/test/ui/issues/issue-46604.ast.stderr
+++ b/src/test/ui/issues/issue-46604.ast.stderr
@@ -1,13 +1,13 @@
 error[E0017]: references in statics may only refer to immutable values
   --> $DIR/issue-46604.rs:4:25
    |
-LL | static buf: &mut [u8] = &mut [1u8,2,3,4,5,7];   //[ast]~ ERROR E0017
+LL | static buf: &mut [u8] = &mut [1u8,2,3,4,5,7];
    |                         ^^^^^^^^^^^^^^^^^^^^ statics require immutable values
 
 error[E0389]: cannot assign to data in a `&` reference
   --> $DIR/issue-46604.rs:10:5
    |
-LL |     buf[0]=2;                                   //[ast]~ ERROR E0389
+LL |     buf[0]=2;
    |     ^^^^^^^^ assignment into an immutable reference
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/issues/issue-46604.mir.stderr b/src/test/ui/issues/issue-46604.mir.stderr
index 4f73a0f..f43588c 100644
--- a/src/test/ui/issues/issue-46604.mir.stderr
+++ b/src/test/ui/issues/issue-46604.mir.stderr
@@ -1,13 +1,13 @@
 error[E0017]: references in statics may only refer to immutable values
   --> $DIR/issue-46604.rs:4:25
    |
-LL | static buf: &mut [u8] = &mut [1u8,2,3,4,5,7];   //[ast]~ ERROR E0017
+LL | static buf: &mut [u8] = &mut [1u8,2,3,4,5,7];
    |                         ^^^^^^^^^^^^^^^^^^^^ statics require immutable values
 
 error[E0594]: cannot assign to `buf[_]`, as `buf` is an immutable static item
   --> $DIR/issue-46604.rs:10:5
    |
-LL |     buf[0]=2;                                   //[ast]~ ERROR E0389
+LL |     buf[0]=2;
    |     ^^^^^^^^ cannot assign
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/issues/issue-50577.stderr b/src/test/ui/issues/issue-50577.stderr
index f26f5a9..0c3ba2e 100644
--- a/src/test/ui/issues/issue-50577.stderr
+++ b/src/test/ui/issues/issue-50577.stderr
@@ -2,10 +2,15 @@
   --> $DIR/issue-50577.rs:3:16
    |
 LL |         Drop = assert_eq!(1, 1)
-   |                ^^^^^^^^^^^^^^^^ expected (), found isize
+   |                ^^^^^^^^^^^^^^^^
+   |                |
+   |                expected (), found isize
+   |                found here
    |
    = note: expected type `()`
               found type `isize`
+   = note: `if` expressions without `else` evaluate to `()`
+   = help: consider adding an `else` block that evaluates to the expected type
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
 error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-5500-1.ast.stderr b/src/test/ui/issues/issue-5500-1.ast.stderr
index 681ccbc..558e7b7 100644
--- a/src/test/ui/issues/issue-5500-1.ast.stderr
+++ b/src/test/ui/issues/issue-5500-1.ast.stderr
@@ -3,8 +3,8 @@
    |
 LL |       let _iter = TrieMapIterator{node: &a};
    |           ----- help: make this binding mutable: `mut _iter`
-LL | /     _iter.node = & //[ast]~ ERROR cannot assign to field `_iter.node` of immutable binding
-LL | |                    //[mir]~^ ERROR cannot assign to field `_iter.node` of immutable binding (Ast)
+LL | /     _iter.node = &
+LL | |
 LL | |                    // MIR doesn't generate an error because the code isn't reachable. This is OK
 LL | |                    // because the test is here to check that the compiler doesn't ICE (cf. #5500).
 LL | |     panic!()
diff --git a/src/test/ui/issues/issue-5500-1.mir.stderr b/src/test/ui/issues/issue-5500-1.mir.stderr
index 67ca23c..92f803e 100644
--- a/src/test/ui/issues/issue-5500-1.mir.stderr
+++ b/src/test/ui/issues/issue-5500-1.mir.stderr
@@ -3,8 +3,8 @@
    |
 LL |       let _iter = TrieMapIterator{node: &a};
    |           ----- help: make this binding mutable: `mut _iter`
-LL | /     _iter.node = & //[ast]~ ERROR cannot assign to field `_iter.node` of immutable binding
-LL | |                    //[mir]~^ ERROR cannot assign to field `_iter.node` of immutable binding (Ast)
+LL | /     _iter.node = &
+LL | |
 LL | |                    // MIR doesn't generate an error because the code isn't reachable. This is OK
 LL | |                    // because the test is here to check that the compiler doesn't ICE (cf. #5500).
 LL | |     panic!()
diff --git a/src/test/ui/issues/issue-55796.stderr b/src/test/ui/issues/issue-55796.stderr
index c05f8b8..7cf597d 100644
--- a/src/test/ui/issues/issue-55796.stderr
+++ b/src/test/ui/issues/issue-55796.stderr
@@ -16,8 +16,8 @@
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: but, the lifetime must be valid for the static lifetime...
    = note: ...so that the expression is assignable:
-           expected std::boxed::Box<(dyn std::iter::Iterator<Item=<Self as Graph<'a>>::Node> + 'static)>
-              found std::boxed::Box<dyn std::iter::Iterator<Item=<Self as Graph<'a>>::Node>>
+           expected std::boxed::Box<(dyn std::iter::Iterator<Item = <Self as Graph<'a>>::Node> + 'static)>
+              found std::boxed::Box<dyn std::iter::Iterator<Item = <Self as Graph<'a>>::Node>>
 
 error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
   --> $DIR/issue-55796.rs:21:9
@@ -37,8 +37,8 @@
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: but, the lifetime must be valid for the static lifetime...
    = note: ...so that the expression is assignable:
-           expected std::boxed::Box<(dyn std::iter::Iterator<Item=<Self as Graph<'a>>::Node> + 'static)>
-              found std::boxed::Box<dyn std::iter::Iterator<Item=<Self as Graph<'a>>::Node>>
+           expected std::boxed::Box<(dyn std::iter::Iterator<Item = <Self as Graph<'a>>::Node> + 'static)>
+              found std::boxed::Box<dyn std::iter::Iterator<Item = <Self as Graph<'a>>::Node>>
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-56031.rs b/src/test/ui/issues/issue-56031.rs
new file mode 100644
index 0000000..b68f568
--- /dev/null
+++ b/src/test/ui/issues/issue-56031.rs
@@ -0,0 +1,6 @@
+struct T;
+
+impl for T {}
+//~^ ERROR missing trait in a trait impl
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-56031.stderr b/src/test/ui/issues/issue-56031.stderr
new file mode 100644
index 0000000..3d7acee
--- /dev/null
+++ b/src/test/ui/issues/issue-56031.stderr
@@ -0,0 +1,8 @@
+error: missing trait in a trait impl
+  --> $DIR/issue-56031.rs:3:5
+   |
+LL | impl for T {}
+   |     ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-59029-1.rs b/src/test/ui/issues/issue-59029-1.rs
new file mode 100644
index 0000000..e98a4d0
--- /dev/null
+++ b/src/test/ui/issues/issue-59029-1.rs
@@ -0,0 +1,8 @@
+#![feature(trait_alias)]
+
+trait Svc<Req> { type Res; }
+
+trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
+//~^ ERROR associated type `Res` not found for `Self`
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-59029-1.stderr b/src/test/ui/issues/issue-59029-1.stderr
new file mode 100644
index 0000000..ed1d98c
--- /dev/null
+++ b/src/test/ui/issues/issue-59029-1.stderr
@@ -0,0 +1,9 @@
+error[E0220]: associated type `Res` not found for `Self`
+  --> $DIR/issue-59029-1.rs:5:46
+   |
+LL | trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
+   |                                              ^^^^^^^^^ associated type `Res` not found
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0220`.
diff --git a/src/test/ui/issues/issue-59029-2.rs b/src/test/ui/issues/issue-59029-2.rs
new file mode 100644
index 0000000..2bdb128
--- /dev/null
+++ b/src/test/ui/issues/issue-59029-2.rs
@@ -0,0 +1,8 @@
+// run-pass
+#![feature(trait_alias)]
+
+trait Svc<Req> { type Res; }
+
+trait MkSvc<Target, Req> = Svc<Target> where <Self as Svc<Target>>::Res: Svc<Req>;
+
+fn main() {}
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.ast.nll.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.ast.nll.stderr
index 9d24570..8376ee8 100644
--- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.ast.nll.stderr
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.ast.nll.stderr
@@ -4,7 +4,7 @@
 LL |     let v: isize;
    |         - help: make this binding mutable: `mut v`
 ...
-LL |         v = 1; //[ast]~ ERROR cannot assign twice to immutable variable
+LL |         v = 1;
    |         ^^^^^ cannot assign twice to immutable variable
 
 error: aborting due to previous error
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.ast.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.ast.stderr
index 20003b7..db2a482 100644
--- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.ast.stderr
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.ast.stderr
@@ -1,7 +1,7 @@
 error[E0384]: cannot assign twice to immutable variable `v`
   --> $DIR/liveness-assign-imm-local-in-loop.rs:9:9
    |
-LL |         v = 1; //[ast]~ ERROR cannot assign twice to immutable variable
+LL |         v = 1;
    |         ^^^^^ cannot assign twice to immutable variable
 
 error: aborting due to previous error
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.mir.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.mir.stderr
index 9d24570..8376ee8 100644
--- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.mir.stderr
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.mir.stderr
@@ -4,7 +4,7 @@
 LL |     let v: isize;
    |         - help: make this binding mutable: `mut v`
 ...
-LL |         v = 1; //[ast]~ ERROR cannot assign twice to immutable variable
+LL |         v = 1;
    |         ^^^^^ cannot assign twice to immutable variable
 
 error: aborting due to previous error
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.ast.nll.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.ast.nll.stderr
index 47b9b02..a6a1c73a 100644
--- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.ast.nll.stderr
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.ast.nll.stderr
@@ -4,10 +4,10 @@
 LL |     let v: isize;
    |         - help: make this binding mutable: `mut v`
 ...
-LL |     v = 2;  //[ast]~ NOTE first assignment
+LL |     v = 2;
    |     ----- first assignment to `v`
-LL |             //[mir]~^ NOTE first assignment
-LL |     v += 1; //[ast]~ ERROR cannot assign twice to immutable variable
+LL |
+LL |     v += 1;
    |     ^^^^^^ cannot assign twice to immutable variable
 
 error: aborting due to previous error
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.ast.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.ast.stderr
index 4ab254b..b287edf 100644
--- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.ast.stderr
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.ast.stderr
@@ -1,10 +1,10 @@
 error[E0384]: cannot assign twice to immutable variable `v`
   --> $DIR/liveness-assign-imm-local-in-op-eq.rs:10:5
    |
-LL |     v = 2;  //[ast]~ NOTE first assignment
+LL |     v = 2;
    |     ----- first assignment to `v`
-LL |             //[mir]~^ NOTE first assignment
-LL |     v += 1; //[ast]~ ERROR cannot assign twice to immutable variable
+LL |
+LL |     v += 1;
    |     ^^^^^^ cannot assign twice to immutable variable
 
 error: aborting due to previous error
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.mir.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.mir.stderr
index 47b9b02..a6a1c73a 100644
--- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.mir.stderr
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.mir.stderr
@@ -4,10 +4,10 @@
 LL |     let v: isize;
    |         - help: make this binding mutable: `mut v`
 ...
-LL |     v = 2;  //[ast]~ NOTE first assignment
+LL |     v = 2;
    |     ----- first assignment to `v`
-LL |             //[mir]~^ NOTE first assignment
-LL |     v += 1; //[ast]~ ERROR cannot assign twice to immutable variable
+LL |
+LL |     v += 1;
    |     ^^^^^^ cannot assign twice to immutable variable
 
 error: aborting due to previous error
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.ast.nll.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.ast.nll.stderr
index 08a1e9d..8316ffd 100644
--- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.ast.nll.stderr
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.ast.nll.stderr
@@ -1,13 +1,13 @@
 error[E0384]: cannot assign twice to immutable variable `b`
   --> $DIR/liveness-assign-imm-local-with-drop.rs:10:5
    |
-LL |     let b = Box::new(1); //[ast]~ NOTE first assignment
+LL |     let b = Box::new(1);
    |         -
    |         |
    |         first assignment to `b`
    |         help: make this binding mutable: `mut b`
 ...
-LL |     b = Box::new(2); //[ast]~ ERROR cannot assign twice to immutable variable
+LL |     b = Box::new(2);
    |     ^ cannot assign twice to immutable variable
 
 error: aborting due to previous error
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.ast.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.ast.stderr
index d543fb9..108ca48 100644
--- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.ast.stderr
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.ast.stderr
@@ -1,10 +1,10 @@
 error[E0384]: cannot assign twice to immutable variable `b`
   --> $DIR/liveness-assign-imm-local-with-drop.rs:10:5
    |
-LL |     let b = Box::new(1); //[ast]~ NOTE first assignment
+LL |     let b = Box::new(1);
    |         - first assignment to `b`
 ...
-LL |     b = Box::new(2); //[ast]~ ERROR cannot assign twice to immutable variable
+LL |     b = Box::new(2);
    |     ^^^^^^^^^^^^^^^ cannot assign twice to immutable variable
 
 error: aborting due to previous error
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.mir.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.mir.stderr
index 08a1e9d..8316ffd 100644
--- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.mir.stderr
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.mir.stderr
@@ -1,13 +1,13 @@
 error[E0384]: cannot assign twice to immutable variable `b`
   --> $DIR/liveness-assign-imm-local-with-drop.rs:10:5
    |
-LL |     let b = Box::new(1); //[ast]~ NOTE first assignment
+LL |     let b = Box::new(1);
    |         -
    |         |
    |         first assignment to `b`
    |         help: make this binding mutable: `mut b`
 ...
-LL |     b = Box::new(2); //[ast]~ ERROR cannot assign twice to immutable variable
+LL |     b = Box::new(2);
    |     ^ cannot assign twice to immutable variable
 
 error: aborting due to previous error
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.ast.nll.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.ast.nll.stderr
index 3c1a569..5fa06f9 100644
--- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.ast.nll.stderr
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.ast.nll.stderr
@@ -1,13 +1,13 @@
 error[E0384]: cannot assign twice to immutable variable `v`
   --> $DIR/liveness-assign-imm-local-with-init.rs:10:5
    |
-LL |     let v: isize = 1; //[ast]~ NOTE first assignment
+LL |     let v: isize = 1;
    |         -
    |         |
    |         first assignment to `v`
    |         help: make this binding mutable: `mut v`
 ...
-LL |     v = 2; //[ast]~ ERROR cannot assign twice to immutable variable
+LL |     v = 2;
    |     ^^^^^ cannot assign twice to immutable variable
 
 error: aborting due to previous error
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.ast.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.ast.stderr
index cf293ae..34fb160 100644
--- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.ast.stderr
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.ast.stderr
@@ -1,10 +1,10 @@
 error[E0384]: cannot assign twice to immutable variable `v`
   --> $DIR/liveness-assign-imm-local-with-init.rs:10:5
    |
-LL |     let v: isize = 1; //[ast]~ NOTE first assignment
+LL |     let v: isize = 1;
    |         - first assignment to `v`
 ...
-LL |     v = 2; //[ast]~ ERROR cannot assign twice to immutable variable
+LL |     v = 2;
    |     ^^^^^ cannot assign twice to immutable variable
 
 error: aborting due to previous error
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.mir.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.mir.stderr
index 3c1a569..5fa06f9 100644
--- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.mir.stderr
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.mir.stderr
@@ -1,13 +1,13 @@
 error[E0384]: cannot assign twice to immutable variable `v`
   --> $DIR/liveness-assign-imm-local-with-init.rs:10:5
    |
-LL |     let v: isize = 1; //[ast]~ NOTE first assignment
+LL |     let v: isize = 1;
    |         -
    |         |
    |         first assignment to `v`
    |         help: make this binding mutable: `mut v`
 ...
-LL |     v = 2; //[ast]~ ERROR cannot assign twice to immutable variable
+LL |     v = 2;
    |     ^^^^^ cannot assign twice to immutable variable
 
 error: aborting due to previous error
diff --git a/src/test/ui/macros/missing-comma.rs b/src/test/ui/macros/missing-comma.rs
index 1e14687..2b411ab 100644
--- a/src/test/ui/macros/missing-comma.rs
+++ b/src/test/ui/macros/missing-comma.rs
@@ -6,6 +6,11 @@
     ($a:ident, $b:ident, $c:ident, $d:ident, $e:ident) => ();
 }
 
+macro_rules! bar {
+    ($lvl:expr, $($arg:tt)+) => {}
+}
+
+
 fn main() {
     println!("{}" a);
     //~^ ERROR expected token: `,`
@@ -17,4 +22,6 @@
     //~^ ERROR no rules expected the token `d`
     foo!(a, b, c d e);
     //~^ ERROR no rules expected the token `d`
+    bar!(Level::Error, );
+    //~^ ERROR unexpected end of macro invocation
 }
diff --git a/src/test/ui/macros/missing-comma.stderr b/src/test/ui/macros/missing-comma.stderr
index 5881e0b..424fefd 100644
--- a/src/test/ui/macros/missing-comma.stderr
+++ b/src/test/ui/macros/missing-comma.stderr
@@ -1,11 +1,11 @@
 error: expected token: `,`
-  --> $DIR/missing-comma.rs:10:19
+  --> $DIR/missing-comma.rs:15:19
    |
 LL |     println!("{}" a);
    |                   ^
 
 error: no rules expected the token `b`
-  --> $DIR/missing-comma.rs:12:12
+  --> $DIR/missing-comma.rs:17:12
    |
 LL | macro_rules! foo {
    | ---------------- when calling this macro
@@ -16,7 +16,7 @@
    |           help: missing comma here
 
 error: no rules expected the token `e`
-  --> $DIR/missing-comma.rs:14:21
+  --> $DIR/missing-comma.rs:19:21
    |
 LL | macro_rules! foo {
    | ---------------- when calling this macro
@@ -27,7 +27,7 @@
    |                    help: missing comma here
 
 error: no rules expected the token `d`
-  --> $DIR/missing-comma.rs:16:18
+  --> $DIR/missing-comma.rs:21:18
    |
 LL | macro_rules! foo {
    | ---------------- when calling this macro
@@ -38,7 +38,7 @@
    |                 help: missing comma here
 
 error: no rules expected the token `d`
-  --> $DIR/missing-comma.rs:18:18
+  --> $DIR/missing-comma.rs:23:18
    |
 LL | macro_rules! foo {
    | ---------------- when calling this macro
@@ -46,5 +46,14 @@
 LL |     foo!(a, b, c d e);
    |                  ^ no rules expected this token in macro call
 
-error: aborting due to 5 previous errors
+error: unexpected end of macro invocation
+  --> $DIR/missing-comma.rs:25:23
+   |
+LL | macro_rules! bar {
+   | ---------------- when calling this macro
+...
+LL |     bar!(Level::Error, );
+   |                       ^ missing tokens in macro arguments
+
+error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/meta-expected-error-correct-rev.a.stderr b/src/test/ui/meta-expected-error-correct-rev.a.stderr
index b561a9e..901bdcd 100644
--- a/src/test/ui/meta-expected-error-correct-rev.a.stderr
+++ b/src/test/ui/meta-expected-error-correct-rev.a.stderr
@@ -1,7 +1,7 @@
 error[E0308]: mismatched types
   --> $DIR/meta-expected-error-correct-rev.rs:7:18
    |
-LL |     let x: u32 = 22_usize; //[a]~ ERROR mismatched types
+LL |     let x: u32 = 22_usize;
    |                  ^^^^^^^^ expected u32, found usize
 
 error: aborting due to previous error
diff --git a/src/test/ui/mut/mut-pattern-internal-mutability.ast.nll.stderr b/src/test/ui/mut/mut-pattern-internal-mutability.ast.nll.stderr
index 82a4628..0db3201 100644
--- a/src/test/ui/mut/mut-pattern-internal-mutability.ast.nll.stderr
+++ b/src/test/ui/mut/mut-pattern-internal-mutability.ast.nll.stderr
@@ -6,7 +6,7 @@
    |              |
    |              first assignment to `x`
    |              help: make this binding mutable: `mut x`
-LL |     x += 1; //[ast]~ ERROR cannot assign twice to immutable variable
+LL |     x += 1;
    |     ^^^^^^ cannot assign twice to immutable variable
 
 error[E0506]: cannot assign to `*foo` because it is borrowed
@@ -14,9 +14,9 @@
    |
 LL |     let &mut ref x = foo;
    |              ----- borrow of `*foo` occurs here
-LL |     *foo += 1; //[ast]~ ERROR cannot assign to `*foo` because it is borrowed
+LL |     *foo += 1;
    |     ^^^^^^^^^ assignment to borrowed `*foo` occurs here
-LL |     //[mir]~^ ERROR cannot assign to `*foo` because it is borrowed
+LL |
 LL |     drop(x);
    |          - borrow later used here
 
diff --git a/src/test/ui/mut/mut-pattern-internal-mutability.ast.stderr b/src/test/ui/mut/mut-pattern-internal-mutability.ast.stderr
index e3423d5..da33cdf 100644
--- a/src/test/ui/mut/mut-pattern-internal-mutability.ast.stderr
+++ b/src/test/ui/mut/mut-pattern-internal-mutability.ast.stderr
@@ -3,7 +3,7 @@
    |
 LL |     let &mut x = foo;
    |              - first assignment to `x`
-LL |     x += 1; //[ast]~ ERROR cannot assign twice to immutable variable
+LL |     x += 1;
    |     ^^^^^^ cannot assign twice to immutable variable
 
 error[E0506]: cannot assign to `*foo` because it is borrowed
@@ -11,7 +11,7 @@
    |
 LL |     let &mut ref x = foo;
    |              ----- borrow of `*foo` occurs here
-LL |     *foo += 1; //[ast]~ ERROR cannot assign to `*foo` because it is borrowed
+LL |     *foo += 1;
    |     ^^^^^^^^^ assignment to borrowed `*foo` occurs here
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/mut/mut-pattern-internal-mutability.mir.stderr b/src/test/ui/mut/mut-pattern-internal-mutability.mir.stderr
index 82a4628..0db3201 100644
--- a/src/test/ui/mut/mut-pattern-internal-mutability.mir.stderr
+++ b/src/test/ui/mut/mut-pattern-internal-mutability.mir.stderr
@@ -6,7 +6,7 @@
    |              |
    |              first assignment to `x`
    |              help: make this binding mutable: `mut x`
-LL |     x += 1; //[ast]~ ERROR cannot assign twice to immutable variable
+LL |     x += 1;
    |     ^^^^^^ cannot assign twice to immutable variable
 
 error[E0506]: cannot assign to `*foo` because it is borrowed
@@ -14,9 +14,9 @@
    |
 LL |     let &mut ref x = foo;
    |              ----- borrow of `*foo` occurs here
-LL |     *foo += 1; //[ast]~ ERROR cannot assign to `*foo` because it is borrowed
+LL |     *foo += 1;
    |     ^^^^^^^^^ assignment to borrowed `*foo` occurs here
-LL |     //[mir]~^ ERROR cannot assign to `*foo` because it is borrowed
+LL |
 LL |     drop(x);
    |          - borrow later used here
 
diff --git a/src/test/ui/mut/mutable-class-fields.ast.nll.stderr b/src/test/ui/mut/mutable-class-fields.ast.nll.stderr
index 6b36b29..e243fb7 100644
--- a/src/test/ui/mut/mutable-class-fields.ast.nll.stderr
+++ b/src/test/ui/mut/mutable-class-fields.ast.nll.stderr
@@ -3,7 +3,7 @@
    |
 LL |   let nyan : Cat = cat(52, 99);
    |       ---- help: consider changing this to be mutable: `mut nyan`
-LL |   nyan.how_hungry = 0; //[ast]~ ERROR cannot assign
+LL |   nyan.how_hungry = 0;
    |   ^^^^^^^^^^^^^^^^^^^ cannot assign
 
 error: aborting due to previous error
diff --git a/src/test/ui/mut/mutable-class-fields.ast.stderr b/src/test/ui/mut/mutable-class-fields.ast.stderr
index 8018570..95a9284 100644
--- a/src/test/ui/mut/mutable-class-fields.ast.stderr
+++ b/src/test/ui/mut/mutable-class-fields.ast.stderr
@@ -3,7 +3,7 @@
    |
 LL |   let nyan : Cat = cat(52, 99);
    |       ---- help: make this binding mutable: `mut nyan`
-LL |   nyan.how_hungry = 0; //[ast]~ ERROR cannot assign
+LL |   nyan.how_hungry = 0;
    |   ^^^^^^^^^^^^^^^^^^^ cannot mutably borrow field of immutable binding
 
 error: aborting due to previous error
diff --git a/src/test/ui/mut/mutable-class-fields.mir.stderr b/src/test/ui/mut/mutable-class-fields.mir.stderr
index 6b36b29..e243fb7 100644
--- a/src/test/ui/mut/mutable-class-fields.mir.stderr
+++ b/src/test/ui/mut/mutable-class-fields.mir.stderr
@@ -3,7 +3,7 @@
    |
 LL |   let nyan : Cat = cat(52, 99);
    |       ---- help: consider changing this to be mutable: `mut nyan`
-LL |   nyan.how_hungry = 0; //[ast]~ ERROR cannot assign
+LL |   nyan.how_hungry = 0;
    |   ^^^^^^^^^^^^^^^^^^^ cannot assign
 
 error: aborting due to previous error
diff --git a/src/test/ui/namespace/namespace-mix.stderr b/src/test/ui/namespace/namespace-mix.stderr
index 22c871d..99fa3b9 100644
--- a/src/test/ui/namespace/namespace-mix.stderr
+++ b/src/test/ui/namespace/namespace-mix.stderr
@@ -462,11 +462,11 @@
 LL | fn check<T: Impossible>(_: T) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0277]: the trait bound `fn() -> namespace_mix::c::E {namespace_mix::c::E::TV}: Impossible` is not satisfied
+error[E0277]: the trait bound `fn() -> namespace_mix::c::E {namespace_mix::xm7::TV}: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:128:5
    |
 LL |     check(xm9::TV);
-   |     ^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::E {namespace_mix::c::E::TV}`
+   |     ^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::E {namespace_mix::xm7::TV}`
    |
 note: required by `check`
   --> $DIR/namespace-mix.rs:21:1
diff --git a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
index 8e40707..46de13d 100644
--- a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
+++ b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
@@ -16,7 +16,7 @@
    |                                       -  -  ^^^^^^ assignment requires that `'1` must outlive `'2`
    |                                       |  |
    |                                       |  has type `&'1 i32`
-   |                                       has type `&mut &'2 i32`
+   |                                       has type `&'_#2r mut &'2 i32`
 
 note: No external requirements
   --> $DIR/escape-argument-callee.rs:20:1
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
index 067bd08..7eb4d96 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
@@ -20,9 +20,9 @@
   --> $DIR/propagate-approximated-fail-no-postdom.rs:46:13
    |
 LL |         |_outlives1, _outlives2, _outlives3, x, y| {
-   |          ----------              ---------- has type `std::cell::Cell<&'2 &u32>`
+   |          ----------              ---------- has type `std::cell::Cell<&'2 &'_#3r u32>`
    |          |
-   |          has type `std::cell::Cell<&&'1 u32>`
+   |          has type `std::cell::Cell<&'_#1r &'1 u32>`
 ...
 LL |             demand_y(x, y, p)
    |             ^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
index 5cf37be..f8b6bfa 100644
--- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
@@ -20,9 +20,9 @@
   --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:37:9
    |
 LL |     establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
-   |                                                ---------  - has type `&std::cell::Cell<&'1 u32>`
+   |                                                ---------  - has type `&'_#7r std::cell::Cell<&'1 u32>`
    |                                                |
-   |                                                has type `&std::cell::Cell<&'2 &u32>`
+   |                                                has type `&'_#5r std::cell::Cell<&'2 &'_#1r u32>`
 LL |         // Only works if 'x: 'y:
 LL |         demand_y(x, y, x.get())
    |         ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
index 671a8b9..7e74294 100644
--- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
@@ -20,9 +20,9 @@
   --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:41:9
    |
 LL |     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
-   |                                                ----------  ---------- has type `&std::cell::Cell<&'2 &u32>`
+   |                                                ----------  ---------- has type `&'_#8r std::cell::Cell<&'2 &'_#2r u32>`
    |                                                |
-   |                                                has type `&std::cell::Cell<&'1 &u32>`
+   |                                                has type `&'_#6r std::cell::Cell<&'1 &'_#1r u32>`
 LL |         // Only works if 'x: 'y:
 LL |         demand_y(x, y, x.get())
    |         ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
diff --git a/src/test/ui/nll/match-guards-always-borrow.ast.nll.stderr b/src/test/ui/nll/match-guards-always-borrow.ast.nll.stderr
index 4d64794..82a30db 100644
--- a/src/test/ui/nll/match-guards-always-borrow.ast.nll.stderr
+++ b/src/test/ui/nll/match-guards-always-borrow.ast.nll.stderr
@@ -10,7 +10,7 @@
 error: compilation successful
   --> $DIR/match-guards-always-borrow.rs:47:1
    |
-LL | / fn main() { //[ast]~ ERROR compilation successful
+LL | / fn main() {
 LL | |     should_reject_destructive_mutate_in_guard();
 LL | |     allow_mutate_in_arm_body();
 LL | |     allow_move_into_arm_body();
diff --git a/src/test/ui/nll/match-guards-always-borrow.ast.stderr b/src/test/ui/nll/match-guards-always-borrow.ast.stderr
index 92d76d5..0c08f20 100644
--- a/src/test/ui/nll/match-guards-always-borrow.ast.stderr
+++ b/src/test/ui/nll/match-guards-always-borrow.ast.stderr
@@ -1,7 +1,7 @@
 error: compilation successful
   --> $DIR/match-guards-always-borrow.rs:47:1
    |
-LL | / fn main() { //[ast]~ ERROR compilation successful
+LL | / fn main() {
 LL | |     should_reject_destructive_mutate_in_guard();
 LL | |     allow_mutate_in_arm_body();
 LL | |     allow_move_into_arm_body();
diff --git a/src/test/ui/nll/reference-carried-through-struct-field.ast.nll.stderr b/src/test/ui/nll/reference-carried-through-struct-field.ast.nll.stderr
index f28e552..1f6eb9a 100644
--- a/src/test/ui/nll/reference-carried-through-struct-field.ast.nll.stderr
+++ b/src/test/ui/nll/reference-carried-through-struct-field.ast.nll.stderr
@@ -3,9 +3,9 @@
    |
 LL |     let wrapper = Wrap { w: &mut x };
    |                             ------ borrow of `x` occurs here
-LL |     x += 1; //[ast]~ ERROR cannot assign to `x` because it is borrowed [E0506]
+LL |     x += 1;
    |     ^^^^^^ use of borrowed `x`
-LL |     //[mir]~^ ERROR cannot use `x` because it was mutably borrowed [E0503]
+LL |
 LL |     *wrapper.w += 1;
    |     --------------- borrow later used here
 
diff --git a/src/test/ui/nll/reference-carried-through-struct-field.ast.stderr b/src/test/ui/nll/reference-carried-through-struct-field.ast.stderr
index b19d0b5..3104944 100644
--- a/src/test/ui/nll/reference-carried-through-struct-field.ast.stderr
+++ b/src/test/ui/nll/reference-carried-through-struct-field.ast.stderr
@@ -3,7 +3,7 @@
    |
 LL |     let wrapper = Wrap { w: &mut x };
    |                                  - borrow of `x` occurs here
-LL |     x += 1; //[ast]~ ERROR cannot assign to `x` because it is borrowed [E0506]
+LL |     x += 1;
    |     ^^^^^^ assignment to borrowed `x` occurs here
 
 error: aborting due to previous error
diff --git a/src/test/ui/nll/reference-carried-through-struct-field.mir.stderr b/src/test/ui/nll/reference-carried-through-struct-field.mir.stderr
index f28e552..1f6eb9a 100644
--- a/src/test/ui/nll/reference-carried-through-struct-field.mir.stderr
+++ b/src/test/ui/nll/reference-carried-through-struct-field.mir.stderr
@@ -3,9 +3,9 @@
    |
 LL |     let wrapper = Wrap { w: &mut x };
    |                             ------ borrow of `x` occurs here
-LL |     x += 1; //[ast]~ ERROR cannot assign to `x` because it is borrowed [E0506]
+LL |     x += 1;
    |     ^^^^^^ use of borrowed `x`
-LL |     //[mir]~^ ERROR cannot use `x` because it was mutably borrowed [E0503]
+LL |
 LL |     *wrapper.w += 1;
    |     --------------- borrow later used here
 
diff --git a/src/test/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.rs b/src/test/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.rs
new file mode 100644
index 0000000..3d042d4
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.rs
@@ -0,0 +1,70 @@
+// This test is ensuring that type ascriptions on let bindings
+// constrain both:
+//
+// 1. the input expression on the right-hand side (after any potential
+//    coercion, and allowing for covariance), *and*
+//
+// 2. the bindings (if any) nested within the pattern on the left-hand
+//    side (and here, the type-constraint is *invariant*).
+
+#![feature(nll)]
+
+#![allow(dead_code, unused_mut)]
+type PairUncoupled<'a, 'b, T> = (&'a T, &'b T);
+type PairCoupledRegions<'a, T> = (&'a T, &'a T);
+type PairCoupledTypes<T> = (T, T);
+
+fn uncoupled_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+    let ((mut y, mut _z),): (PairUncoupled<u32>,) = ((s, &_x),); // ok
+    // Above compiling does *not* imply below would compile.
+    // ::std::mem::swap(&mut y, &mut _z);
+    y
+}
+
+fn swap_regions((mut y, mut _z): PairCoupledRegions<u32>) {
+    ::std::mem::swap(&mut y, &mut _z);
+}
+
+fn coupled_regions_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+    let ((y, _z),): (PairCoupledRegions<u32>,) = ((s, &_x),);
+    // If above line compiled, so should line below ...
+
+    // swap_regions((y, _z));
+
+    // ... but the ascribed type also invalidates this use of `y`
+    y //~ ERROR lifetime may not live long enough
+}
+
+fn swap_types((mut y, mut _z): PairCoupledTypes<&u32>) {
+    ::std::mem::swap(&mut y, &mut _z);
+}
+
+fn coupled_types_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+    let ((y, _z),): (PairCoupledTypes<&u32>,) = ((s, &_x),);
+    // If above line compiled, so should line below ...
+
+    // swap_types((y, _z));
+
+    // ... but the ascribed type also invalidates this use of `y`
+    y //~ ERROR lifetime may not live long enough
+}
+
+fn swap_wilds((mut y, mut _z): PairCoupledTypes<&u32>) {
+    ::std::mem::swap(&mut y, &mut _z);
+}
+
+fn coupled_wilds_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+    let ((y, _z),): (PairCoupledTypes<_>,) = ((s, &_x),);
+    // If above line compiled, so should line below
+    // swap_wilds((y, _z));
+
+    // ... but the ascribed type also invalidates this use of `y`
+    y //~ ERROR lifetime may not live long enough
+}
+
+fn main() {
+    uncoupled_lhs(&3, &4);
+    coupled_regions_lhs(&3, &4);
+    coupled_types_lhs(&3, &4);
+    coupled_wilds_lhs(&3, &4);
+}
diff --git a/src/test/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.stderr b/src/test/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.stderr
new file mode 100644
index 0000000..5929707
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.stderr
@@ -0,0 +1,29 @@
+error: lifetime may not live long enough
+  --> $DIR/issue-55748-pat-types-constrain-bindings.rs:35:5
+   |
+LL | fn coupled_regions_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+   |                        -- lifetime `'a` defined here
+...
+LL |     y
+   |     ^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/issue-55748-pat-types-constrain-bindings.rs:49:5
+   |
+LL | fn coupled_types_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+   |                      -- lifetime `'a` defined here
+...
+LL |     y
+   |     ^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/issue-55748-pat-types-constrain-bindings.rs:62:5
+   |
+LL | fn coupled_wilds_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+   |                      -- lifetime `'a` defined here
+...
+LL |     y
+   |     ^ returning this value requires that `'a` must outlive `'static`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/obsolete-in-place/bad.bad.stderr b/src/test/ui/obsolete-in-place/bad.bad.stderr
index 245ecb4..468577a 100644
--- a/src/test/ui/obsolete-in-place/bad.bad.stderr
+++ b/src/test/ui/obsolete-in-place/bad.bad.stderr
@@ -1,7 +1,7 @@
 error: emplacement syntax is obsolete (for now, anyway)
   --> $DIR/bad.rs:9:5
    |
-LL |     x <- y; //[bad]~ ERROR emplacement syntax is obsolete
+LL |     x <- y;
    |     ^^^^^^
    |
    = note: for more information, see <https://github.com/rust-lang/rust/issues/27779#issuecomment-378416911>
@@ -9,7 +9,7 @@
 error: emplacement syntax is obsolete (for now, anyway)
   --> $DIR/bad.rs:10:5
    |
-LL |     in(foo) { bar }; //[bad]~ ERROR emplacement syntax is obsolete
+LL |     in(foo) { bar };
    |     ^^^^^^^^^^^^^^^
    |
    = note: for more information, see <https://github.com/rust-lang/rust/issues/27779#issuecomment-378416911>
diff --git a/src/test/ui/parser/macros-no-semicolon-items.rs b/src/test/ui/parser/macros-no-semicolon-items.rs
index a727caf..3afc275 100644
--- a/src/test/ui/parser/macros-no-semicolon-items.rs
+++ b/src/test/ui/parser/macros-no-semicolon-items.rs
@@ -1,4 +1,15 @@
 macro_rules! foo()  //~ ERROR semicolon
+                    //~| ERROR unexpected end of macro
+
+macro_rules! bar {
+    ($($tokens:tt)*) => {}
+}
+
+bar!( //~ ERROR semicolon
+    blah
+    blah
+    blah
+)
 
 fn main() {
 }
diff --git a/src/test/ui/parser/macros-no-semicolon-items.stderr b/src/test/ui/parser/macros-no-semicolon-items.stderr
index a869a53..5276aa6 100644
--- a/src/test/ui/parser/macros-no-semicolon-items.stderr
+++ b/src/test/ui/parser/macros-no-semicolon-items.stderr
@@ -1,8 +1,45 @@
-error: macros that expand to items must either be surrounded with braces or followed by a semicolon
+error: macros that expand to items must be delimited with braces or followed by a semicolon
   --> $DIR/macros-no-semicolon-items.rs:1:17
    |
 LL | macro_rules! foo()
    |                 ^^
+help: change the delimiters to curly braces
+   |
+LL | macro_rules! foo {}
+   |                  ^^
+help: add a semicolon
+   |
+LL | macro_rules! foo();
+   |                   ^
 
-error: aborting due to previous error
+error: macros that expand to items must be delimited with braces or followed by a semicolon
+  --> $DIR/macros-no-semicolon-items.rs:8:5
+   |
+LL |   bar!(
+   |  _____^
+LL | |     blah
+LL | |     blah
+LL | |     blah
+LL | | )
+   | |_^
+help: change the delimiters to curly braces
+   |
+LL | bar! {
+LL |     blah
+LL |     blah
+LL |     blah
+LL | }
+   |
+help: add a semicolon
+   |
+LL | );
+   |  ^
+
+error: unexpected end of macro invocation
+  --> $DIR/macros-no-semicolon-items.rs:1:1
+   |
+LL | macro_rules! foo()
+   | ^^^^^^^^^^^^^^^^^^ missing tokens in macro arguments
+
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/parser/raw/raw-literal-self.rs b/src/test/ui/parser/raw/raw-literal-self.rs
index d7b9553..123a11b 100644
--- a/src/test/ui/parser/raw/raw-literal-self.rs
+++ b/src/test/ui/parser/raw/raw-literal-self.rs
@@ -1,3 +1,4 @@
-fn self_test(r#self: u32) {
-    //~^ ERROR `r#self` is not currently supported.
+fn main() {
+    let r#self;
+    //~^ ERROR `self` cannot be a raw identifier
 }
diff --git a/src/test/ui/parser/raw/raw-literal-self.stderr b/src/test/ui/parser/raw/raw-literal-self.stderr
index e643327..9a330fc 100644
--- a/src/test/ui/parser/raw/raw-literal-self.stderr
+++ b/src/test/ui/parser/raw/raw-literal-self.stderr
@@ -1,8 +1,8 @@
-error: `r#self` is not currently supported.
-  --> $DIR/raw-literal-self.rs:1:14
+error: `self` cannot be a raw identifier
+  --> $DIR/raw-literal-self.rs:2:9
    |
-LL | fn self_test(r#self: u32) {
-   |              ^^^^^^
+LL |     let r#self;
+   |         ^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/raw/raw-literal-underscore.rs b/src/test/ui/parser/raw/raw-literal-underscore.rs
index bbedd39..6d15f1e 100644
--- a/src/test/ui/parser/raw/raw-literal-underscore.rs
+++ b/src/test/ui/parser/raw/raw-literal-underscore.rs
@@ -1,3 +1,4 @@
-fn underscore_test(r#_: u32) {
-    //~^ ERROR `r#_` is not currently supported.
+fn main() {
+    let r#_;
+    //~^ ERROR `_` cannot be a raw identifier
 }
diff --git a/src/test/ui/parser/raw/raw-literal-underscore.stderr b/src/test/ui/parser/raw/raw-literal-underscore.stderr
index 9427b33..d96b14f 100644
--- a/src/test/ui/parser/raw/raw-literal-underscore.stderr
+++ b/src/test/ui/parser/raw/raw-literal-underscore.stderr
@@ -1,8 +1,8 @@
-error: `r#_` is not currently supported.
-  --> $DIR/raw-literal-underscore.rs:1:20
+error: `_` cannot be a raw identifier
+  --> $DIR/raw-literal-underscore.rs:2:9
    |
-LL | fn underscore_test(r#_: u32) {
-   |                    ^^^
+LL |     let r#_;
+   |         ^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/recover-enum.rs b/src/test/ui/parser/recover-enum.rs
index 204ad85..da42da8 100644
--- a/src/test/ui/parser/recover-enum.rs
+++ b/src/test/ui/parser/recover-enum.rs
@@ -3,7 +3,11 @@
 fn main() {
     enum Test {
         Very
-        Bad //~ ERROR found `Bad`
-        Stuff
+        //~^ ERROR missing comma
+        Bad(usize)
+        //~^ ERROR missing comma
+        Stuff { a: usize }
+        //~^ ERROR missing comma
+        Here
     }
 }
diff --git a/src/test/ui/parser/recover-enum.stderr b/src/test/ui/parser/recover-enum.stderr
index 8c3448d..10b4aba 100644
--- a/src/test/ui/parser/recover-enum.stderr
+++ b/src/test/ui/parser/recover-enum.stderr
@@ -1,10 +1,20 @@
-error: expected one of `(`, `,`, `=`, `{`, or `}`, found `Bad`
-  --> $DIR/recover-enum.rs:6:9
+error: missing comma
+  --> $DIR/recover-enum.rs:5:13
    |
 LL |         Very
-   |             - expected one of `(`, `,`, `=`, `{`, or `}` here
-LL |         Bad
-   |         ^^^ unexpected token
+   |             ^ help: missing comma
 
-error: aborting due to previous error
+error: missing comma
+  --> $DIR/recover-enum.rs:7:19
+   |
+LL |         Bad(usize)
+   |                   ^ help: missing comma
+
+error: missing comma
+  --> $DIR/recover-enum.rs:9:27
+   |
+LL |         Stuff { a: usize }
+   |                           ^ help: missing comma
+
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/parser/trait-pub-assoc-const.rs b/src/test/ui/parser/trait-pub-assoc-const.rs
index 3ee2dc1..219ffa3 100644
--- a/src/test/ui/parser/trait-pub-assoc-const.rs
+++ b/src/test/ui/parser/trait-pub-assoc-const.rs
@@ -1,6 +1,6 @@
 trait Foo {
     pub const Foo: u32;
-    //~^ ERROR expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found
+    //~^ ERROR unnecessary visibility qualifier
 }
 
 fn main() {}
diff --git a/src/test/ui/parser/trait-pub-assoc-const.stderr b/src/test/ui/parser/trait-pub-assoc-const.stderr
index 8fc9ae4..817692c 100644
--- a/src/test/ui/parser/trait-pub-assoc-const.stderr
+++ b/src/test/ui/parser/trait-pub-assoc-const.stderr
@@ -1,10 +1,8 @@
-error: expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found `pub`
+error: unnecessary visibility qualifier
   --> $DIR/trait-pub-assoc-const.rs:2:5
    |
-LL | trait Foo {
-   |            - expected one of 7 possible tokens here
 LL |     pub const Foo: u32;
-   |     ^^^ unexpected token
+   |     ^^^ `pub` not permitted here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/trait-pub-assoc-ty.rs b/src/test/ui/parser/trait-pub-assoc-ty.rs
index 042addf..a78dfbd 100644
--- a/src/test/ui/parser/trait-pub-assoc-ty.rs
+++ b/src/test/ui/parser/trait-pub-assoc-ty.rs
@@ -1,6 +1,6 @@
 trait Foo {
     pub type Foo;
-    //~^ ERROR expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found
+    //~^ ERROR unnecessary visibility qualifier
 }
 
 fn main() {}
diff --git a/src/test/ui/parser/trait-pub-assoc-ty.stderr b/src/test/ui/parser/trait-pub-assoc-ty.stderr
index b8eab4e..400be6a 100644
--- a/src/test/ui/parser/trait-pub-assoc-ty.stderr
+++ b/src/test/ui/parser/trait-pub-assoc-ty.stderr
@@ -1,10 +1,8 @@
-error: expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found `pub`
+error: unnecessary visibility qualifier
   --> $DIR/trait-pub-assoc-ty.rs:2:5
    |
-LL | trait Foo {
-   |            - expected one of 7 possible tokens here
 LL |     pub type Foo;
-   |     ^^^ unexpected token
+   |     ^^^ `pub` not permitted here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/trait-pub-method.rs b/src/test/ui/parser/trait-pub-method.rs
index 9675182..1f6ee02 100644
--- a/src/test/ui/parser/trait-pub-method.rs
+++ b/src/test/ui/parser/trait-pub-method.rs
@@ -1,6 +1,6 @@
 trait Foo {
     pub fn foo();
-    //~^ ERROR expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found
+    //~^ ERROR unnecessary visibility qualifier
 }
 
 fn main() {}
diff --git a/src/test/ui/parser/trait-pub-method.stderr b/src/test/ui/parser/trait-pub-method.stderr
index d4db961..b3617a4 100644
--- a/src/test/ui/parser/trait-pub-method.stderr
+++ b/src/test/ui/parser/trait-pub-method.stderr
@@ -1,10 +1,8 @@
-error: expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found `pub`
+error: unnecessary visibility qualifier
   --> $DIR/trait-pub-method.rs:2:5
    |
-LL | trait Foo {
-   |            - expected one of 7 possible tokens here
 LL |     pub fn foo();
-   |     ^^^ unexpected token
+   |     ^^^ `pub` not permitted here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/privacy/private-inferred-type-3.rs b/src/test/ui/privacy/private-inferred-type-3.rs
index d885407..39f2e5d 100644
--- a/src/test/ui/privacy/private-inferred-type-3.rs
+++ b/src/test/ui/privacy/private-inferred-type-3.rs
@@ -6,7 +6,7 @@
 // error-pattern:type `fn() {<u8 as ext::PrivTrait>::method}` is private
 // error-pattern:type `fn(u8) -> ext::PrivTupleStruct {ext::PrivTupleStruct}` is private
 // error-pattern:type `fn(u8) -> ext::PubTupleStruct {ext::PubTupleStruct}` is private
-// error-pattern:type `for<'r> fn(&'r ext::Pub<u8>) {<ext::Pub<u8>>::priv_method}` is private
+// error-pattern:type `for<'r> fn(&'r ext::Pub<u8>) {ext::Pub::<u8>::priv_method}` is private
 
 #![feature(decl_macro)]
 
diff --git a/src/test/ui/privacy/private-inferred-type-3.stderr b/src/test/ui/privacy/private-inferred-type-3.stderr
index f8b757e..61cd847 100644
--- a/src/test/ui/privacy/private-inferred-type-3.stderr
+++ b/src/test/ui/privacy/private-inferred-type-3.stderr
@@ -46,7 +46,7 @@
    |
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
-error: type `for<'r> fn(&'r ext::Pub<u8>) {<ext::Pub<u8>>::priv_method}` is private
+error: type `for<'r> fn(&'r ext::Pub<u8>) {ext::Pub::<u8>::priv_method}` is private
   --> $DIR/private-inferred-type-3.rs:16:5
    |
 LL |     ext::m!();
diff --git a/src/test/ui/privacy/private-inferred-type.rs b/src/test/ui/privacy/private-inferred-type.rs
index d98cf59..d9bb421 100644
--- a/src/test/ui/privacy/private-inferred-type.rs
+++ b/src/test/ui/privacy/private-inferred-type.rs
@@ -47,7 +47,7 @@
         PubTupleStruct;
         //~^ ERROR type `fn(u8) -> m::PubTupleStruct {m::PubTupleStruct}` is private
         Pub(0u8).priv_method();
-        //~^ ERROR type `for<'r> fn(&'r m::Pub<u8>) {<m::Pub<u8>>::priv_method}` is private
+        //~^ ERROR type `for<'r> fn(&'r m::Pub<u8>) {m::Pub::<u8>::priv_method}` is private
     }
 
     trait Trait {}
diff --git a/src/test/ui/privacy/private-inferred-type.stderr b/src/test/ui/privacy/private-inferred-type.stderr
index baa9829..4d40b6b 100644
--- a/src/test/ui/privacy/private-inferred-type.stderr
+++ b/src/test/ui/privacy/private-inferred-type.stderr
@@ -151,7 +151,7 @@
 LL |     m::m!();
    |     -------- in this macro invocation
 
-error: type `for<'r> fn(&'r m::Pub<u8>) {<m::Pub<u8>>::priv_method}` is private
+error: type `for<'r> fn(&'r m::Pub<u8>) {m::Pub::<u8>::priv_method}` is private
   --> $DIR/private-inferred-type.rs:49:18
    |
 LL |         Pub(0u8).priv_method();
diff --git a/src/test/ui/proc-macro/attribute.rs b/src/test/ui/proc-macro/attribute.rs
index a0b982d..ac7d0b4 100644
--- a/src/test/ui/proc-macro/attribute.rs
+++ b/src/test/ui/proc-macro/attribute.rs
@@ -4,53 +4,73 @@
 #![crate_type = "proc-macro"]
 
 extern crate proc_macro;
+use proc_macro::*;
 
 #[proc_macro_derive]
 //~^ ERROR: attribute must be of the form
-pub fn foo1(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
-    input
-}
+pub fn foo1(input: TokenStream) -> TokenStream { input }
 
-#[proc_macro_derive = "foo"]
+#[proc_macro_derive = ""]
 //~^ ERROR: attribute must be of the form
-pub fn foo2(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
-    input
-}
+pub fn foo2(input: TokenStream) -> TokenStream { input }
 
-#[proc_macro_derive(
-    a = "b"
-)]
-//~^^ ERROR: must only be one word
-pub fn foo3(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
-    input
-}
-
-#[proc_macro_derive(b, c, d)]
+#[proc_macro_derive(d3, a, b)]
 //~^ ERROR: attribute must have either one or two arguments
-pub fn foo4(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
-    input
-}
+pub fn foo3(input: TokenStream) -> TokenStream { input }
 
-#[proc_macro_derive(d(e))]
-//~^ ERROR: must only be one word
-pub fn foo5(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
-    input
-}
-
-#[proc_macro_derive(f, attributes(g = "h"))]
-//~^ ERROR: must only be one word
-pub fn foo6(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
-    input
-}
-
-#[proc_macro_derive(i, attributes(j(k)))]
-//~^ ERROR: must only be one word
-pub fn foo7(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
-    input
-}
-
-#[proc_macro_derive(l, attributes(m), n)]
+#[proc_macro_derive(d4, attributes(a), b)]
 //~^ ERROR: attribute must have either one or two arguments
-pub fn foo8(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
-    input
-}
+pub fn foo4(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive("a")]
+//~^ ERROR: not a meta item
+pub fn foo5(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(d6 = "")]
+//~^ ERROR: must only be one word
+pub fn foo6(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(m::d7)]
+//~^ ERROR: must only be one word
+pub fn foo7(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(d8(a))]
+//~^ ERROR: must only be one word
+pub fn foo8(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(self)]
+//~^ ERROR: `self` cannot be a name of derive macro
+pub fn foo9(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(PartialEq)]
+//~^ ERROR: cannot override a built-in derive macro
+pub fn foo10(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(d11, a)]
+//~^ ERROR: second argument must be `attributes`
+//~| ERROR: attribute must be of form: `attributes(foo, bar)`
+pub fn foo11(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(d12, attributes)]
+//~^ ERROR: attribute must be of form: `attributes(foo, bar)`
+pub fn foo12(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(d13, attributes("a"))]
+//~^ ERROR: not a meta item
+pub fn foo13(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(d14, attributes(a = ""))]
+//~^ ERROR: must only be one word
+pub fn foo14(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(d15, attributes(m::a))]
+//~^ ERROR: must only be one word
+pub fn foo15(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(d16, attributes(a(b)))]
+//~^ ERROR: must only be one word
+pub fn foo16(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(d17, attributes(self))]
+//~^ ERROR: `self` cannot be a name of derive helper attribute
+pub fn foo17(input: TokenStream) -> TokenStream { input }
diff --git a/src/test/ui/proc-macro/attribute.stderr b/src/test/ui/proc-macro/attribute.stderr
index 231eb1f..cc17d38 100644
--- a/src/test/ui/proc-macro/attribute.stderr
+++ b/src/test/ui/proc-macro/attribute.stderr
@@ -1,50 +1,110 @@
-error: must only be one word
-  --> $DIR/attribute.rs:21:5
+error: attribute must have either one or two arguments
+  --> $DIR/attribute.rs:17:1
    |
-LL |     a = "b"
-   |     ^^^^^^^
+LL | #[proc_macro_derive(d3, a, b)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: attribute must have either one or two arguments
-  --> $DIR/attribute.rs:28:1
+  --> $DIR/attribute.rs:21:1
    |
-LL | #[proc_macro_derive(b, c, d)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[proc_macro_derive(d4, attributes(a), b)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: not a meta item
+  --> $DIR/attribute.rs:25:21
+   |
+LL | #[proc_macro_derive("a")]
+   |                     ^^^
 
 error: must only be one word
-  --> $DIR/attribute.rs:34:21
+  --> $DIR/attribute.rs:29:21
    |
-LL | #[proc_macro_derive(d(e))]
+LL | #[proc_macro_derive(d6 = "")]
+   |                     ^^^^^^^
+
+error: must only be one word
+  --> $DIR/attribute.rs:33:21
+   |
+LL | #[proc_macro_derive(m::d7)]
+   |                     ^^^^^
+
+error: must only be one word
+  --> $DIR/attribute.rs:37:21
+   |
+LL | #[proc_macro_derive(d8(a))]
+   |                     ^^^^^
+
+error: `self` cannot be a name of derive macro
+  --> $DIR/attribute.rs:41:21
+   |
+LL | #[proc_macro_derive(self)]
    |                     ^^^^
 
-error: must only be one word
-  --> $DIR/attribute.rs:40:35
+error: cannot override a built-in derive macro
+  --> $DIR/attribute.rs:45:21
    |
-LL | #[proc_macro_derive(f, attributes(g = "h"))]
-   |                                   ^^^^^^^
+LL | #[proc_macro_derive(PartialEq)]
+   |                     ^^^^^^^^^
+
+error: second argument must be `attributes`
+  --> $DIR/attribute.rs:49:26
+   |
+LL | #[proc_macro_derive(d11, a)]
+   |                          ^
+
+error: attribute must be of form: `attributes(foo, bar)`
+  --> $DIR/attribute.rs:49:26
+   |
+LL | #[proc_macro_derive(d11, a)]
+   |                          ^
+
+error: attribute must be of form: `attributes(foo, bar)`
+  --> $DIR/attribute.rs:54:26
+   |
+LL | #[proc_macro_derive(d12, attributes)]
+   |                          ^^^^^^^^^^
+
+error: not a meta item
+  --> $DIR/attribute.rs:58:37
+   |
+LL | #[proc_macro_derive(d13, attributes("a"))]
+   |                                     ^^^
 
 error: must only be one word
-  --> $DIR/attribute.rs:46:35
+  --> $DIR/attribute.rs:62:37
    |
-LL | #[proc_macro_derive(i, attributes(j(k)))]
-   |                                   ^^^^
+LL | #[proc_macro_derive(d14, attributes(a = ""))]
+   |                                     ^^^^^^
 
-error: attribute must have either one or two arguments
-  --> $DIR/attribute.rs:52:1
+error: must only be one word
+  --> $DIR/attribute.rs:66:37
    |
-LL | #[proc_macro_derive(l, attributes(m), n)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[proc_macro_derive(d15, attributes(m::a))]
+   |                                     ^^^^
+
+error: must only be one word
+  --> $DIR/attribute.rs:70:37
+   |
+LL | #[proc_macro_derive(d16, attributes(a(b)))]
+   |                                     ^^^^
+
+error: `self` cannot be a name of derive helper attribute
+  --> $DIR/attribute.rs:74:37
+   |
+LL | #[proc_macro_derive(d17, attributes(self))]
+   |                                     ^^^^
 
 error: attribute must be of the form `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]`
-  --> $DIR/attribute.rs:8:1
+  --> $DIR/attribute.rs:9:1
    |
 LL | #[proc_macro_derive]
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: attribute must be of the form `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]`
-  --> $DIR/attribute.rs:14:1
+  --> $DIR/attribute.rs:13:1
    |
-LL | #[proc_macro_derive = "foo"]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[proc_macro_derive = ""]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 8 previous errors
+error: aborting due to 18 previous errors
 
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-3.stderr b/src/test/ui/proc-macro/invalid-punct-ident-3.stderr
index 6ff47e3..24371f3 100644
--- a/src/test/ui/proc-macro/invalid-punct-ident-3.stderr
+++ b/src/test/ui/proc-macro/invalid-punct-ident-3.stderr
@@ -4,7 +4,7 @@
 LL | invalid_raw_ident!();
    | ^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: message: `"self"` is not a valid raw identifier
+   = help: message: `self` cannot be a raw identifier
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/proc-macro/shadow-builtin.rs b/src/test/ui/proc-macro/shadow-builtin.rs
deleted file mode 100644
index afcc0eb..0000000
--- a/src/test/ui/proc-macro/shadow-builtin.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-// force-host
-// no-prefer-dynamic
-
-#![crate_type = "proc-macro"]
-
-extern crate proc_macro;
-
-use proc_macro::TokenStream;
-
-#[proc_macro_derive(PartialEq)]
-//~^ ERROR: cannot override a built-in #[derive] mode
-pub fn foo(input: TokenStream) -> TokenStream {
-    input
-}
diff --git a/src/test/ui/proc-macro/shadow-builtin.stderr b/src/test/ui/proc-macro/shadow-builtin.stderr
deleted file mode 100644
index 6685795..0000000
--- a/src/test/ui/proc-macro/shadow-builtin.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: cannot override a built-in #[derive] mode
-  --> $DIR/shadow-builtin.rs:10:21
-   |
-LL | #[proc_macro_derive(PartialEq)]
-   |                     ^^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/regions/regions-addr-of-upvar-self.stderr b/src/test/ui/regions/regions-addr-of-upvar-self.stderr
index 01b2631..ac5e5e9 100644
--- a/src/test/ui/regions/regions-addr-of-upvar-self.stderr
+++ b/src/test/ui/regions/regions-addr-of-upvar-self.stderr
@@ -4,7 +4,7 @@
 LL |             let p: &'static mut usize = &mut self.food;
    |                                         ^^^^^^^^^^^^^^
    |
-note: first, the lifetime cannot outlive the lifetime  as defined on the body at 9:18...
+note: first, the lifetime cannot outlive the lifetime '_ as defined on the body at 9:18...
   --> $DIR/regions-addr-of-upvar-self.rs:9:18
    |
 LL |         let _f = || {
diff --git a/src/test/ui/regions/regions-free-region-ordering-caller.ast.stderr b/src/test/ui/regions/regions-free-region-ordering-caller.ast.stderr
index 73266ab..a33d358 100644
--- a/src/test/ui/regions/regions-free-region-ordering-caller.ast.stderr
+++ b/src/test/ui/regions/regions-free-region-ordering-caller.ast.stderr
@@ -5,7 +5,7 @@
    |                     ---------     ---------
    |                     |
    |                     these two types are declared with different lifetimes...
-LL |     let z: Option<&'b &'a usize> = None;//[ast]~ ERROR E0623
+LL |     let z: Option<&'b &'a usize> = None;
    |            ^^^^^^^^^^^^^^^^^^^^^ ...but data from `a` flows into `b` here
 
 error[E0623]: lifetime mismatch
@@ -16,7 +16,7 @@
    |                     |
    |                     these two types are declared with different lifetimes...
 LL |     let y: Paramd<'a> = Paramd { x: a };
-LL |     let z: Option<&'b Paramd<'a>> = None;//[ast]~ ERROR E0623
+LL |     let z: Option<&'b Paramd<'a>> = None;
    |            ^^^^^^^^^^^^^^^^^^^^^^ ...but data from `a` flows into `b` here
 
 error[E0623]: lifetime mismatch
@@ -24,7 +24,7 @@
    |
 LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) {
    |                     ---------     --------- these two types are declared with different lifetimes...
-LL |     let z: Option<&'a &'b usize> = None;//[ast]~ ERROR E0623
+LL |     let z: Option<&'a &'b usize> = None;
    |            ^^^^^^^^^^^^^^^^^^^^^ ...but data from `b` flows into `a` here
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/regions/regions-free-region-ordering-caller.mir.stderr b/src/test/ui/regions/regions-free-region-ordering-caller.mir.stderr
index abec468..16eda28 100644
--- a/src/test/ui/regions/regions-free-region-ordering-caller.mir.stderr
+++ b/src/test/ui/regions/regions-free-region-ordering-caller.mir.stderr
@@ -5,7 +5,7 @@
    |          --  -- lifetime `'b` defined here
    |          |
    |          lifetime `'a` defined here
-LL |     let z: Option<&'b &'a usize> = None;//[ast]~ ERROR E0623
+LL |     let z: Option<&'b &'a usize> = None;
    |            ^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'b`
 
 error: lifetime may not live long enough
@@ -16,7 +16,7 @@
    |          |
    |          lifetime `'a` defined here
 LL |     let y: Paramd<'a> = Paramd { x: a };
-LL |     let z: Option<&'b Paramd<'a>> = None;//[ast]~ ERROR E0623
+LL |     let z: Option<&'b Paramd<'a>> = None;
    |            ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'b`
 
 error: lifetime may not live long enough
@@ -26,7 +26,7 @@
    |          --  -- lifetime `'b` defined here
    |          |
    |          lifetime `'a` defined here
-LL |     let z: Option<&'a &'b usize> = None;//[ast]~ ERROR E0623
+LL |     let z: Option<&'a &'b usize> = None;
    |            ^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/regions/regions-pattern-typing-issue-19997.ast.nll.stderr b/src/test/ui/regions/regions-pattern-typing-issue-19997.ast.nll.stderr
index 9356200..b1c5878 100644
--- a/src/test/ui/regions/regions-pattern-typing-issue-19997.ast.nll.stderr
+++ b/src/test/ui/regions/regions-pattern-typing-issue-19997.ast.nll.stderr
@@ -4,9 +4,9 @@
 LL |     match (&a1,) {
    |            --- borrow of `a1` occurs here
 LL |         (&ref b0,) => {
-LL |             a1 = &f; //[ast]~ ERROR cannot assign
+LL |             a1 = &f;
    |             ^^^^^^^ assignment to borrowed `a1` occurs here
-LL |             //[mir]~^ ERROR cannot assign to `a1` because it is borrowed
+LL |
 LL |             drop(b0);
    |                  -- borrow later used here
 
diff --git a/src/test/ui/regions/regions-pattern-typing-issue-19997.ast.stderr b/src/test/ui/regions/regions-pattern-typing-issue-19997.ast.stderr
index e23c6ad..0074d2b 100644
--- a/src/test/ui/regions/regions-pattern-typing-issue-19997.ast.stderr
+++ b/src/test/ui/regions/regions-pattern-typing-issue-19997.ast.stderr
@@ -4,7 +4,7 @@
 LL |     match (&a1,) {
    |             -- borrow of `a1` occurs here
 LL |         (&ref b0,) => {
-LL |             a1 = &f; //[ast]~ ERROR cannot assign
+LL |             a1 = &f;
    |             ^^^^^^^ assignment to borrowed `a1` occurs here
 
 error: aborting due to previous error
diff --git a/src/test/ui/regions/regions-pattern-typing-issue-19997.mir.stderr b/src/test/ui/regions/regions-pattern-typing-issue-19997.mir.stderr
index 9356200..b1c5878 100644
--- a/src/test/ui/regions/regions-pattern-typing-issue-19997.mir.stderr
+++ b/src/test/ui/regions/regions-pattern-typing-issue-19997.mir.stderr
@@ -4,9 +4,9 @@
 LL |     match (&a1,) {
    |            --- borrow of `a1` occurs here
 LL |         (&ref b0,) => {
-LL |             a1 = &f; //[ast]~ ERROR cannot assign
+LL |             a1 = &f;
    |             ^^^^^^^ assignment to borrowed `a1` occurs here
-LL |             //[mir]~^ ERROR cannot assign to `a1` because it is borrowed
+LL |
 LL |             drop(b0);
    |                  -- borrow later used here
 
diff --git a/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr b/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr
index 9cf0b0f..be441bc 100644
--- a/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr
+++ b/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr
@@ -4,7 +4,7 @@
 LL |         let mut f = || &mut x;
    |                        ^^^^^^
    |
-note: first, the lifetime cannot outlive the lifetime  as defined on the body at 7:21...
+note: first, the lifetime cannot outlive the lifetime '_ as defined on the body at 7:21...
   --> $DIR/regions-return-ref-to-upvar-issue-17403.rs:7:21
    |
 LL |         let mut f = || &mut x;
diff --git a/src/test/ui/regions/regions-static-bound.ll.stderr b/src/test/ui/regions/regions-static-bound.ll.stderr
index 4695a82..d0dc554 100644
--- a/src/test/ui/regions/regions-static-bound.ll.stderr
+++ b/src/test/ui/regions/regions-static-bound.ll.stderr
@@ -1,7 +1,7 @@
 error[E0312]: lifetime of reference outlives lifetime of borrowed content...
   --> $DIR/regions-static-bound.rs:9:5
    |
-LL |     t //[ll]~ ERROR E0312
+LL |     t
    |     ^
    |
    = note: ...the reference is valid for the static lifetime...
@@ -16,7 +16,7 @@
    |
 LL | fn error(u: &(), v: &()) {
    |             --- help: add explicit lifetime `'static` to the type of `u`: `&'static ()`
-LL |     static_id(&u); //[ll]~ ERROR explicit lifetime required in the type of `u` [E0621]
+LL |     static_id(&u);
    |     ^^^^^^^^^ lifetime `'static` required
 
 error[E0621]: explicit lifetime required in the type of `v`
@@ -25,7 +25,7 @@
 LL | fn error(u: &(), v: &()) {
    |                     --- help: add explicit lifetime `'static` to the type of `v`: `&'static ()`
 ...
-LL |     static_id_indirect(&v); //[ll]~ ERROR explicit lifetime required in the type of `v` [E0621]
+LL |     static_id_indirect(&v);
    |     ^^^^^^^^^^^^^^^^^^ lifetime `'static` required
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/regions/regions-static-bound.nll.stderr b/src/test/ui/regions/regions-static-bound.nll.stderr
index d6cec03..b5f3e6c 100644
--- a/src/test/ui/regions/regions-static-bound.nll.stderr
+++ b/src/test/ui/regions/regions-static-bound.nll.stderr
@@ -3,7 +3,7 @@
    |
 LL | fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a {
    |                        -- lifetime `'a` defined here
-LL |     t //[ll]~ ERROR E0312
+LL |     t
    |     ^ returning this value requires that `'a` must outlive `'static`
 
 error[E0621]: explicit lifetime required in the type of `u`
@@ -11,7 +11,7 @@
    |
 LL | fn error(u: &(), v: &()) {
    |             --- help: add explicit lifetime `'static` to the type of `u`: `&'static ()`
-LL |     static_id(&u); //[ll]~ ERROR explicit lifetime required in the type of `u` [E0621]
+LL |     static_id(&u);
    |     ^^^^^^^^^^^^^ lifetime `'static` required
 
 error[E0621]: explicit lifetime required in the type of `v`
@@ -20,7 +20,7 @@
 LL | fn error(u: &(), v: &()) {
    |                     --- help: add explicit lifetime `'static` to the type of `v`: `&'static ()`
 ...
-LL |     static_id_indirect(&v); //[ll]~ ERROR explicit lifetime required in the type of `v` [E0621]
+LL |     static_id_indirect(&v);
    |     ^^^^^^^^^^^^^^^^^^^^^^ lifetime `'static` required
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/retslot-cast.stderr b/src/test/ui/retslot-cast.stderr
index 3c58285..a116991 100644
--- a/src/test/ui/retslot-cast.stderr
+++ b/src/test/ui/retslot-cast.stderr
@@ -2,10 +2,10 @@
   --> $DIR/retslot-cast.rs:13:5
    |
 LL |     inner(x)
-   |     ^^^^^^^^ expected trait `std::iter::Iterator<Item=()>`, found trait `std::iter::Iterator<Item=()> + std::marker::Send`
+   |     ^^^^^^^^ expected trait `std::iter::Iterator<Item = ()>`, found trait `std::iter::Iterator<Item = ()> + std::marker::Send`
    |
-   = note: expected type `std::option::Option<&dyn std::iter::Iterator<Item=()>>`
-              found type `std::option::Option<&dyn std::iter::Iterator<Item=()> + std::marker::Send>`
+   = note: expected type `std::option::Option<&dyn std::iter::Iterator<Item = ()>>`
+              found type `std::option::Option<&dyn std::iter::Iterator<Item = ()> + std::marker::Send>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs
index 3d24f49..67f7f80 100644
--- a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs
+++ b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs
@@ -33,6 +33,9 @@
     // We can move `b` because it's Copy.
     drop(b);
 
+    // Without parameters works as expected.
+    let _: () = dbg!();
+
     // Test that we can borrow and that successive applications is still identity.
     let a = NoCopy(1337);
     let b: &NoCopy = dbg!(dbg!(&a));
@@ -69,17 +72,19 @@
         "    y: 24",
         "}",
 
-        ":38] &a = NoCopy(",
+        ":37]",
+
+        ":41] &a = NoCopy(",
         "    1337",
         ")",
 
-        ":38] dbg!(& a) = NoCopy(",
+        ":41] dbg!(& a) = NoCopy(",
         "    1337",
         ")",
-        ":43] f(&42) = 42",
+        ":46] f(&42) = 42",
 
         "before",
-        ":48] { foo += 1; eprintln!(\"before\"); 7331 } = 7331",
+        ":51] { foo += 1; eprintln!(\"before\"); 7331 } = 7331",
     ]);
 }
 
diff --git a/src/test/ui/rfc1445/feature-gate.no_gate.stderr b/src/test/ui/rfc1445/feature-gate.no_gate.stderr
index 8c6a08d..370b74b 100644
--- a/src/test/ui/rfc1445/feature-gate.no_gate.stderr
+++ b/src/test/ui/rfc1445/feature-gate.no_gate.stderr
@@ -1,7 +1,7 @@
 error[E0658]: the semantics of constant patterns is not yet settled (see issue #31434)
   --> $DIR/feature-gate.rs:13:1
    |
-LL | #[structural_match] //[no_gate]~ ERROR semantics of constant patterns is not yet settled
+LL | #[structural_match]
    | ^^^^^^^^^^^^^^^^^^^
    |
    = help: add #![feature(structural_match)] to the crate attributes to enable
diff --git a/src/test/ui/rfc1445/feature-gate.with_gate.stderr b/src/test/ui/rfc1445/feature-gate.with_gate.stderr
index da68166..ca8dc75 100644
--- a/src/test/ui/rfc1445/feature-gate.with_gate.stderr
+++ b/src/test/ui/rfc1445/feature-gate.with_gate.stderr
@@ -1,7 +1,7 @@
 error: compilation successful
   --> $DIR/feature-gate.rs:21:1
    |
-LL | / fn main() { //[with_gate]~ ERROR compilation successful
+LL | / fn main() {
 LL | |     let y = Foo { x: 1 };
 LL | |     match y {
 LL | |         FOO => { }
diff --git a/src/test/ui/rust-2018/uniform-paths/auxiliary/cross-crate.rs b/src/test/ui/rust-2018/uniform-paths/auxiliary/cross-crate.rs
new file mode 100644
index 0000000..4aa5d18
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/auxiliary/cross-crate.rs
@@ -0,0 +1,5 @@
+// edition:2018
+
+pub use ignore as built_in_attr;
+pub use u8 as built_in_type;
+pub use rustfmt as tool_mod;
diff --git a/src/test/ui/rust-2018/uniform-paths/cross-crate.rs b/src/test/ui/rust-2018/uniform-paths/cross-crate.rs
new file mode 100644
index 0000000..27d6dbf
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/cross-crate.rs
@@ -0,0 +1,11 @@
+// edition:2018
+// aux-build:cross-crate.rs
+
+extern crate cross_crate;
+use cross_crate::*;
+
+#[built_in_attr] //~ ERROR cannot use a built-in attribute through an import
+#[tool_mod::skip] //~ ERROR cannot use a tool module through an import
+fn main() {
+    let _: built_in_type; // OK
+}
diff --git a/src/test/ui/rust-2018/uniform-paths/cross-crate.stderr b/src/test/ui/rust-2018/uniform-paths/cross-crate.stderr
new file mode 100644
index 0000000..fdde75f
--- /dev/null
+++ b/src/test/ui/rust-2018/uniform-paths/cross-crate.stderr
@@ -0,0 +1,26 @@
+error: cannot use a built-in attribute through an import
+  --> $DIR/cross-crate.rs:7:3
+   |
+LL | #[built_in_attr]
+   |   ^^^^^^^^^^^^^
+   |
+note: the built-in attribute imported here
+  --> $DIR/cross-crate.rs:5:5
+   |
+LL | use cross_crate::*;
+   |     ^^^^^^^^^^^^^^
+
+error: cannot use a tool module through an import
+  --> $DIR/cross-crate.rs:8:3
+   |
+LL | #[tool_mod::skip]
+   |   ^^^^^^^^
+   |
+note: the tool module imported here
+  --> $DIR/cross-crate.rs:5:5
+   |
+LL | use cross_crate::*;
+   |     ^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/simd-type.rs b/src/test/ui/simd-type.rs
index d1e2efa..9e4b7e7 100644
--- a/src/test/ui/simd-type.rs
+++ b/src/test/ui/simd-type.rs
@@ -7,7 +7,4 @@
 #[repr(simd)]
 struct i64f64(i64, f64); //~ ERROR SIMD vector should be homogeneous
 
-#[repr(simd)]
-struct int4(isize, isize, isize, isize); //~ ERROR SIMD vector element type should be machine type
-
 fn main() {}
diff --git a/src/test/ui/simd-type.stderr b/src/test/ui/simd-type.stderr
index 027afcb..48b9916 100644
--- a/src/test/ui/simd-type.stderr
+++ b/src/test/ui/simd-type.stderr
@@ -10,13 +10,7 @@
 LL | struct i64f64(i64, f64);
    | ^^^^^^^^^^^^^^^^^^^^^^^^ SIMD elements must have the same type
 
-error[E0077]: SIMD vector element type should be machine type
-  --> $DIR/simd-type.rs:11:1
-   |
-LL | struct int4(isize, isize, isize, isize);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+error: aborting due to 2 previous errors
 
-error: aborting due to 3 previous errors
-
-Some errors occurred: E0075, E0076, E0077.
+Some errors occurred: E0075, E0076.
 For more information about an error, try `rustc --explain E0075`.
diff --git a/src/test/ui/specialization/specialization-overlap-hygiene.rs b/src/test/ui/specialization/specialization-overlap-hygiene.rs
new file mode 100644
index 0000000..93e7c83
--- /dev/null
+++ b/src/test/ui/specialization/specialization-overlap-hygiene.rs
@@ -0,0 +1,23 @@
+#![feature(decl_macro)]
+
+struct X;
+
+macro_rules! define_f_legacy { () => {
+    fn f() {}
+}}
+macro define_g_modern() {
+    fn g() {}
+}
+
+impl X {
+   fn f() {} //~ ERROR duplicate definitions with name `f`
+   fn g() {} // OK
+}
+impl X {
+    define_f_legacy!();
+}
+impl X {
+    define_g_modern!();
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/specialization-overlap-hygiene.stderr b/src/test/ui/specialization/specialization-overlap-hygiene.stderr
new file mode 100644
index 0000000..6adf16d
--- /dev/null
+++ b/src/test/ui/specialization/specialization-overlap-hygiene.stderr
@@ -0,0 +1,12 @@
+error[E0592]: duplicate definitions with name `f`
+  --> $DIR/specialization-overlap-hygiene.rs:13:4
+   |
+LL |     fn f() {}
+   |     --------- other definition for `f`
+...
+LL |    fn f() {}
+   |    ^^^^^^^^^ duplicate definitions for `f`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0592`.
diff --git a/src/test/ui/substs-ppaux.rs b/src/test/ui/substs-ppaux.rs
index 7ad7ccb..129ebd4 100644
--- a/src/test/ui/substs-ppaux.rs
+++ b/src/test/ui/substs-ppaux.rs
@@ -25,7 +25,7 @@
     let x: () = <i8 as Foo<'static, 'static,  u32>>::bar::<'static, char>;
     //[verbose]~^ ERROR mismatched types
     //[verbose]~| expected type `()`
-    //[verbose]~| found type `fn() {<i8 as Foo<ReStatic, ReStatic, u32>>::bar::<ReStatic, char>}`
+    //[verbose]~| found type `fn() {<i8 as Foo<ReStatic, ReStatic>>::bar::<ReStatic, char>}`
     //[normal]~^^^^ ERROR mismatched types
     //[normal]~| expected type `()`
     //[normal]~| found type `fn() {<i8 as Foo<'static, 'static>>::bar::<'static, char>}`
diff --git a/src/test/ui/substs-ppaux.verbose.stderr b/src/test/ui/substs-ppaux.verbose.stderr
index 9d8a555..8693647 100644
--- a/src/test/ui/substs-ppaux.verbose.stderr
+++ b/src/test/ui/substs-ppaux.verbose.stderr
@@ -14,7 +14,7 @@
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found fn item
    |
    = note: expected type `()`
-              found type `fn() {<i8 as Foo<ReStatic, ReStatic, u32>>::bar::<ReStatic, char>}`
+              found type `fn() {<i8 as Foo<ReStatic, ReStatic>>::bar::<ReStatic, char>}`
 
 error[E0308]: mismatched types
   --> $DIR/substs-ppaux.rs:33:17
diff --git a/src/test/ui/suggestions/return-without-lifetime.rs b/src/test/ui/suggestions/return-without-lifetime.rs
new file mode 100644
index 0000000..9bfce11
--- /dev/null
+++ b/src/test/ui/suggestions/return-without-lifetime.rs
@@ -0,0 +1,10 @@
+struct Thing<'a>(&'a ());
+struct Foo<'a>(&usize);
+//~^ ERROR missing lifetime specifier
+
+fn func1<'a>(_arg: &'a Thing) -> &() { unimplemented!() }
+//~^ ERROR missing lifetime specifier
+fn func2<'a>(_arg: &Thing<'a>) -> &() { unimplemented!() }
+//~^ ERROR missing lifetime specifier
+
+fn main() {}
diff --git a/src/test/ui/suggestions/return-without-lifetime.stderr b/src/test/ui/suggestions/return-without-lifetime.stderr
new file mode 100644
index 0000000..7f5ff95
--- /dev/null
+++ b/src/test/ui/suggestions/return-without-lifetime.stderr
@@ -0,0 +1,25 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/return-without-lifetime.rs:2:16
+   |
+LL | struct Foo<'a>(&usize);
+   |                ^ help: consider using the named lifetime: `&'a`
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/return-without-lifetime.rs:5:34
+   |
+LL | fn func1<'a>(_arg: &'a Thing) -> &() { unimplemented!() }
+   |                                  ^ help: consider using the named lifetime: `&'a`
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say which one of `_arg`'s 2 lifetimes it is borrowed from
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/return-without-lifetime.rs:7:35
+   |
+LL | fn func2<'a>(_arg: &Thing<'a>) -> &() { unimplemented!() }
+   |                                   ^ help: consider using the named lifetime: `&'a`
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say which one of `_arg`'s 2 lifetimes it is borrowed from
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/suggestions/suggest-on-bare-closure-call.rs b/src/test/ui/suggestions/suggest-on-bare-closure-call.rs
new file mode 100644
index 0000000..355708c
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-on-bare-closure-call.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let _ = ||{}();
+    //~^ ERROR expected function, found `()`
+}
diff --git a/src/test/ui/suggestions/suggest-on-bare-closure-call.stderr b/src/test/ui/suggestions/suggest-on-bare-closure-call.stderr
new file mode 100644
index 0000000..17001e3
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-on-bare-closure-call.stderr
@@ -0,0 +1,15 @@
+error[E0618]: expected function, found `()`
+  --> $DIR/suggest-on-bare-closure-call.rs:2:15
+   |
+LL |     let _ = ||{}();
+   |               ^^--
+   |               |
+   |               call expression requires function
+help: if you meant to create this closure and immediately call it, surround the closure with parenthesis
+   |
+LL |     let _ = (||{})();
+   |             ^    ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0618`.
diff --git a/src/test/ui/symbol-names/basic.rs b/src/test/ui/symbol-names/basic.rs
index 2a051a5..086b903 100644
--- a/src/test/ui/symbol-names/basic.rs
+++ b/src/test/ui/symbol-names/basic.rs
@@ -1,6 +1,6 @@
 #![feature(rustc_attrs)]
 
 #[rustc_symbol_name] //~ ERROR _ZN5basic4main
-#[rustc_item_path] //~ ERROR item-path(main)
+#[rustc_def_path] //~ ERROR def-path(main)
 fn main() {
 }
diff --git a/src/test/ui/symbol-names/basic.stderr b/src/test/ui/symbol-names/basic.stderr
index e23a326..6ddd93d 100644
--- a/src/test/ui/symbol-names/basic.stderr
+++ b/src/test/ui/symbol-names/basic.stderr
@@ -4,11 +4,11 @@
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: item-path(main)
+error: def-path(main)
   --> $DIR/basic.rs:4:1
    |
-LL | #[rustc_item_path]
-   | ^^^^^^^^^^^^^^^^^^
+LL | #[rustc_def_path]
+   | ^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/symbol-names/impl1.rs b/src/test/ui/symbol-names/impl1.rs
index 97169c3..c712137 100644
--- a/src/test/ui/symbol-names/impl1.rs
+++ b/src/test/ui/symbol-names/impl1.rs
@@ -6,7 +6,7 @@
 
     impl Foo {
         #[rustc_symbol_name] //~ ERROR _ZN5impl13foo3Foo3bar
-        #[rustc_item_path] //~ ERROR item-path(foo::Foo::bar)
+        #[rustc_def_path] //~ ERROR def-path(foo::Foo::bar)
         fn bar() { }
     }
 }
@@ -16,7 +16,7 @@
 
     impl Foo {
         #[rustc_symbol_name] //~ ERROR _ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz
-        #[rustc_item_path] //~ ERROR item-path(bar::<impl foo::Foo>::baz)
+        #[rustc_def_path] //~ ERROR def-path(bar::<impl foo::Foo>::baz)
         fn baz() { }
     }
 }
diff --git a/src/test/ui/symbol-names/impl1.stderr b/src/test/ui/symbol-names/impl1.stderr
index e4fefeb..eda8646 100644
--- a/src/test/ui/symbol-names/impl1.stderr
+++ b/src/test/ui/symbol-names/impl1.stderr
@@ -4,11 +4,11 @@
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: item-path(foo::Foo::bar)
+error: def-path(foo::Foo::bar)
   --> $DIR/impl1.rs:9:9
    |
-LL |         #[rustc_item_path]
-   |         ^^^^^^^^^^^^^^^^^^
+LL |         #[rustc_def_path]
+   |         ^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz17h38577281258e1527E)
   --> $DIR/impl1.rs:18:9
@@ -16,11 +16,11 @@
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: item-path(bar::<impl foo::Foo>::baz)
+error: def-path(bar::<impl foo::Foo>::baz)
   --> $DIR/impl1.rs:19:9
    |
-LL |         #[rustc_item_path]
-   |         ^^^^^^^^^^^^^^^^^^
+LL |         #[rustc_def_path]
+   |         ^^^^^^^^^^^^^^^^^
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/type_length_limit.rs b/src/test/ui/type_length_limit.rs
index bb54669..cd15f81 100644
--- a/src/test/ui/type_length_limit.rs
+++ b/src/test/ui/type_length_limit.rs
@@ -1,3 +1,5 @@
+// ignore-musl
+// ignore-x86
 // error-pattern: reached the type-length limit while instantiating
 
 // Test that the type length limit can be changed.
diff --git a/src/test/ui/type_length_limit.stderr b/src/test/ui/type_length_limit.stderr
index 910eca0..9d07c86 100644
--- a/src/test/ui/type_length_limit.stderr
+++ b/src/test/ui/type_length_limit.stderr
@@ -1,6 +1,10 @@
-error: reached the type-length limit while instantiating `std::mem::drop::<std::option::Option<((((((G, G, G), (G, G, G), ...`
+error: reached the type-length limit while instantiating `std::mem::drop::<std::option::Op... G), (G, G, G), (G, G, G))))))>>`
+  --> $SRC_DIR/libcore/mem.rs:LL:COL
    |
-   = note: consider adding a `#![type_length_limit="512"]` attribute to your crate
+LL | pub fn drop<T>(_x: T) { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: consider adding a `#![type_length_limit="1094"]` attribute to your crate
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr b/src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr
index f111870..d410861 100644
--- a/src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr
+++ b/src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr
@@ -7,7 +7,7 @@
    |     ^^ expected (), found trait std::iter::Iterator
    |
    = note: expected type `()`
-              found type `(dyn std::iter::Iterator<Item=()> + 'static)`
+              found type `(dyn std::iter::Iterator<Item = ()> + 'static)`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-default.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-default.stderr
index 508c2f7..ce90f5b 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-default.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-default.stderr
@@ -1,8 +1,8 @@
-error[E0277]: the trait bound `dyn Foo<(isize,), isize, Output=()>: Eq<dyn Foo<(isize,), Output=()>>` is not satisfied
+error[E0277]: the trait bound `dyn Foo<(isize,), isize, Output = ()>: Eq<dyn Foo<(isize,), Output = ()>>` is not satisfied
   --> $DIR/unboxed-closure-sugar-default.rs:21:5
    |
 LL |     eq::< Foo<(isize,),isize,Output=()>,      Foo(isize)                      >();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Eq<dyn Foo<(isize,), Output=()>>` is not implemented for `dyn Foo<(isize,), isize, Output=()>`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Eq<dyn Foo<(isize,), Output = ()>>` is not implemented for `dyn Foo<(isize,), isize, Output = ()>`
    |
 note: required by `eq`
   --> $DIR/unboxed-closure-sugar-default.rs:14:1
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-equiv.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-equiv.stderr
index 071ba27..857a32c 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-equiv.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-equiv.stderr
@@ -1,9 +1,9 @@
-error[E0277]: the trait bound `dyn Foo<(char,), Output=()>: Eq<dyn Foo<(), Output=()>>` is not satisfied
+error[E0277]: the trait bound `dyn Foo<(char,), Output = ()>: Eq<dyn Foo<(), Output = ()>>` is not satisfied
   --> $DIR/unboxed-closure-sugar-equiv.rs:43:5
    |
 LL | /     eq::< Foo<(),Output=()>,
 LL | |           Foo(char)                                               >();
-   | |___________________________________________________________________^ the trait `Eq<dyn Foo<(), Output=()>>` is not implemented for `dyn Foo<(char,), Output=()>`
+   | |___________________________________________________________________^ the trait `Eq<dyn Foo<(), Output = ()>>` is not implemented for `dyn Foo<(char,), Output = ()>`
    |
 note: required by `eq`
   --> $DIR/unboxed-closure-sugar-equiv.rs:16:1
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.ast.nll.stderr b/src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.ast.nll.stderr
index 2f83a64..3440ede 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.ast.nll.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.ast.nll.stderr
@@ -10,8 +10,8 @@
 LL |       call(|| {
    |  __________^
 LL | |         counter += 1;
-LL | |         //[ast]~^ ERROR cannot assign to data in a captured outer variable in an `Fn` closure
-LL | |         //[mir]~^^ ERROR cannot assign to `counter`
+LL | |
+LL | |
 LL | |     });
    | |_____^
 
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.ast.stderr b/src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.ast.stderr
index 293f59f..0788350 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.ast.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.ast.stderr
@@ -10,8 +10,8 @@
 LL |       call(|| {
    |  __________^
 LL | |         counter += 1;
-LL | |         //[ast]~^ ERROR cannot assign to data in a captured outer variable in an `Fn` closure
-LL | |         //[mir]~^^ ERROR cannot assign to `counter`
+LL | |
+LL | |
 LL | |     });
    | |_____^
 
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.mir.stderr b/src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.mir.stderr
index 2f83a64..3440ede 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.mir.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.mir.stderr
@@ -10,8 +10,8 @@
 LL |       call(|| {
    |  __________^
 LL | |         counter += 1;
-LL | |         //[ast]~^ ERROR cannot assign to data in a captured outer variable in an `Fn` closure
-LL | |         //[mir]~^^ ERROR cannot assign to `counter`
+LL | |
+LL | |
 LL | |     });
    | |_____^
 
diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
index 69a9fd7..d0475bf 100644
--- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
+++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
@@ -19,8 +19,8 @@
    |              ^^^^^
    = note: but, the lifetime must be valid for the static lifetime...
    = note: ...so that the expression is assignable:
-           expected std::boxed::Box<(dyn std::iter::Iterator<Item=&T> + 'static)>
-              found std::boxed::Box<dyn std::iter::Iterator<Item=&T>>
+           expected std::boxed::Box<(dyn std::iter::Iterator<Item = &T> + 'static)>
+              found std::boxed::Box<dyn std::iter::Iterator<Item = &T>>
 
 error: aborting due to previous error
 
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index d44a51a..706fce2 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -10,7 +10,7 @@
 use std::path::{PathBuf, Path};
 use std::process::{Command, Stdio};
 
-static HOSTS: &'static [&'static str] = &[
+static HOSTS: &[&str] = &[
     "aarch64-unknown-linux-gnu",
     "arm-unknown-linux-gnueabi",
     "arm-unknown-linux-gnueabihf",
@@ -23,6 +23,10 @@
     "mips64-unknown-linux-gnuabi64",
     "mips64el-unknown-linux-gnuabi64",
     "mipsel-unknown-linux-gnu",
+    "mipsisa32r6-unknown-linux-gnu",
+    "mipsisa32r6el-unknown-linux-gnu",
+    "mipsisa64r6-unknown-linux-gnuabi64",
+    "mipsisa64r6el-unknown-linux-gnuabi64",
     "powerpc-unknown-linux-gnu",
     "powerpc64-unknown-linux-gnu",
     "powerpc64le-unknown-linux-gnu",
@@ -32,10 +36,11 @@
     "x86_64-pc-windows-msvc",
     "x86_64-unknown-freebsd",
     "x86_64-unknown-linux-gnu",
+    "x86_64-unknown-linux-musl",
     "x86_64-unknown-netbsd",
 ];
 
-static TARGETS: &'static [&'static str] = &[
+static TARGETS: &[&str] = &[
     "aarch64-apple-ios",
     "aarch64-fuchsia",
     "aarch64-linux-android",
@@ -77,6 +82,10 @@
     "mips-unknown-linux-musl",
     "mips64-unknown-linux-gnuabi64",
     "mips64el-unknown-linux-gnuabi64",
+    "mipsisa32r6-unknown-linux-gnu",
+    "mipsisa32r6el-unknown-linux-gnu",
+    "mipsisa64r6-unknown-linux-gnuabi64",
+    "mipsisa64r6el-unknown-linux-gnuabi64",
     "mipsel-unknown-linux-gnu",
     "mipsel-unknown-linux-musl",
     "nvptx64-nvidia-cuda",
@@ -115,7 +124,7 @@
     "x86_64-unknown-redox",
 ];
 
-static DOCS_TARGETS: &'static [&'static str] = &[
+static DOCS_TARGETS: &[&str] = &[
     "i686-apple-darwin",
     "i686-pc-windows-gnu",
     "i686-pc-windows-msvc",
@@ -126,7 +135,7 @@
     "x86_64-unknown-linux-gnu",
 ];
 
-static MINGW: &'static [&'static str] = &[
+static MINGW: &[&str] = &[
     "i686-pc-windows-gnu",
     "x86_64-pc-windows-gnu",
 ];
@@ -153,7 +162,7 @@
     to: String,
 }
 
-#[derive(Serialize)]
+#[derive(Serialize, Default)]
 struct Target {
     available: bool,
     url: Option<String>,
@@ -165,17 +174,7 @@
 }
 
 impl Target {
-    fn unavailable() -> Target {
-        Target {
-            available: false,
-            url: None,
-            hash: None,
-            xz_url: None,
-            xz_hash: None,
-            components: None,
-            extensions: None,
-        }
-    }
+    fn unavailable() -> Self { Self::default() }
 }
 
 #[derive(Serialize)]
@@ -184,6 +183,12 @@
     target: String,
 }
 
+impl Component {
+    fn from_str(pkg: &str, target: &str) -> Self {
+        Self { pkg: pkg.to_string(), target: target.to_string() }
+    }
+}
+
 macro_rules! t {
     ($e:expr) => (match $e {
         Ok(e) => e,
@@ -301,6 +306,25 @@
     }.build();
 }
 
+enum PkgType { RustSrc, Cargo, Rls, Clippy, Rustfmt, LlvmTools, Lldb, Miri, Other }
+
+impl PkgType {
+    fn from_component(component: &str) -> Self {
+        use PkgType::*;
+        match component {
+            "rust-src" => RustSrc,
+            "cargo" => Cargo,
+            "rls" | "rls-preview" => Rls,
+            "clippy" | "clippy-preview" => Clippy,
+            "rustfmt" | "rustfmt-preview" => Rustfmt,
+            "llvm-tools" | "llvm-tools-preview" => LlvmTools,
+            "lldb" | "lldb-preview" => Lldb,
+            "miri" | "miri-preview" => Miri,
+            _ => Other,
+        }
+    }
+}
+
 impl Builder {
     fn build(&mut self) {
         self.rust_version = self.version("rust", "x86_64-unknown-linux-gnu");
@@ -349,39 +373,56 @@
             renames: BTreeMap::new(),
             profiles: BTreeMap::new(),
         };
+        self.add_packages_to(&mut manifest);
+        self.add_profiles_to(&mut manifest);
+        self.add_renames_to(&mut manifest);
+        manifest.pkg.insert("rust".to_string(), self.rust_package(&manifest));
+        manifest
+    }
 
-        self.package("rustc", &mut manifest.pkg, HOSTS);
-        self.package("cargo", &mut manifest.pkg, HOSTS);
-        self.package("rust-mingw", &mut manifest.pkg, MINGW);
-        self.package("rust-std", &mut manifest.pkg, TARGETS);
-        self.package("rust-docs", &mut manifest.pkg, DOCS_TARGETS);
-        self.package("rust-src", &mut manifest.pkg, &["*"]);
-        self.package("rls-preview", &mut manifest.pkg, HOSTS);
-        self.package("clippy-preview", &mut manifest.pkg, HOSTS);
-        self.package("miri", &mut manifest.pkg, HOSTS);
-        self.package("rustfmt-preview", &mut manifest.pkg, HOSTS);
-        self.package("rust-analysis", &mut manifest.pkg, TARGETS);
-        self.package("llvm-tools-preview", &mut manifest.pkg, TARGETS);
-        self.package("lldb-preview", &mut manifest.pkg, TARGETS);
+    fn add_packages_to(&mut self, manifest: &mut Manifest) {
+        let mut package = |name, targets| self.package(name, &mut manifest.pkg, targets);
+        package("rustc", HOSTS);
+        package("cargo", HOSTS);
+        package("rust-mingw", MINGW);
+        package("rust-std", TARGETS);
+        package("rust-docs", DOCS_TARGETS);
+        package("rust-src", &["*"]);
+        package("rls-preview", HOSTS);
+        package("clippy-preview", HOSTS);
+        package("miri", HOSTS);
+        package("rustfmt-preview", HOSTS);
+        package("rust-analysis", TARGETS);
+        package("llvm-tools-preview", TARGETS);
+        package("lldb-preview", TARGETS);
+    }
 
-        self.profile("minimal",
-                     &mut manifest.profiles,
-                     &["rustc", "cargo", "rust-std", "rust-mingw"]);
-        self.profile("default",
-                     &mut manifest.profiles,
-                     &["rustc", "cargo", "rust-std", "rust-mingw",
-                       "rust-docs", "rustfmt-preview", "clippy-preview"]);
-        self.profile("complete",
-                     &mut manifest.profiles,
-                     &["rustc", "cargo", "rust-std", "rust-mingw",
-                       "rust-docs", "rustfmt-preview", "clippy-preview",
-                       "rls-preview", "rust-src", "llvm-tools-preview",
-                       "lldb-preview", "rust-analysis", "miri"]);
+    fn add_profiles_to(&mut self, manifest: &mut Manifest) {
+        let mut profile = |name, pkgs| self.profile(name, &mut manifest.profiles, pkgs);
+        profile("minimal", &["rustc", "cargo", "rust-std", "rust-mingw"]);
+        profile("default", &[
+            "rustc", "cargo", "rust-std", "rust-mingw",
+            "rust-docs", "rustfmt-preview", "clippy-preview"
+        ]);
+        profile("complete", &[
+            "rustc", "cargo", "rust-std", "rust-mingw",
+            "rust-docs", "rustfmt-preview", "clippy-preview",
+            "rls-preview", "rust-src", "llvm-tools-preview",
+            "lldb-preview", "rust-analysis", "miri"
+        ]);
+    }
 
-        manifest.renames.insert("rls".to_owned(), Rename { to: "rls-preview".to_owned() });
-        manifest.renames.insert("rustfmt".to_owned(), Rename { to: "rustfmt-preview".to_owned() });
-        manifest.renames.insert("clippy".to_owned(), Rename { to: "clippy-preview".to_owned() });
+    fn add_renames_to(&self, manifest: &mut Manifest) {
+        let mut rename = |from: &str, to: &str| manifest.renames.insert(
+            from.to_owned(),
+            Rename { to: to.to_owned() }
+        );
+        rename("rls", "rls-preview");
+        rename("rustfmt", "rustfmt-preview");
+        rename("clippy", "clippy-preview");
+    }
 
+    fn rust_package(&mut self, manifest: &Manifest) -> Package {
         let mut pkg = Package {
             version: self.cached_version("rust")
                          .as_ref()
@@ -391,90 +432,82 @@
             target: BTreeMap::new(),
         };
         for host in HOSTS {
-            let filename = self.filename("rust", host);
-            let digest = match self.digests.remove(&filename) {
-                Some(digest) => digest,
-                None => {
-                    pkg.target.insert(host.to_string(), Target::unavailable());
-                    continue
-                }
-            };
-            let xz_filename = filename.replace(".tar.gz", ".tar.xz");
-            let xz_digest = self.digests.remove(&xz_filename);
-            let mut components = Vec::new();
-            let mut extensions = Vec::new();
-
-            // rustc/rust-std/cargo/docs are all required, and so is rust-mingw
-            // if it's available for the target.
-            components.extend(vec![
-                Component { pkg: "rustc".to_string(), target: host.to_string() },
-                Component { pkg: "rust-std".to_string(), target: host.to_string() },
-                Component { pkg: "cargo".to_string(), target: host.to_string() },
-                Component { pkg: "rust-docs".to_string(), target: host.to_string() },
-            ]);
-            if host.contains("pc-windows-gnu") {
-                components.push(Component {
-                    pkg: "rust-mingw".to_string(),
-                    target: host.to_string(),
-                });
+            if let Some(target) = self.target_host_combination(host, &manifest) {
+                pkg.target.insert(host.to_string(), target);
+            } else {
+                pkg.target.insert(host.to_string(), Target::unavailable());
+                continue
             }
-
-            // Tools are always present in the manifest, but might be marked as unavailable if they
-            // weren't built
-            extensions.extend(vec![
-                Component { pkg: "clippy-preview".to_string(), target: host.to_string() },
-                Component { pkg: "miri".to_string(), target: host.to_string() },
-                Component { pkg: "rls-preview".to_string(), target: host.to_string() },
-                Component { pkg: "rustfmt-preview".to_string(), target: host.to_string() },
-                Component { pkg: "llvm-tools-preview".to_string(), target: host.to_string() },
-                Component { pkg: "lldb-preview".to_string(), target: host.to_string() },
-                Component { pkg: "rust-analysis".to_string(), target: host.to_string() },
-            ]);
-
-            for target in TARGETS {
-                if target != host {
-                    extensions.push(Component {
-                        pkg: "rust-std".to_string(),
-                        target: target.to_string(),
-                    });
-                }
-            }
-            extensions.push(Component {
-                pkg: "rust-src".to_string(),
-                target: "*".to_string(),
-            });
-
-            // If the components/extensions don't actually exist for this
-            // particular host/target combination then nix it entirely from our
-            // lists.
-            {
-                let has_component = |c: &Component| {
-                    if c.target == "*" {
-                        return true
-                    }
-                    let pkg = match manifest.pkg.get(&c.pkg) {
-                        Some(p) => p,
-                        None => return false,
-                    };
-                    pkg.target.get(&c.target).is_some()
-                };
-                extensions.retain(&has_component);
-                components.retain(&has_component);
-            }
-
-            pkg.target.insert(host.to_string(), Target {
-                available: true,
-                url: Some(self.url(&filename)),
-                hash: Some(digest),
-                xz_url: xz_digest.as_ref().map(|_| self.url(&xz_filename)),
-                xz_hash: xz_digest,
-                components: Some(components),
-                extensions: Some(extensions),
-            });
         }
-        manifest.pkg.insert("rust".to_string(), pkg);
+        pkg
+    }
 
-        manifest
+    fn target_host_combination(&mut self, host: &str, manifest: &Manifest) -> Option<Target> {
+        let filename = self.filename("rust", host);
+        let digest = self.digests.remove(&filename)?;
+        let xz_filename = filename.replace(".tar.gz", ".tar.xz");
+        let xz_digest = self.digests.remove(&xz_filename);
+        let mut components = Vec::new();
+        let mut extensions = Vec::new();
+
+        let host_component = |pkg| Component::from_str(pkg, host);
+
+        // rustc/rust-std/cargo/docs are all required,
+        // and so is rust-mingw if it's available for the target.
+        components.extend(vec![
+            host_component("rustc"),
+            host_component("rust-std"),
+            host_component("cargo"),
+            host_component("rust-docs"),
+        ]);
+        if host.contains("pc-windows-gnu") {
+            components.push(host_component("rust-mingw"));
+        }
+
+        // Tools are always present in the manifest,
+        // but might be marked as unavailable if they weren't built.
+        extensions.extend(vec![
+            host_component("clippy-preview"),
+            host_component("miri"),
+            host_component("rls-preview"),
+            host_component("rustfmt-preview"),
+            host_component("llvm-tools-preview"),
+            host_component("lldb-preview"),
+            host_component("rust-analysis"),
+        ]);
+
+        extensions.extend(
+            TARGETS.iter()
+                .filter(|&&target| target != host)
+                .map(|target| Component::from_str("rust-std", target))
+        );
+        extensions.push(Component::from_str("rust-src", "*"));
+
+        // If the components/extensions don't actually exist for this
+        // particular host/target combination then nix it entirely from our
+        // lists.
+        let has_component = |c: &Component| {
+            if c.target == "*" {
+                return true
+            }
+            let pkg = match manifest.pkg.get(&c.pkg) {
+                Some(p) => p,
+                None => return false,
+            };
+            pkg.target.get(&c.target).is_some()
+        };
+        extensions.retain(&has_component);
+        components.retain(&has_component);
+
+        Some(Target {
+            available: true,
+            url: Some(self.url(&filename)),
+            hash: Some(digest),
+            xz_url: xz_digest.as_ref().map(|_| self.url(&xz_filename)),
+            xz_hash: xz_digest,
+            components: Some(components),
+            extensions: Some(extensions),
+        })
     }
 
     fn profile(&mut self,
@@ -488,10 +521,11 @@
                pkgname: &str,
                dst: &mut BTreeMap<String, Package>,
                targets: &[&str]) {
-        let (version, is_present) = match *self.cached_version(pkgname) {
-            Some(ref version) => (version.clone(), true),
-            None => (String::new(), false),
-        };
+        let (version, is_present) = self.cached_version(pkgname)
+            .as_ref()
+            .cloned()
+            .map(|version| (version, true))
+            .unwrap_or_default();
 
         let targets = targets.iter().map(|name| {
             if is_present {
@@ -515,15 +549,7 @@
             } else {
                 // If the component is not present for this build add it anyway but mark it as
                 // unavailable -- this way rustup won't allow upgrades without --force
-                (name.to_string(), Target {
-                    available: false,
-                    url: None,
-                    hash: None,
-                    xz_url: None,
-                    xz_hash: None,
-                    components: None,
-                    extensions: None,
-                })
+                (name.to_string(), Target::unavailable())
             }
         }).collect();
 
@@ -542,89 +568,65 @@
     }
 
     fn filename(&self, component: &str, target: &str) -> String {
-        if component == "rust-src" {
-            format!("rust-src-{}.tar.gz", self.rust_release)
-        } else if component == "cargo" {
-            format!("cargo-{}-{}.tar.gz", self.cargo_release, target)
-        } else if component == "rls" || component == "rls-preview" {
-            format!("rls-{}-{}.tar.gz", self.rls_release, target)
-        } else if component == "clippy" || component == "clippy-preview" {
-            format!("clippy-{}-{}.tar.gz", self.clippy_release, target)
-        } else if component == "rustfmt" || component == "rustfmt-preview" {
-            format!("rustfmt-{}-{}.tar.gz", self.rustfmt_release, target)
-        } else if component == "llvm-tools" || component == "llvm-tools-preview" {
-            format!("llvm-tools-{}-{}.tar.gz", self.llvm_tools_release, target)
-        } else if component == "lldb" || component == "lldb-preview" {
-            format!("lldb-{}-{}.tar.gz", self.lldb_release, target)
-        } else if component == "miri" || component == "miri-preview" {
-            format!("miri-{}-{}.tar.gz", self.miri_release, target)
-        } else {
-            format!("{}-{}-{}.tar.gz", component, self.rust_release, target)
+        use PkgType::*;
+        match PkgType::from_component(component) {
+            RustSrc => format!("rust-src-{}.tar.gz", self.rust_release),
+            Cargo => format!("cargo-{}-{}.tar.gz", self.cargo_release, target),
+            Rls => format!("rls-{}-{}.tar.gz", self.rls_release, target),
+            Clippy => format!("clippy-{}-{}.tar.gz", self.clippy_release, target),
+            Rustfmt => format!("rustfmt-{}-{}.tar.gz", self.rustfmt_release, target),
+            LlvmTools => format!("llvm-tools-{}-{}.tar.gz", self.llvm_tools_release, target),
+            Lldb => format!("lldb-{}-{}.tar.gz", self.lldb_release, target),
+            Miri => format!("miri-{}-{}.tar.gz", self.miri_release, target),
+            Other => format!("{}-{}-{}.tar.gz", component, self.rust_release, target),
         }
     }
 
     fn cached_version(&self, component: &str) -> &Option<String> {
-        if component == "cargo" {
-            &self.cargo_version
-        } else if component == "rls" || component == "rls-preview" {
-            &self.rls_version
-        } else if component == "clippy" || component == "clippy-preview" {
-            &self.clippy_version
-        } else if component == "rustfmt" || component == "rustfmt-preview" {
-            &self.rustfmt_version
-        } else if component == "llvm-tools" || component == "llvm-tools-preview" {
-            &self.llvm_tools_version
-        } else if component == "lldb" || component == "lldb-preview" {
-            &self.lldb_version
-        } else if component == "miri" || component == "miri-preview" {
-            &self.miri_version
-        } else {
-            &self.rust_version
+        use PkgType::*;
+        match PkgType::from_component(component) {
+            Cargo => &self.cargo_version,
+            Rls => &self.rls_version,
+            Clippy => &self.clippy_version,
+            Rustfmt => &self.rustfmt_version,
+            LlvmTools => &self.llvm_tools_version,
+            Lldb => &self.lldb_version,
+            Miri => &self.miri_version,
+            _ => &self.rust_version,
         }
     }
 
     fn cached_git_commit_hash(&self, component: &str) -> &Option<String> {
-        if component == "cargo" {
-            &self.cargo_git_commit_hash
-        } else if component == "rls" || component == "rls-preview" {
-            &self.rls_git_commit_hash
-        } else if component == "clippy" || component == "clippy-preview" {
-            &self.clippy_git_commit_hash
-        } else if component == "rustfmt" || component == "rustfmt-preview" {
-            &self.rustfmt_git_commit_hash
-        } else if component == "llvm-tools" || component == "llvm-tools-preview" {
-            &self.llvm_tools_git_commit_hash
-        } else if component == "lldb" || component == "lldb-preview" {
-            &self.lldb_git_commit_hash
-        } else if component == "miri" || component == "miri-preview" {
-            &self.miri_git_commit_hash
-        } else {
-            &self.rust_git_commit_hash
+        use PkgType::*;
+        match PkgType::from_component(component) {
+            Cargo => &self.cargo_git_commit_hash,
+            Rls => &self.rls_git_commit_hash,
+            Clippy => &self.clippy_git_commit_hash,
+            Rustfmt => &self.rustfmt_git_commit_hash,
+            LlvmTools => &self.llvm_tools_git_commit_hash,
+            Lldb => &self.lldb_git_commit_hash,
+            Miri => &self.miri_git_commit_hash,
+            _ => &self.rust_git_commit_hash,
         }
     }
 
     fn version(&self, component: &str, target: &str) -> Option<String> {
-        let mut cmd = Command::new("tar");
-        let filename = self.filename(component, target);
-        cmd.arg("xf")
-           .arg(self.input.join(&filename))
-           .arg(format!("{}/version", filename.replace(".tar.gz", "")))
-           .arg("-O");
-        let output = t!(cmd.output());
-        if output.status.success() {
-            Some(String::from_utf8_lossy(&output.stdout).trim().to_string())
-        } else {
-            // Perhaps we didn't build this package.
-            None
-        }
+        self.untar(component, target, |filename| format!("{}/version", filename))
     }
 
     fn git_commit_hash(&self, component: &str, target: &str) -> Option<String> {
+        self.untar(component, target, |filename| format!("{}/git-commit-hash", filename))
+    }
+
+    fn untar<F>(&self, component: &str, target: &str, dir: F) -> Option<String>
+    where
+        F: FnOnce(String) -> String
+    {
         let mut cmd = Command::new("tar");
         let filename = self.filename(component, target);
         cmd.arg("xf")
            .arg(self.input.join(&filename))
-           .arg(format!("{}/git-commit-hash", filename.replace(".tar.gz", "")))
+           .arg(dir(filename.replace(".tar.gz", "")))
            .arg("-O");
         let output = t!(cmd.output());
         if output.status.success() {
diff --git a/src/tools/clippy b/src/tools/clippy
index 016d92d..92612c9 160000
--- a/src/tools/clippy
+++ b/src/tools/clippy
@@ -1 +1 @@
-Subproject commit 016d92d6ed5ae8a3785b65aa300768abbc26f818
+Subproject commit 92612c9de159889f77f05855a77482ee1d895f51
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index f0991c8..80b8a8b 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -26,6 +26,7 @@
     Ui,
     JsDocTest,
     MirOpt,
+    Assembly,
 }
 
 impl Mode {
@@ -62,6 +63,7 @@
             "ui" => Ok(Ui),
             "js-doc-test" => Ok(JsDocTest),
             "mir-opt" => Ok(MirOpt),
+            "assembly" => Ok(Assembly),
             _ => Err(()),
         }
     }
@@ -86,6 +88,7 @@
             Ui => "ui",
             JsDocTest => "js-doc-test",
             MirOpt => "mir-opt",
+            Assembly => "assembly",
         };
         fmt::Display::fmt(s, f)
     }
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index c2c4a6b..7bf5670 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -335,6 +335,7 @@
     pub failure_status: i32,
     pub run_rustfix: bool,
     pub rustfix_only_machine_applicable: bool,
+    pub assembly_output: Option<String>,
 }
 
 impl TestProps {
@@ -370,6 +371,7 @@
             failure_status: -1,
             run_rustfix: false,
             rustfix_only_machine_applicable: false,
+            assembly_output: None,
         }
     }
 
@@ -517,6 +519,10 @@
                 self.rustfix_only_machine_applicable =
                     config.parse_rustfix_only_machine_applicable(ln);
             }
+
+            if self.assembly_output.is_none() {
+                self.assembly_output = config.parse_assembly_output(ln);
+            }
         });
 
         if self.failure_status == -1 {
@@ -594,6 +600,7 @@
 
     fn parse_aux_build(&self, line: &str) -> Option<String> {
         self.parse_name_value_directive(line, "aux-build")
+            .map(|r| r.trim().to_string())
     }
 
     fn parse_compile_flags(&self, line: &str) -> Option<String> {
@@ -676,6 +683,11 @@
         self.parse_name_directive(line, "skip-codegen")
     }
 
+    fn parse_assembly_output(&self, line: &str) -> Option<String> {
+        self.parse_name_value_directive(line, "assembly-output")
+            .map(|r| r.trim().to_string())
+    }
+
     fn parse_env(&self, line: &str, name: &str) -> Option<(String, String)> {
         self.parse_name_value_directive(line, name).map(|nv| {
             // nv is either FOO or FOO=BAR
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 84dd671..3e3499e 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -4,7 +4,7 @@
 use crate::common::{Codegen, CodegenUnits, DebugInfoBoth, DebugInfoGdb, DebugInfoLldb, Rustdoc};
 use crate::common::{CompileFail, Pretty, RunFail, RunPass, RunPassValgrind};
 use crate::common::{Config, TestPaths};
-use crate::common::{Incremental, MirOpt, RunMake, Ui, JsDocTest};
+use crate::common::{Incremental, MirOpt, RunMake, Ui, JsDocTest, Assembly};
 use diff;
 use crate::errors::{self, Error, ErrorKind};
 use filetime::FileTime;
@@ -275,6 +275,7 @@
             RunMake => self.run_rmake_test(),
             RunPass | Ui => self.run_ui_test(),
             MirOpt => self.run_mir_opt_test(),
+            Assembly => self.run_assembly_test(),
             JsDocTest => self.run_js_doc_test(),
         }
     }
@@ -1606,6 +1607,7 @@
                 || self.config.target.contains("emscripten")
                 || (self.config.target.contains("musl") && !aux_props.force_host)
                 || self.config.target.contains("wasm32")
+                || self.config.target.contains("nvptx")
             {
                 // We primarily compile all auxiliary libraries as dynamic libraries
                 // to avoid code size bloat and large binaries as much as possible
@@ -1805,7 +1807,7 @@
                 rustc.arg(dir_opt);
             }
             RunFail | RunPassValgrind | Pretty | DebugInfoBoth | DebugInfoGdb | DebugInfoLldb
-            | Codegen | Rustdoc | RunMake | CodegenUnits | JsDocTest => {
+            | Codegen | Rustdoc | RunMake | CodegenUnits | JsDocTest | Assembly => {
                 // do not use JSON output
             }
         }
@@ -2100,12 +2102,37 @@
         self.compose_and_run_compiler(rustc, None)
     }
 
-    fn check_ir_with_filecheck(&self) -> ProcRes {
-        let irfile = self.output_base_name().with_extension("ll");
+    fn compile_test_and_save_assembly(&self) -> (ProcRes, PathBuf) {
+        // This works with both `--emit asm` (as default output name for the assembly)
+        // and `ptx-linker` because the latter can write output at requested location.
+        let output_path = self.output_base_name().with_extension("s");
+
+        let output_file = TargetLocation::ThisFile(output_path.clone());
+        let mut rustc = self.make_compile_args(&self.testpaths.file, output_file);
+
+        rustc.arg("-L").arg(self.aux_output_dir_name());
+
+        match self.props.assembly_output.as_ref().map(AsRef::as_ref) {
+            Some("emit-asm") => {
+                rustc.arg("--emit=asm");
+            }
+
+            Some("ptx-linker") => {
+                // No extra flags needed.
+            }
+
+            Some(_) => self.fatal("unknown 'assembly-output' header"),
+            None => self.fatal("missing 'assembly-output' header"),
+        }
+
+        (self.compose_and_run_compiler(rustc, None), output_path)
+    }
+
+    fn verify_with_filecheck(&self, output: &Path) -> ProcRes {
         let mut filecheck = Command::new(self.config.llvm_filecheck.as_ref().unwrap());
         filecheck
             .arg("--input-file")
-            .arg(irfile)
+            .arg(output)
             .arg(&self.testpaths.file);
         // It would be more appropriate to make most of the arguments configurable through
         // a comment-attribute similar to `compile-flags`. For example, --check-prefixes is a very
@@ -2124,12 +2151,29 @@
             self.fatal("missing --llvm-filecheck");
         }
 
-        let mut proc_res = self.compile_test_and_save_ir();
+        let proc_res = self.compile_test_and_save_ir();
         if !proc_res.status.success() {
             self.fatal_proc_rec("compilation failed!", &proc_res);
         }
 
-        proc_res = self.check_ir_with_filecheck();
+        let output_path = self.output_base_name().with_extension("ll");
+        let proc_res = self.verify_with_filecheck(&output_path);
+        if !proc_res.status.success() {
+            self.fatal_proc_rec("verification with 'FileCheck' failed", &proc_res);
+        }
+    }
+
+    fn run_assembly_test(&self) {
+        if self.config.llvm_filecheck.is_none() {
+            self.fatal("missing --llvm-filecheck");
+        }
+
+        let (proc_res, output_path) = self.compile_test_and_save_assembly();
+        if !proc_res.status.success() {
+            self.fatal_proc_rec("compilation failed!", &proc_res);
+        }
+
+        let proc_res = self.verify_with_filecheck(&output_path);
         if !proc_res.status.success() {
             self.fatal_proc_rec("verification with 'FileCheck' failed", &proc_res);
         }
@@ -3110,7 +3154,7 @@
 
         // Remove test annotations like `//~ ERROR text` from the output,
         // since they duplicate actual errors and make the output hard to read.
-        normalized = Regex::new("\\s*//~.*").unwrap()
+        normalized = Regex::new("\\s*//(\\[.*\\])?~.*").unwrap()
             .replace_all(&normalized, "").into_owned();
 
         for rule in custom_rules {
diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs
index 240287f..50dce4b 100644
--- a/src/tools/compiletest/src/util.rs
+++ b/src/tools/compiletest/src/util.rs
@@ -41,7 +41,6 @@
     ("armv7", "arm"),
     ("armv7s", "arm"),
     ("asmjs", "asmjs"),
-    ("cuda", "cuda"),
     ("hexagon", "hexagon"),
     ("i386", "x86"),
     ("i586", "x86"),
@@ -49,8 +48,17 @@
     ("mips", "mips"),
     ("mips64", "mips64"),
     ("mips64el", "mips64"),
+    ("mipsisa32r6", "mips"),
+    ("mipsisa32r6el", "mips"),
+    ("mipsisa64r6", "mips64"),
+    ("mipsisa64r6el", "mips64"),
     ("mipsel", "mips"),
+    ("mipsisa32r6", "mips"),
+    ("mipsisa32r6el", "mips"),
+    ("mipsisa64r6", "mips64"),
+    ("mipsisa64r6el", "mips64"),
     ("msp430", "msp430"),
+    ("nvptx64", "nvptx64"),
     ("powerpc", "powerpc"),
     ("powerpc64", "powerpc64"),
     ("powerpc64le", "powerpc64"),
@@ -158,7 +166,7 @@
 fn test_get_arch() {
     assert_eq!("x86_64", get_arch("x86_64-unknown-linux-gnu"));
     assert_eq!("x86_64", get_arch("amd64"));
-    assert_eq!("cuda", get_arch("nvptx64-nvidia-cuda"));
+    assert_eq!("nvptx64", get_arch("nvptx64-nvidia-cuda"));
 }
 
 #[test]
diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py
index fb6132a..f2a585e 100755
--- a/src/tools/publish_toolstate.py
+++ b/src/tools/publish_toolstate.py
@@ -12,7 +12,7 @@
 except ImportError:
     import urllib.request as urllib2
 
-# List of people to ping when the status of a tool changed.
+# List of people to ping when the status of a tool or a book changed.
 MAINTAINERS = {
     'miri': '@oli-obk @RalfJung @eddyb',
     'clippy-driver': '@Manishearth @llogiq @mcarton @oli-obk @phansch',
@@ -22,6 +22,10 @@
     'nomicon': '@frewsxcv @Gankro',
     'reference': '@steveklabnik @Havvy @matthewjasper @alercah',
     'rust-by-example': '@steveklabnik @marioidival @projektir',
+    'embedded-book': (
+        '@adamgreig @andre-richter @jamesmunns @korken89 '
+        '@ryankurte @thejpster @therealprof'
+    ),
 }
 
 REPOS = {
@@ -33,6 +37,7 @@
     'nomicon': 'https://github.com/rust-lang-nursery/nomicon',
     'reference': 'https://github.com/rust-lang-nursery/reference',
     'rust-by-example': 'https://github.com/rust-lang/rust-by-example',
+    'embedded-book': 'https://github.com/rust-embedded/book',
 }
 
 
@@ -70,7 +75,7 @@
 
             cc @{}, the PR reviewer, and @rust-lang/compiler -- nominating for prioritization.
 
-            ''').format(relevant_pr_number, tool, REPOS[tool], relevant_pr_user, pr_reviewer),
+            ''').format(relevant_pr_number, tool, REPOS.get(tool), relevant_pr_user, pr_reviewer),
             'title': '`{}` no longer builds after {}'.format(tool, relevant_pr_number),
             'assignees': assignees,
             'labels': ['T-compiler', 'I-nominated'],
@@ -137,7 +142,7 @@
             if build_failed:
                 try:
                     issue(
-                        tool, MAINTAINERS.get(tool),
+                        tool, MAINTAINERS.get(tool, ''),
                         relevant_pr_number, relevant_pr_user, pr_reviewer,
                     )
                 except IOError as e:
diff --git a/src/tools/rls b/src/tools/rls
index 6840dd6..90f7ab0 160000
--- a/src/tools/rls
+++ b/src/tools/rls
@@ -1 +1 @@
-Subproject commit 6840dd69af3ada1f8a432075f1f0be679ea8a468
+Subproject commit 90f7ab070321ebc5ad217dc0d6db163c029dffd9
diff --git a/src/tools/rustfmt b/src/tools/rustfmt
index d6829d6..1427e4c 160000
--- a/src/tools/rustfmt
+++ b/src/tools/rustfmt
@@ -1 +1 @@
-Subproject commit d6829d62dca64dfe7ceaa96d1a9c1cd36428221d
+Subproject commit 1427e4c20ba5cdc80a338347585c9de71a0dea4d