Rollup merge of #59291 - SimonSapin:nonzero-thread-id, r=alexcrichton

Make Option<ThreadId> no larger than ThreadId, with NonZeroU64
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 4951ed5..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)",
@@ -2958,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"
 
@@ -3051,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)",
@@ -3066,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)",
@@ -3115,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"
 
@@ -3217,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]]
@@ -3244,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)",
 ]
@@ -3265,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",
@@ -3416,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)",
 ]
@@ -3427,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)",
@@ -3446,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 = [
@@ -3479,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)",
 ]
@@ -3488,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]]
@@ -3499,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)",
 ]
 
@@ -3533,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)",
 ]
@@ -3614,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)",
@@ -3646,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)",
@@ -3717,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)",
@@ -3833,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]]
@@ -3900,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]]
@@ -3973,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]]
@@ -4108,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"
@@ -4155,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"
@@ -4184,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"
@@ -4210,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"
@@ -4231,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/appveyor.yml b/appveyor.yml
index 2abf723..ab0a29d 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -10,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.
   #
@@ -52,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
@@ -83,8 +84,8 @@
     SCRIPT: python x.py dist
     DIST_REQUIRE_ALL_TOOLS: 1
     DEPLOY: 1
-    CI_JOB_NAME: dist-x86_64-msvc
-  - 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
@@ -92,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
@@ -101,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
@@ -110,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/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 414033a..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,
@@ -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")
                 },
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/test.rs b/src/bootstrap/test.rs
index 8a9d99c..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) {
@@ -936,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,
@@ -1036,7 +1039,7 @@
             || mode == "js-doc-test"
         {
             cmd.arg("--rustdoc-path")
-                .arg(builder.rustdoc(compiler.host));
+                .arg(builder.rustdoc(compiler));
         }
 
         cmd.arg("--src-base")
@@ -1458,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)
@@ -1483,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 865b1f8..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))
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/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/test-various/Dockerfile b/src/ci/docker/test-various/Dockerfile
index 60b431a..611a24a 100644
--- a/src/ci/docker/test-various/Dockerfile
+++ b/src/ci/docker/test-various/Dockerfile
@@ -53,7 +53,8 @@
 
 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 MUSL_TARGETS=x86_64-unknown-linux-musl \
     CC_x86_64_unknown_linux_musl=x86_64-linux-musl-gcc \
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/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 7de94d2..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
 ///     }
 /// }
@@ -691,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/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/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/ops/arith.rs b/src/libcore/ops/arith.rs
index 0252ede..28c9ff9 100644
--- a/src/libcore/ops/arith.rs
+++ b/src/libcore/ops/arith.rs
@@ -1,6 +1,6 @@
 /// The addition operator `+`.
 ///
-/// Note that `RHS` is `Self` by default, but this is not mandatory. For
+/// Note that `Rhs` is `Self` by default, but this is not mandatory. For
 /// example, [`std::time::SystemTime`] implements `Add<Duration>`, which permits
 /// operations of the form `SystemTime = SystemTime + Duration`.
 ///
@@ -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,
 ///         }
@@ -67,18 +67,18 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(
     on(
-        all(_Self="{integer}", RHS="{float}"),
+        all(_Self="{integer}", Rhs="{float}"),
         message="cannot add a float to an integer",
     ),
     on(
-        all(_Self="{float}", RHS="{integer}"),
+        all(_Self="{float}", Rhs="{integer}"),
         message="cannot add an integer to a float",
     ),
-    message="cannot add `{RHS}` to `{Self}`",
-    label="no implementation for `{Self} + {RHS}`",
+    message="cannot add `{Rhs}` to `{Self}`",
+    label="no implementation for `{Self} + {Rhs}`",
 )]
 #[doc(alias = "+")]
-pub trait Add<RHS=Self> {
+pub trait Add<Rhs=Self> {
     /// The resulting type after applying the `+` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
@@ -86,7 +86,7 @@
     /// Performs the `+` operation.
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn add(self, rhs: RHS) -> Self::Output;
+    fn add(self, rhs: Rhs) -> Self::Output;
 }
 
 macro_rules! add_impl {
@@ -108,7 +108,7 @@
 
 /// The subtraction operator `-`.
 ///
-/// Note that `RHS` is `Self` by default, but this is not mandatory. For
+/// Note that `Rhs` is `Self` by default, but this is not mandatory. For
 /// example, [`std::time::SystemTime`] implements `Sub<Duration>`, which permits
 /// operations of the form `SystemTime = SystemTime - Duration`.
 ///
@@ -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,
@@ -173,10 +173,10 @@
 /// ```
 #[lang = "sub"]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented(message="cannot subtract `{RHS}` from `{Self}`",
-                         label="no implementation for `{Self} - {RHS}`")]
+#[rustc_on_unimplemented(message="cannot subtract `{Rhs}` from `{Self}`",
+                         label="no implementation for `{Self} - {Rhs}`")]
 #[doc(alias = "-")]
-pub trait Sub<RHS=Self> {
+pub trait Sub<Rhs=Self> {
     /// The resulting type after applying the `-` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
@@ -184,7 +184,7 @@
     /// Performs the `-` operation.
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn sub(self, rhs: RHS) -> Self::Output;
+    fn sub(self, rhs: Rhs) -> Self::Output;
 }
 
 macro_rules! sub_impl {
@@ -206,7 +206,7 @@
 
 /// The multiplication operator `*`.
 ///
-/// Note that `RHS` is `Self` by default, but this is not mandatory.
+/// Note that `Rhs` is `Self` by default, but this is not mandatory.
 ///
 /// # Examples
 ///
@@ -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() }
 ///     }
 /// }
@@ -293,10 +293,10 @@
 /// ```
 #[lang = "mul"]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented(message="cannot multiply `{RHS}` to `{Self}`",
-                         label="no implementation for `{Self} * {RHS}`")]
+#[rustc_on_unimplemented(message="cannot multiply `{Rhs}` to `{Self}`",
+                         label="no implementation for `{Self} * {Rhs}`")]
 #[doc(alias = "*")]
-pub trait Mul<RHS=Self> {
+pub trait Mul<Rhs=Self> {
     /// The resulting type after applying the `*` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
@@ -304,7 +304,7 @@
     /// Performs the `*` operation.
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn mul(self, rhs: RHS) -> Self::Output;
+    fn mul(self, rhs: Rhs) -> Self::Output;
 }
 
 macro_rules! mul_impl {
@@ -326,7 +326,7 @@
 
 /// The division operator `/`.
 ///
-/// Note that `RHS` is `Self` by default, but this is not mandatory.
+/// Note that `Rhs` is `Self` by default, but this is not mandatory.
 ///
 /// # Examples
 ///
@@ -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() }
 ///     }
 /// }
@@ -417,10 +417,10 @@
 /// ```
 #[lang = "div"]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented(message="cannot divide `{Self}` by `{RHS}`",
-                         label="no implementation for `{Self} / {RHS}`")]
+#[rustc_on_unimplemented(message="cannot divide `{Self}` by `{Rhs}`",
+                         label="no implementation for `{Self} / {Rhs}`")]
 #[doc(alias = "/")]
-pub trait Div<RHS=Self> {
+pub trait Div<Rhs=Self> {
     /// The resulting type after applying the `/` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
@@ -428,7 +428,7 @@
     /// Performs the `/` operation.
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn div(self, rhs: RHS) -> Self::Output;
+    fn div(self, rhs: Rhs) -> Self::Output;
 }
 
 macro_rules! div_impl_integer {
@@ -467,7 +467,7 @@
 
 /// The remainder operator `%`.
 ///
-/// Note that `RHS` is `Self` by default, but this is not mandatory.
+/// Note that `Rhs` is `Self` by default, but this is not mandatory.
 ///
 /// # Examples
 ///
@@ -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;
@@ -502,10 +502,10 @@
 /// ```
 #[lang = "rem"]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented(message="cannot mod `{Self}` by `{RHS}`",
-                         label="no implementation for `{Self} % {RHS}`")]
+#[rustc_on_unimplemented(message="cannot mod `{Self}` by `{Rhs}`",
+                         label="no implementation for `{Self} % {Rhs}`")]
 #[doc(alias = "%")]
-pub trait Rem<RHS=Self> {
+pub trait Rem<Rhs=Self> {
     /// The resulting type after applying the `%` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output = Self;
@@ -513,7 +513,7 @@
     /// Performs the `%` operation.
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn rem(self, rhs: RHS) -> Self::Output;
+    fn rem(self, rhs: Rhs) -> Self::Output;
 }
 
 macro_rules! rem_impl_integer {
@@ -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 2c9bf24..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
@@ -59,7 +59,7 @@
 
 /// The bitwise AND operator `&`.
 ///
-/// Note that `RHS` is `Self` by default, but this is not mandatory.
+/// Note that `Rhs` is `Self` by default, but this is not mandatory.
 ///
 /// # Examples
 ///
@@ -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())
@@ -112,9 +112,9 @@
 #[lang = "bitand"]
 #[doc(alias = "&")]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented(message="no implementation for `{Self} & {RHS}`",
-                         label="no implementation for `{Self} & {RHS}`")]
-pub trait BitAnd<RHS=Self> {
+#[rustc_on_unimplemented(message="no implementation for `{Self} & {Rhs}`",
+                         label="no implementation for `{Self} & {Rhs}`")]
+pub trait BitAnd<Rhs=Self> {
     /// The resulting type after applying the `&` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
@@ -122,7 +122,7 @@
     /// Performs the `&` operation.
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn bitand(self, rhs: RHS) -> Self::Output;
+    fn bitand(self, rhs: Rhs) -> Self::Output;
 }
 
 macro_rules! bitand_impl {
@@ -143,7 +143,7 @@
 
 /// The bitwise OR operator `|`.
 ///
-/// Note that `RHS` is `Self` by default, but this is not mandatory.
+/// Note that `Rhs` is `Self` by default, but this is not mandatory.
 ///
 /// # Examples
 ///
@@ -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())
@@ -196,9 +196,9 @@
 #[lang = "bitor"]
 #[doc(alias = "|")]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented(message="no implementation for `{Self} | {RHS}`",
-                         label="no implementation for `{Self} | {RHS}`")]
-pub trait BitOr<RHS=Self> {
+#[rustc_on_unimplemented(message="no implementation for `{Self} | {Rhs}`",
+                         label="no implementation for `{Self} | {Rhs}`")]
+pub trait BitOr<Rhs=Self> {
     /// The resulting type after applying the `|` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
@@ -206,7 +206,7 @@
     /// Performs the `|` operation.
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn bitor(self, rhs: RHS) -> Self::Output;
+    fn bitor(self, rhs: Rhs) -> Self::Output;
 }
 
 macro_rules! bitor_impl {
@@ -227,7 +227,7 @@
 
 /// The bitwise XOR operator `^`.
 ///
-/// Note that `RHS` is `Self` by default, but this is not mandatory.
+/// Note that `Rhs` is `Self` by default, but this is not mandatory.
 ///
 /// # Examples
 ///
@@ -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()
@@ -283,9 +283,9 @@
 #[lang = "bitxor"]
 #[doc(alias = "^")]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented(message="no implementation for `{Self} ^ {RHS}`",
-                         label="no implementation for `{Self} ^ {RHS}`")]
-pub trait BitXor<RHS=Self> {
+#[rustc_on_unimplemented(message="no implementation for `{Self} ^ {Rhs}`",
+                         label="no implementation for `{Self} ^ {Rhs}`")]
+pub trait BitXor<Rhs=Self> {
     /// The resulting type after applying the `^` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
@@ -293,7 +293,7 @@
     /// Performs the `^` operation.
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn bitxor(self, rhs: RHS) -> Self::Output;
+    fn bitxor(self, rhs: Rhs) -> Self::Output;
 }
 
 macro_rules! bitxor_impl {
@@ -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![];
@@ -371,9 +371,9 @@
 #[lang = "shl"]
 #[doc(alias = "<<")]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented(message="no implementation for `{Self} << {RHS}`",
-                         label="no implementation for `{Self} << {RHS}`")]
-pub trait Shl<RHS=Self> {
+#[rustc_on_unimplemented(message="no implementation for `{Self} << {Rhs}`",
+                         label="no implementation for `{Self} << {Rhs}`")]
+pub trait Shl<Rhs=Self> {
     /// The resulting type after applying the `<<` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
@@ -381,7 +381,7 @@
     /// Performs the `<<` operation.
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn shl(self, rhs: RHS) -> Self::Output;
+    fn shl(self, rhs: Rhs) -> Self::Output;
 }
 
 macro_rules! shl_impl {
@@ -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![];
@@ -480,9 +480,9 @@
 #[lang = "shr"]
 #[doc(alias = ">>")]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented(message="no implementation for `{Self} >> {RHS}`",
-                         label="no implementation for `{Self} >> {RHS}`")]
-pub trait Shr<RHS=Self> {
+#[rustc_on_unimplemented(message="no implementation for `{Self} >> {Rhs}`",
+                         label="no implementation for `{Self} >> {Rhs}`")]
+pub trait Shr<Rhs=Self> {
     /// The resulting type after applying the `>>` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
@@ -490,7 +490,7 @@
     /// Performs the `>>` operation.
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn shr(self, rhs: RHS) -> Self::Output;
+    fn shr(self, rhs: Rhs) -> Self::Output;
 }
 
 macro_rules! shr_impl {
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/pin.rs b/src/libcore/pin.rs
index cf55b6c..57bd3ed 100644
--- a/src/libcore/pin.rs
+++ b/src/libcore/pin.rs
@@ -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/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/lib.rs b/src/libcore/tests/lib.rs
index a50310e..08dda4b 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -16,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/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index eb75e62..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;
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/lowering.rs b/src/librustc/hir/lowering.rs
index 949fdd2..73c3b30 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -2672,7 +2672,7 @@
 
     fn lower_variant_data(&mut self, vdata: &VariantData) -> hir::VariantData {
         match *vdata {
-            VariantData::Struct(ref fields, id) => {
+            VariantData::Struct(ref fields, id, recovered) => {
                 let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(id);
 
                 hir::VariantData::Struct(
@@ -2682,6 +2682,7 @@
                         .map(|f| self.lower_struct_field(f))
                         .collect(),
                     hir_id,
+                    recovered,
                 )
             },
             VariantData::Tuple(ref fields, id) => {
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 88ab58d..5edddb3 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -816,6 +816,9 @@
     pub legacy: bool,
 }
 
+/// A block of statements `{ .. }`, which may have a label (in this case the
+/// `targeted_by_break` field will be `true`) and may be `unsafe` by means of
+/// the `rules` being anything but `DefaultBlock`.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct Block {
     /// Statements in a block.
@@ -1178,6 +1181,7 @@
     }
 }
 
+/// The contents of a statement.
 #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
 pub enum StmtKind {
     /// A local (`let`) binding.
@@ -1208,21 +1212,28 @@
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct Local {
     pub pat: P<Pat>,
+    /// Type annotation, if any (otherwise the type will be inferred).
     pub ty: Option<P<Ty>>,
     /// Initializer expression to set the value, if any.
     pub init: Option<P<Expr>>,
     pub hir_id: HirId,
     pub span: Span,
     pub attrs: ThinVec<Attribute>,
+    /// Can be `ForLoopDesugar` if the `let` statement is part of a `for` loop
+    /// desugaring. Otherwise will be `Normal`.
     pub source: LocalSource,
 }
 
-/// Represents a single arm of a `match` expression.
+/// Represents a single arm of a `match` expression, e.g.
+/// `<pats> (if <guard>) => <body>`.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct Arm {
     pub attrs: HirVec<Attribute>,
+    /// Multiple patterns can be combined with `|`
     pub pats: HirVec<P<Pat>>,
+    /// Optional guard clause.
     pub guard: Option<Guard>,
+    /// The expression the arm evaluates to if this arm matches.
     pub body: P<Expr>,
 }
 
@@ -2173,7 +2184,7 @@
 /// Id of the whole struct lives in `Item`.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub enum VariantData {
-    Struct(HirVec<StructField>, HirId),
+    Struct(HirVec<StructField>, HirId, /* recovered */ bool),
     Tuple(HirVec<StructField>, HirId),
     Unit(HirId),
 }
@@ -2187,7 +2198,7 @@
     }
     pub fn hir_id(&self) -> HirId {
         match *self {
-            VariantData::Struct(_, hir_id)
+            VariantData::Struct(_, hir_id, _)
             | VariantData::Tuple(_, hir_id)
             | VariantData::Unit(hir_id) => hir_id,
         }
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/lib.rs b/src/librustc/lib.rs
index b667732..4b2fda3 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -60,6 +60,8 @@
 #![feature(test)]
 #![feature(in_band_lifetimes)]
 #![feature(crate_visibility_modifier)]
+#![feature(proc_macro_hygiene)]
+#![feature(log_syntax)]
 
 #![recursion_limit="512"]
 
@@ -69,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;
@@ -96,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;
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/ty/mod.rs b/src/librustc/ty/mod.rs
index 298af1d..91b84b6 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -1811,6 +1811,7 @@
     pub fields: Vec<FieldDef>,
     pub ctor_kind: CtorKind,
     flags: VariantFlags,
+    pub recovered: bool,
 }
 
 impl<'a, 'gcx, 'tcx> VariantDef {
@@ -1829,16 +1830,17 @@
     ///
     /// If someone speeds up attribute loading to not be a performance concern, they can
     /// remove this hack and use the constructor `DefId` everywhere.
-    pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
-               did: DefId,
-               ident: Ident,
-               discr: VariantDiscr,
-               fields: Vec<FieldDef>,
-               adt_kind: AdtKind,
-               ctor_kind: CtorKind,
-               attribute_def_id: DefId)
-               -> Self
-    {
+    pub fn new(
+        tcx: TyCtxt<'a, 'gcx, 'tcx>,
+        did: DefId,
+        ident: Ident,
+        discr: VariantDiscr,
+        fields: Vec<FieldDef>,
+        adt_kind: AdtKind,
+        ctor_kind: CtorKind,
+        attribute_def_id: DefId,
+        recovered: bool,
+    ) -> Self {
         debug!("VariantDef::new({:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?})", did, ident, discr,
                fields, adt_kind, ctor_kind, attribute_def_id);
         let mut flags = VariantFlags::NO_VARIANT_FLAGS;
@@ -1852,7 +1854,8 @@
             discr,
             fields,
             ctor_kind,
-            flags
+            flags,
+            recovered,
         }
     }
 
@@ -1868,7 +1871,8 @@
     discr,
     fields,
     ctor_kind,
-    flags
+    flags,
+    recovered
 });
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs
index 395b288..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]
@@ -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()
@@ -949,21 +937,6 @@
     }
 }
 
-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))
-    }
-}
-
 impl<'tcx> QueryDescription<'tcx> for queries::program_clauses_for<'tcx> {
     fn describe(_tcx: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> {
         "generating chalk-style clauses".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 cff99f2..e82e09c 100644
--- a/src/librustc/ty/query/plumbing.rs
+++ b/src/librustc/ty/query/plumbing.rs
@@ -1131,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:
@@ -1171,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 |
@@ -1274,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!()); }
@@ -1332,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!()); }
@@ -1349,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!()); }
@@ -1432,7 +1438,7 @@
         DepKind::BackendOptimizationLevel => {
             force!(backend_optimization_level, krate!());
         }
-    }
+    );
 
     true
 }
@@ -1493,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_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs
index 5551cf6..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>;
 
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/decoder.rs b/src/librustc_metadata/decoder.rs
index 6fe00a4..c608c03 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -576,7 +576,8 @@
             }).collect(),
             adt_kind,
             data.ctor_kind,
-            attribute_def_id
+            attribute_def_id,
+            false,
         )
     }
 
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 8078699..314c95a 100644
--- a/src/librustc_metadata/native_libs.rs
+++ b/src/librustc_metadata/native_libs.rs
@@ -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/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index 33645b5..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,
@@ -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);
 
@@ -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/util/pretty.rs b/src/librustc_mir/util/pretty.rs
index 4663f90..13bcdc2 100644
--- a/src/librustc_mir/util/pretty.rs
+++ b/src/librustc_mir/util/pretty.rs
@@ -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 {
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 3fea515..01bb643 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -481,8 +481,8 @@
         };
 
         let (value, fields) = match item.node {
-            ast::ItemKind::Struct(ast::VariantData::Struct(ref fields, _), _) |
-            ast::ItemKind::Union(ast::VariantData::Struct(ref fields, _), _) => {
+            ast::ItemKind::Struct(ast::VariantData::Struct(ref fields, ..), _) |
+            ast::ItemKind::Union(ast::VariantData::Struct(ref fields, ..), _) => {
                 let include_priv_fields = !self.save_ctxt.config.pub_only;
                 let fields_str = fields
                     .iter()
@@ -560,7 +560,7 @@
             let name_span = variant.node.ident.span;
 
             match variant.node.data {
-                ast::VariantData::Struct(ref fields, _) => {
+                ast::VariantData::Struct(ref fields, ..) => {
                     let fields_str = fields
                         .iter()
                         .enumerate()
diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs
index 64a2c92..6e47ae6 100644
--- a/src/librustc_save_analysis/sig.rs
+++ b/src/librustc_save_analysis/sig.rs
@@ -703,7 +703,7 @@
     fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
         let mut text = self.ident.to_string();
         match self.data {
-            ast::VariantData::Struct(ref fields, id) => {
+            ast::VariantData::Struct(ref fields, id, r) => {
                 let name_def = SigElement {
                     id: id_from_node_id(id, scx),
                     start: offset,
@@ -712,12 +712,16 @@
                 text.push_str(" { ");
                 let mut defs = vec![name_def];
                 let mut refs = vec![];
-                for f in fields {
-                    let field_sig = f.make(offset + text.len(), Some(id), scx)?;
-                    text.push_str(&field_sig.text);
-                    text.push_str(", ");
-                    defs.extend(field_sig.defs.into_iter());
-                    refs.extend(field_sig.refs.into_iter());
+                if r {
+                    text.push_str("/* parse error */ ");
+                } else {
+                    for f in fields {
+                        let field_sig = f.make(offset + text.len(), Some(id), scx)?;
+                        text.push_str(&field_sig.text);
+                        text.push_str(", ");
+                        defs.extend(field_sig.defs.into_iter());
+                        refs.extend(field_sig.refs.into_iter());
+                    }
                 }
                 text.push('}');
                 Ok(Signature { text, defs, refs })
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index c6b6639..c30b9d6 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -918,14 +918,16 @@
         pat_ty
     }
 
-    fn check_struct_pat_fields(&self,
-                               adt_ty: Ty<'tcx>,
-                               pat_id: hir::HirId,
-                               span: Span,
-                               variant: &'tcx ty::VariantDef,
-                               fields: &'gcx [Spanned<hir::FieldPat>],
-                               etc: bool,
-                               def_bm: ty::BindingMode) -> bool {
+    fn check_struct_pat_fields(
+        &self,
+        adt_ty: Ty<'tcx>,
+        pat_id: hir::HirId,
+        span: Span,
+        variant: &'tcx ty::VariantDef,
+        fields: &'gcx [Spanned<hir::FieldPat>],
+        etc: bool,
+        def_bm: ty::BindingMode,
+    ) -> bool {
         let tcx = self.tcx;
 
         let (substs, adt) = match adt_ty.sty {
@@ -985,7 +987,7 @@
                 .map(|field| field.ident.modern())
                 .filter(|ident| !used_fields.contains_key(&ident))
                 .collect::<Vec<_>>();
-        if inexistent_fields.len() > 0 {
+        if inexistent_fields.len() > 0 && !variant.recovered {
             let (field_names, t, plural) = if inexistent_fields.len() == 1 {
                 (format!("a field named `{}`", inexistent_fields[0].1), "this", "")
             } else {
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/mod.rs b/src/librustc_typeck/check/mod.rs
index ba6894b..ab0e4b0 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -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,
@@ -3689,12 +3734,17 @@
                            field, expr_t)
     }
 
-    fn report_unknown_field(&self,
-                            ty: Ty<'tcx>,
-                            variant: &'tcx ty::VariantDef,
-                            field: &hir::Field,
-                            skip_fields: &[hir::Field],
-                            kind_name: &str) {
+    fn report_unknown_field(
+        &self,
+        ty: Ty<'tcx>,
+        variant: &'tcx ty::VariantDef,
+        field: &hir::Field,
+        skip_fields: &[hir::Field],
+        kind_name: &str,
+    ) {
+        if variant.recovered {
+            return;
+        }
         let mut err = self.type_error_struct_with_diag(
             field.ident.span,
             |actual| match ty.sty {
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/collect.rs b/src/librustc_typeck/collect.rs
index 10e9613..c0739db 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -598,6 +598,10 @@
             }
         })
         .collect();
+    let recovered = match def {
+        hir::VariantData::Struct(_, _, r) => *r,
+        _ => false,
+    };
     ty::VariantDef::new(tcx,
         did,
         ident,
@@ -605,7 +609,8 @@
         fields,
         adt_kind,
         CtorKind::from_hir(def),
-        attribute_def_id
+        attribute_def_id,
+        recovered,
     )
 }
 
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/mod.rs b/src/librustdoc/clean/mod.rs
index c51c802..ba44817 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -17,11 +17,11 @@
 use rustc::middle::lang_items;
 use rustc::middle::stability;
 use rustc::mir::interpret::{GlobalId, ConstValue};
-use rustc::hir::{self, GenericArg, HirVec};
+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::hir::map::DisambiguatedDefPathData;
-use rustc::ty::subst::{Kind, InternalSubsts, SubstsRef};
+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;
@@ -508,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)]
@@ -1045,7 +1057,7 @@
         GenericBound::TraitBound(PolyTrait {
             trait_: ResolvedPath {
                 path,
-                typarams: None,
+                param_names: None,
                 did,
                 is_generic: false,
             },
@@ -1089,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
@@ -1114,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 }
         }
     }
 }
@@ -1176,7 +1194,7 @@
             PolyTrait {
                 trait_: ResolvedPath {
                     path,
-                    typarams: None,
+                    param_names: None,
                     did: trait_ref.def_id,
                     is_generic: false,
                 },
@@ -1462,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))
@@ -1484,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),
+                })
             }
         };
 
@@ -1685,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),
@@ -1700,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))
@@ -1711,6 +1732,7 @@
             decl,
             generics,
             header: self.0.header,
+            defaultness: self.3,
         }
     }
 }
@@ -2016,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, || {
@@ -2054,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),
@@ -2137,7 +2159,8 @@
                             abi: sig.abi(),
                             constness,
                             asyncness: hir::IsAsync::NotAsync,
-                        }
+                        },
+                        defaultness: Some(self.defaultness),
                     })
                 } else {
                     TyMethodItem(TyMethod {
@@ -2244,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,
@@ -2365,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
                     }
@@ -2706,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)
@@ -2714,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
                 }
@@ -2781,7 +2807,7 @@
                                          None, false, vec![], substs);
                 ResolvedPath {
                     path,
-                    typarams: None,
+                    param_names: None,
                     did,
                     is_generic: false,
                 }
@@ -2792,7 +2818,7 @@
                                          None, false, vec![], InternalSubsts::empty());
                 ResolvedPath {
                     path: path,
-                    typarams: None,
+                    param_names: None,
                     did: did,
                     is_generic: false,
                 }
@@ -2813,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(),
@@ -2823,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![];
@@ -2844,7 +2870,7 @@
                     false, bindings, substs);
                 ResolvedPath {
                     path,
-                    typarams: Some(typarams),
+                    param_names: Some(param_names),
                     did,
                     is_generic: false,
                 }
@@ -2921,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);
@@ -3229,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 {
@@ -3250,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),
             }
         }
@@ -3294,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())
@@ -3322,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();
@@ -3475,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,
@@ -3955,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 {
@@ -4381,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 dca6458..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,
+                    }))
                 }
             }
         }
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 b3a816d..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>,
@@ -601,7 +601,7 @@
     let RenderInfo {
         inlined: _,
         external_paths,
-        external_typarams,
+        external_param_names,
         exact_paths,
         access_levels,
         deref_trait_did,
@@ -635,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(),
     };
 
@@ -1751,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());
                 }
             }
         }
@@ -3429,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
@@ -3445,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,
diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs
index a2b12d0..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]
diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs
index be5cd92..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]
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 1a2152a..4c88fc8 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -1345,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.
@@ -2173,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)]
@@ -2396,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 fc8ac9a..296c4c8 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -301,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)]
@@ -323,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/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/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/net.rs b/src/libstd/sys/sgx/net.rs
index e167e91..81f33c1 100644
--- a/src/libstd/sys/sgx/net.rs
+++ b/src/libstd/sys/sgx/net.rs
@@ -249,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/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/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_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/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 1a0da73..2cbd2df 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -620,7 +620,7 @@
 
     /// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`).
     /// The `bool` is `true` in the presence of a `..`.
-    Struct(Path, Vec<Spanned<FieldPat>>, bool),
+    Struct(Path, Vec<Spanned<FieldPat>>, /* recovered */ bool),
 
     /// A tuple struct/variant pattern (`Variant(x, y, .., z)`).
     /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
@@ -2133,7 +2133,7 @@
     /// Struct variant.
     ///
     /// E.g., `Bar { .. }` as in `enum Foo { Bar { .. } }`.
-    Struct(Vec<StructField>, NodeId),
+    Struct(Vec<StructField>, NodeId, bool),
     /// Tuple variant.
     ///
     /// E.g., `Bar(..)` as in `enum Foo { Bar(..) }`.
@@ -2147,13 +2147,13 @@
 impl VariantData {
     pub fn fields(&self) -> &[StructField] {
         match *self {
-            VariantData::Struct(ref fields, _) | VariantData::Tuple(ref fields, _) => fields,
+            VariantData::Struct(ref fields, ..) | VariantData::Tuple(ref fields, _) => fields,
             _ => &[],
         }
     }
     pub fn id(&self) -> NodeId {
         match *self {
-            VariantData::Struct(_, id) | VariantData::Tuple(_, id) | VariantData::Unit(id) => id,
+            VariantData::Struct(_, id, _) | VariantData::Tuple(_, id) | VariantData::Unit(id) => id,
         }
     }
     pub fn is_struct(&self) -> bool {
diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs
index c300ffc..7159c94 100644
--- a/src/libsyntax/config.rs
+++ b/src/libsyntax/config.rs
@@ -225,7 +225,7 @@
 
     fn configure_variant_data(&mut self, vdata: &mut ast::VariantData) {
         match vdata {
-            ast::VariantData::Struct(fields, _id) |
+            ast::VariantData::Struct(fields, _id, _) |
             ast::VariantData::Tuple(fields, _id) =>
                 fields.flat_map_in_place(|field| self.configure(field)),
             ast::VariantData::Unit(_id) => {}
diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs
index 462346d..5bb1d8a 100644
--- a/src/libsyntax/mut_visit.rs
+++ b/src/libsyntax/mut_visit.rs
@@ -765,7 +765,7 @@
 
 pub fn noop_visit_variant_data<T: MutVisitor>(vdata: &mut VariantData, vis: &mut T) {
     match vdata {
-        VariantData::Struct(fields, id) |
+        VariantData::Struct(fields, id, _) |
         VariantData::Tuple(fields, id) => {
             visit_vec(fields, |field| vis.visit_struct_field(field));
             vis.visit_id(id);
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 3e00d94..648ee77 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1524,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() {
@@ -6837,14 +6837,16 @@
                 VariantData::Unit(ast::DUMMY_NODE_ID)
             } else {
                 // If we see: `struct Foo<T> where T: Copy { ... }`
-                VariantData::Struct(self.parse_record_struct_body()?, ast::DUMMY_NODE_ID)
+                let (fields, recovered) = self.parse_record_struct_body()?;
+                VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered)
             }
         // No `where` so: `struct Foo<T>;`
         } else if self.eat(&token::Semi) {
             VariantData::Unit(ast::DUMMY_NODE_ID)
         // Record-style struct definition
         } else if self.token == token::OpenDelim(token::Brace) {
-            VariantData::Struct(self.parse_record_struct_body()?, ast::DUMMY_NODE_ID)
+            let (fields, recovered) = self.parse_record_struct_body()?;
+            VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered)
         // Tuple-style struct definition with optional where-clause.
         } else if self.token == token::OpenDelim(token::Paren) {
             let body = VariantData::Tuple(self.parse_tuple_struct_body()?, ast::DUMMY_NODE_ID);
@@ -6872,9 +6874,11 @@
 
         let vdata = if self.token.is_keyword(keywords::Where) {
             generics.where_clause = self.parse_where_clause()?;
-            VariantData::Struct(self.parse_record_struct_body()?, ast::DUMMY_NODE_ID)
+            let (fields, recovered) = self.parse_record_struct_body()?;
+            VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered)
         } else if self.token == token::OpenDelim(token::Brace) {
-            VariantData::Struct(self.parse_record_struct_body()?, ast::DUMMY_NODE_ID)
+            let (fields, recovered) = self.parse_record_struct_body()?;
+            VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered)
         } else {
             let token_str = self.this_token_descr();
             let mut err = self.fatal(&format!(
@@ -6906,12 +6910,16 @@
         }
     }
 
-    fn parse_record_struct_body(&mut self) -> PResult<'a, Vec<StructField>> {
+    fn parse_record_struct_body(
+        &mut self,
+    ) -> PResult<'a, (Vec<StructField>, /* recovered */ bool)> {
         let mut fields = Vec::new();
+        let mut recovered = false;
         if self.eat(&token::OpenDelim(token::Brace)) {
             while self.token != token::CloseDelim(token::Brace) {
                 let field = self.parse_struct_decl_field().map_err(|e| {
                     self.recover_stmt();
+                    recovered = true;
                     e
                 });
                 match field {
@@ -6930,7 +6938,7 @@
             return Err(err);
         }
 
-        Ok(fields)
+        Ok((fields, recovered))
     }
 
     fn parse_tuple_struct_body(&mut self) -> PResult<'a, Vec<StructField>> {
@@ -7688,16 +7696,19 @@
 
             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.
                 all_nullary = false;
-                struct_def = VariantData::Struct(self.parse_record_struct_body()?,
-                                                 ast::DUMMY_NODE_ID);
+                let (fields, recovered) = self.parse_record_struct_body()?;
+                struct_def = VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered);
             } else if self.check(&token::OpenDelim(token::Paren)) {
                 all_nullary = false;
-                struct_def = VariantData::Tuple(self.parse_tuple_struct_body()?,
-                                                ast::DUMMY_NODE_ID);
+                struct_def = VariantData::Tuple(
+                    self.parse_tuple_struct_body()?,
+                    ast::DUMMY_NODE_ID,
+                );
             } else if self.eat(&token::Eq) {
                 disr_expr = Some(AnonConst {
                     id: ast::DUMMY_NODE_ID,
@@ -7719,11 +7730,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",
             );
@@ -8608,6 +8633,21 @@
             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 e04e127..07df14d 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -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/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/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/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 3ce43cc..c771013 100644
--- a/src/test/mir-opt/basic_assignment.rs
+++ b/src/test/mir-opt/basic_assignment.rs
@@ -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-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 9eeef85..0cbf048 100644
--- a/src/test/mir-opt/match_false_edges.rs
+++ b/src/test/mir-opt/match_false_edges.rs
@@ -47,7 +47,7 @@
 //      _3 = discriminant(_2);
 //      switchInt(move _3) -> [0isize: bb4, 1isize: bb2, otherwise: bb7];
 //  }
-//  bb1: {
+//  bb1 (cleanup): {
 //      resume;
 //  }
 //  bb2: {
@@ -116,7 +116,7 @@
 //      _3 = discriminant(_2);
 //      switchInt(move _3) -> [0isize: bb3, 1isize: bb2, otherwise: bb7];
 //  }
-//  bb1: {
+//  bb1 (cleanup): {
 //      resume;
 //  }
 //  bb2: {
@@ -185,7 +185,7 @@
 //      _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/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/unusual-item-types.rs b/src/test/mir-opt/unusual-item-types.rs
index ced3038..ef41373 100644
--- a/src/test/mir-opt/unusual-item-types.rs
+++ b/src/test/mir-opt/unusual-item-types.rs
@@ -29,7 +29,7 @@
 //     _0 = const 2i32;
 //     return;
 // }
-// bb1: {
+// bb1 (cleanup): {
 //     resume;
 // }
 // END rustc.{{impl}}-ASSOCIATED_CONSTANT.mir_map.0.mir
@@ -39,7 +39,7 @@
 //     _0 = const 5isize;
 //     return;
 // }
-// bb1: {
+// bb1 (cleanup): {
 //     resume;
 // }
 // END rustc.E-V-{{constant}}.mir_map.0.mir
@@ -51,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: {
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/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/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/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/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/issues/issue-21950.stderr b/src/test/ui/issues/issue-21950.stderr
index 5f401d1..bda2e3c 100644
--- a/src/test/ui/issues/issue-21950.stderr
+++ b/src/test/ui/issues/issue-21950.stderr
@@ -1,8 +1,8 @@
-error[E0393]: the type parameter `RHS` must be explicitly specified
+error[E0393]: the type parameter `Rhs` must be explicitly specified
   --> $DIR/issue-21950.rs:7:14
    |
 LL |             &Add;
-   |              ^^^ missing reference to `RHS`
+   |              ^^^ missing reference to `Rhs`
    |
    = note: because of the default `Self` reference, type parameters must be specified on object types
 
diff --git a/src/test/ui/issues/issue-22560.stderr b/src/test/ui/issues/issue-22560.stderr
index be4f3dd..694a4af 100644
--- a/src/test/ui/issues/issue-22560.stderr
+++ b/src/test/ui/issues/issue-22560.stderr
@@ -1,16 +1,16 @@
-error[E0393]: the type parameter `RHS` must be explicitly specified
+error[E0393]: the type parameter `Rhs` must be explicitly specified
   --> $DIR/issue-22560.rs:5:13
    |
 LL | type Test = Add +
-   |             ^^^ missing reference to `RHS`
+   |             ^^^ missing reference to `Rhs`
    |
    = note: because of the default `Self` reference, type parameters must be specified on object types
 
-error[E0393]: the type parameter `RHS` must be explicitly specified
+error[E0393]: the type parameter `Rhs` must be explicitly specified
   --> $DIR/issue-22560.rs:8:13
    |
 LL |             Sub;
-   |             ^^^ missing reference to `RHS`
+   |             ^^^ missing reference to `Rhs`
    |
    = note: because of the default `Self` reference, type parameters must be specified on object types
 
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-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-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/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/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/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/recovered-struct-variant.rs b/src/test/ui/parser/recovered-struct-variant.rs
new file mode 100644
index 0000000..5b195dc
--- /dev/null
+++ b/src/test/ui/parser/recovered-struct-variant.rs
@@ -0,0 +1,13 @@
+enum Foo {
+    A { a, b: usize }
+    //~^ ERROR expected `:`, found `,`
+}
+
+fn main() {
+    // no complaints about non-existing fields
+    let f = Foo::A { a:3, b: 4};
+    match f {
+        // no complaints about non-existing fields
+        Foo::A {a, b} => {}
+    }
+}
diff --git a/src/test/ui/parser/recovered-struct-variant.stderr b/src/test/ui/parser/recovered-struct-variant.stderr
new file mode 100644
index 0000000..51aaf8b
--- /dev/null
+++ b/src/test/ui/parser/recovered-struct-variant.stderr
@@ -0,0 +1,8 @@
+error: expected `:`, found `,`
+  --> $DIR/recovered-struct-variant.rs:2:10
+   |
+LL |     A { a, b: usize }
+   |          ^ expected `:`
+
+error: aborting due to previous error
+
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/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/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/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/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index 058f2df..3c360a8 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",
@@ -40,7 +40,7 @@
     "x86_64-unknown-netbsd",
 ];
 
-static TARGETS: &'static [&'static str] = &[
+static TARGETS: &[&str] = &[
     "aarch64-apple-ios",
     "aarch64-fuchsia",
     "aarch64-linux-android",
@@ -124,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",
@@ -135,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",
 ];
@@ -162,7 +162,7 @@
     to: String,
 }
 
-#[derive(Serialize)]
+#[derive(Serialize, Default)]
 struct Target {
     available: bool,
     url: Option<String>,
@@ -174,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)]
@@ -193,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,
@@ -310,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");
@@ -358,39 +373,57 @@
             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-preview", 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-preview"
+        ]);
+    }
 
-        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");
+        rename("miri", "miri-preview");
+    }
 
+    fn rust_package(&mut self, manifest: &Manifest) -> Package {
         let mut pkg = Package {
             version: self.cached_version("rust")
                          .as_ref()
@@ -400,90 +433,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-preview"),
+            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,
@@ -497,10 +522,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 {
@@ -524,15 +550,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();
 
@@ -551,89 +569,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 97bacb6..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);
         }
diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs
index 3533dcd..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"),
@@ -59,6 +58,7 @@
     ("mipsisa64r6", "mips64"),
     ("mipsisa64r6el", "mips64"),
     ("msp430", "msp430"),
+    ("nvptx64", "nvptx64"),
     ("powerpc", "powerpc"),
     ("powerpc64", "powerpc64"),
     ("powerpc64le", "powerpc64"),
@@ -166,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